Files
Multi-Rules/wp-rules.php
2026-01-06 17:58:44 +00:00

679 lines
45 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: Multi Rules
* Description: Erstellt einen anpassbaren Regelbereich mit Tabs, Shortcode [meine_regeln] sowie Styling- und Import/Export-Funktionen.
* Version: 1.2
* Author: M_Viper
* Plugin URI: https://git.viper.ipv64.net/M_Viper/Multi-Rules/releases
* Author URI: https://m-viper.de
* Tags: rules, tabs, shortcode, settings, admin, frontend, styling, import-export, responsive, accessibility
* Requires at least: 6.8
* Tested up to: 6.8
* Requires PHP: 7.4
* License: GPL2
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: multi-rules
* Support: https://t.me/M_Viper04
*/
// Sicherheit: Verhindert direkten Zugriff auf die Datei
if (!defined('ABSPATH')) {
exit;
}
// 1. Backend-Menüpunkt hinzufügen
function mrp_add_admin_menu() {
add_menu_page(
'Multi Rules Einstellungen',
'Multi Rules',
'manage_options',
'multi-rules-plugin',
'mrp_options_page_html',
'dashicons-admin-generic',
25
);
}
add_action('admin_menu', 'mrp_add_admin_menu');
// 2. Einstellungen registrieren
function mrp_settings_init() {
register_setting('mrp_plugin_page', 'mrp_settings', 'mrp_sanitize_settings');
// Sektion für den Willkommens-Tab
add_settings_section('mrp_welcome_section', 'Standard-Tab (Willkommen)', 'mrp_welcome_section_callback', 'mrp_plugin_page');
add_settings_field('mrp_welcome_tab_editor', 'Inhalt des Willkommens-Tabs', 'mrp_welcome_tab_render', 'mrp_plugin_page', 'mrp_welcome_section');
add_settings_field('mrp_welcome_tab_bg_color', 'Hintergrundfarbe des Willkommens-Tabs ', 'mrp_welcome_tab_bg_color_render', 'mrp_plugin_page', 'mrp_welcome_section');
// NEU: Schriftfarbe für den Willkommenstab
add_settings_field('mrp_welcome_tab_font_color', 'Schriftfarbe des Willkommens-Tabs', 'mrp_welcome_tab_font_color_render', 'mrp_plugin_page', 'mrp_welcome_section');
add_settings_field('mrp_show_welcome_tab', 'Anzeige', 'mrp_show_welcome_tab_render', 'mrp_plugin_page', 'mrp_welcome_section');
// Sektion für die Regeln (Inhalt)
add_settings_section('mrp_rules_section', 'Regeln und Tabs verwalten', 'mrp_rules_section_callback', 'mrp_plugin_page');
add_settings_field('mrp_repeater_field', '', 'mrp_repeater_field_render', 'mrp_plugin_page', 'mrp_rules_section');
// Sektion für das Styling (Frontend)
add_settings_section('mrp_style_section', 'Stil-Einstellungen (Frontend)', 'mrp_style_section_callback', 'mrp_plugin_page');
add_settings_field('mrp_tab_title_font_size', 'Tab-Titel: Schriftgröße', 'mrp_tab_title_font_size_render', 'mrp_plugin_page', 'mrp_style_section');
add_settings_field('mrp_tab_title_font_color', 'Tab-Titel: Schriftfarbe', 'mrp_tab_title_font_color_render', 'mrp_plugin_page', 'mrp_style_section');
add_settings_field('mrp_rule_title_font_size', 'Regel-Titel: Schriftgröße', 'mrp_rule_title_font_size_render', 'mrp_plugin_page', 'mrp_style_section');
add_settings_field('mrp_rule_title_font_color', 'Regel-Titel: Schriftfarbe', 'mrp_rule_title_font_color_render', 'mrp_plugin_page', 'mrp_style_section');
add_settings_field('mrp_rule_content_font_size', 'Regel-Text: Schriftgröße', 'mrp_rule_content_font_size_render', 'mrp_plugin_page', 'mrp_style_section');
add_settings_field('mrp_rule_content_font_color', 'Regel-Text: Schriftfarbe', 'mrp_rule_content_font_color_render', 'mrp_plugin_page', 'mrp_style_section');
// Sektion für erweiterte Funktionen
add_settings_section('mrp_advanced_section', 'Erweiterte Funktionen', 'mrp_advanced_section_callback', 'mrp_plugin_page');
add_settings_field('mrp_enable_animations', 'Animationen', 'mrp_enable_animations_render', 'mrp_plugin_page', 'mrp_advanced_section');
add_settings_field('mrp_enable_drag_drop', 'Sortierung', 'mrp_enable_drag_drop_render', 'mrp_plugin_page', 'mrp_advanced_section');
add_settings_field('mrp_show_last_updated', 'Anzeige "Zuletzt aktualisiert"', 'mrp_show_last_updated_render', 'mrp_plugin_page', 'mrp_advanced_section');
}
add_action('admin_init', 'mrp_settings_init');
// 3. Callbacks für die Sektionsbeschreibungen
function mrp_welcome_section_callback() { echo 'Bearbeiten Sie hier den Inhalt des standardmäßigen Willkommens-Tabs. Sie können diesen Tab auch vollständig ausblenden.'; }
function mrp_rules_section_callback() { echo 'Erstellen und verwalten Sie hier Ihre Tabs und die dazugehörigen Regeln.'; }
function mrp_style_section_callback() { echo 'Passen Sie das Erscheinungsbild der Regeln im Frontend an. Änderungen werden sofort angewendet.'; }
function mrp_advanced_section_callback() { echo 'Aktivieren oder deaktivieren Sie hier erweiterte Funktionen des Plugins.'; }
// Render-Funktionen für erweiterte Funktionen
function mrp_enable_animations_render() {
$options = get_option('mrp_settings');
$enabled = ($options === false || !is_array($options)) ? '1' : (isset($options['enable_animations']) ? $options['enable_animations'] : '0');
echo '<label><input type="checkbox" name="mrp_settings[enable_animations]" value="1" ' . checked(1, $enabled, false) . ' /> ' . esc_html__('Sanfte Animationen für das Auf- und Zuklappen der Regeln aktivieren.', 'multi-rules') . '</label>';
}
function mrp_enable_drag_drop_render() {
$options = get_option('mrp_settings');
$enabled = ($options === false || !is_array($options)) ? '1' : (isset($options['enable_drag_drop']) ? $options['enable_drag_drop'] : '0');
echo '<label><input type="checkbox" name="mrp_settings[enable_drag_drop]" value="1" ' . checked(1, $enabled, false) . ' /> ' . esc_html__('Drag-and-Drop zum Sortieren von Tabs und Regeln im Backend aktivieren.', 'multi-rules') . '</label>';
}
function mrp_show_last_updated_render() {
$options = get_option('mrp_settings');
$is_checked = ($options === false || !is_array($options)) ? '1' : (isset($options['show_last_updated']) ? $options['show_last_updated'] : '0');
echo '<label><input type="checkbox" name="mrp_settings[show_last_updated]" value="1" ' . checked(1, $is_checked, false) . ' ' . esc_html__('"Zuletzt aktualisiert"-Datum im Frontend anzeigen', 'multi-rules') . '</label>';
}
function mrp_show_welcome_tab_render() {
$options = get_option('mrp_settings');
if ($options === false || !is_array($options)) {
$is_checked = true;
} else {
$is_checked = isset($options['show_welcome_tab']);
}
echo '<label><input type="checkbox" name="mrp_settings[show_welcome_tab]" value="1" ' . checked($is_checked, true, false) . ' /> ' . esc_html__('Willkommens-Tab im Frontend anzeigen', 'multi-rules') . '</label>';
}
// Render-Funktion für den Willkommens-Tab
function mrp_welcome_tab_render() {
$options = get_option('mrp_settings');
$default_welcome_text = "Willkommen in unserer Community! 🎉
Es freut uns riesig, dass du den Weg zu uns gefunden hast. Damit alle hier eine tolle Zeit haben, haben wir einige einfache Regeln aufgestellt. Sie sind kein strenges Gesetz, sondern eher eine gemeinsame Vereinbarung, wie wir miteinander umgehen wollen mit Respekt, Fairness und einer guten Portion Spaß.
Nimm dir einen Moment Zeit, sie durchzulesen. Solltest du Fragen haben, zögere nicht, ein Mitglied unseres Teams oder einen Moderator anzusprechen.
Wir wünschen dir eine fantastische Zeit hier!";
$welcome_content = isset($options['welcome_tab_content']) ? $options['welcome_tab_content'] : $default_welcome_text;
echo '<br>';
$editor_id = 'mrp_welcome_tab_editor';
$settings = array(
'textarea_name' => 'mrp_settings[welcome_tab_content]',
'media_buttons' => true,
'textarea_rows' => 15,
'teeny' => true,
);
wp_editor($welcome_content, $editor_id, $settings);
}
function mrp_welcome_tab_bg_color_render() {
$options = get_option('mrp_settings');
$bg_color = isset($options['welcome_tab_bg_color']) ? $options['welcome_tab_bg_color'] : '#f0f0f0';
echo "<input type='color' name='mrp_settings[welcome_tab_bg_color]' value='" . esc_attr($bg_color) . "'>";
echo "<p class='description'>" . esc_html__('Wählen Sie eine Hintergrundfarbe. Diese wird automatisch mit 50% Transparenz im Frontend angezeigt.', 'multi-rules') . "</p>";
}
// NEU: Render-Funktion für die Schriftfarbe des Willkommen-Tabs
function mrp_welcome_tab_font_color_render() {
$options = get_option('mrp_settings');
$font_color = isset($options['welcome_tab_font_color']) ? $options['welcome_tab_font_color'] : '#6c757d'; // Standard Grau
echo "<input type='color' name='mrp_settings[welcome_tab_font_color]' value='" . esc_attr($font_color) . "'>";
echo "<p class='description'>" . esc_html__('Wählen Sie die Schriftfarbe für den Willkommen-Text.', 'multi-rules') . "</p>";
}
// 4. Render-Funktionen für die Styling-Felder
function mrp_tab_title_font_size_render() {
$options = get_option('mrp_settings'); $font_size = isset($options['tab_title_font_size']) ? $options['tab_title_font_size'] : '15';
echo "<input type='number' name='mrp_settings[tab_title_font_size]' value='" . esc_attr($font_size) . "' min='10' max='30' style='width: 70px;'> px";
}
function mrp_tab_title_font_color_render() {
$options = get_option('mrp_settings'); $font_color = isset($options['tab_title_font_color']) ? $options['tab_title_font_color'] : '#2c3e50';
echo "<input type='color' name='mrp_settings[tab_title_font_color]' value='" . esc_attr($font_color) . "'>";
}
function mrp_rule_title_font_size_render() {
$options = get_option('mrp_settings'); $font_size = isset($options['rule_title_font_size']) ? $options['rule_title_font_size'] : '16';
echo "<input type='number' name='mrp_settings[rule_title_font_size]' value='" . esc_attr($font_size) . "' min='10' max='30' style='width: 70px;'> px";
}
function mrp_rule_title_font_color_render() {
$options = get_option('mrp_settings'); $font_color = isset($options['rule_title_font_color']) ? $options['rule_title_font_color'] : '#2c3e50';
echo "<input type='color' name='mrp_settings[rule_title_font_color]' value='" . esc_attr($font_color) . "'>";
}
function mrp_rule_content_font_size_render() {
$options = get_option('mrp_settings'); $font_size = isset($options['rule_content_font_size']) ? $options['rule_content_font_size'] : '15';
echo "<input type='number' name='mrp_settings[rule_content_font_size]' value='" . esc_attr($font_size) . "' min='10' max='30' style='width: 70px;'> px";
}
function mrp_rule_content_font_color_render() {
$options = get_option('mrp_settings'); $font_color = isset($options['rule_content_font_color']) ? $options['rule_content_font_color'] : '#6c757d';
echo "<input type='color' name='mrp_settings[rule_content_font_color]' value='" . esc_attr($font_color) . "'>";
}
if (!function_exists('hex_to_rgba')) {
function hex_to_rgba($hex, $alpha) {
$hex = str_replace("#", "", $hex);
if (strlen($hex) == 3) {
$r = hexdec(substr($hex, 0, 1).substr($hex, 0, 1));
$g = hexdec(substr($hex, 1, 1).substr($hex, 1, 1));
$b = hexdec(substr($hex, 2, 1).substr($hex, 2, 1));
} else {
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
}
return "rgba({$r}, {$g}, {$b}, {$alpha})";
}
}
// 5. HTML für die Einstellungsseite
function mrp_options_page_html() {
if (!current_user_can('manage_options')) return;
$options = get_option('mrp_settings');
$enable_drag_drop = isset($options['enable_drag_drop']) ? $options['enable_drag_drop'] : '0';
if ($enable_drag_drop === '1') {
wp_enqueue_script('jquery-ui-sortable');
}
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<form action="options.php" method="post" id="mrp-settings-form">
<?php settings_fields('mrp_plugin_page'); ?>
<div class="mrp-two-column-container">
<div class="mrp-column">
<div class="postbox">
<h2 class="hndle" style="padding: 8px 12px; font-size: 14px;"><?php esc_html_e('Erweiterte Funktionen', 'multi-rules'); ?></h2>
<div class="inside">
<table class="form-table" role="presentation">
<tbody><?php do_settings_fields('mrp_plugin_page', 'mrp_advanced_section'); ?></tbody>
</table>
</div>
</div>
</div>
<div class="mrp-column">
<div class="postbox">
<h2 class="hndle" style="padding: 8px 12px; font-size: 14px;"><?php esc_html_e('Stil-Einstellungen (Frontend)', 'multi-rules'); ?></h2>
<div class="inside">
<div class="mrp-style-settings">
<div class="mrp-style-row">
<div class="mrp-style-field">
<label><?php esc_html_e('Tab-Titel: Schriftgröße', 'multi-rules'); ?></label>
<?php mrp_tab_title_font_size_render(); ?>
</div>
<div class="mrp-style-field">
<label><?php esc_html_e('Tab-Titel: Schriftfarbe', 'multi-rules'); ?></label>
<?php mrp_tab_title_font_color_render(); ?>
</div>
</div>
<div class="mrp-style-row">
<div class="mrp-style-field">
<label><?php esc_html_e('Regel-Titel: Schriftgröße', 'multi-rules'); ?></label>
<?php mrp_rule_title_font_size_render(); ?>
</div>
<div class="mrp-style-field">
<label><?php esc_html_e('Regel-Titel: Schriftfarbe', 'multi-rules'); ?></label>
<?php mrp_rule_title_font_color_render(); ?>
</div>
</div>
<div class="mrp-style-row">
<div class="mrp-style-field">
<label><?php esc_html_e('Regel-Text: Schriftgröße', 'multi-rules'); ?></label>
<?php mrp_rule_content_font_size_render(); ?>
</div>
<div class="mrp-style-field">
<label><?php esc_html_e('Regel-Text: Schriftfarbe', 'multi-rules'); ?></label>
<?php mrp_rule_content_font_color_render(); ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="postbox">
<h2 class="hndle" style="padding: 8px 12px; font-size: 14px;"><?php esc_html_e('Standard-Tab (Willkommen)', 'multi-rules'); ?></h2>
<div class="inside">
<?php do_settings_fields('mrp_plugin_page', 'mrp_welcome_section'); ?>
</div>
</div>
<div class="postbox">
<h2 class="hndle" style="padding: 8px 12px; font-size: 14px;"><?php esc_html_e('Regeln und Tabs verwalten', 'multi-rules'); ?></h2>
<div class="inside">
<div id="mrp-repeater-wrapper">
<div id="tabs-container">
<?php $tabs = isset($options['tabs']) ? $options['tabs'] : array(); ?>
<?php if (!empty($tabs)) : ?>
<?php foreach ($tabs as $tab_index => $tab) : ?>
<div class="backend-tab-card" data-index="<?php echo esc_attr($tab_index); ?>">
<div class="backend-tab-header">
<h3><span class="dashicons dashicons-menu drag-handle"></span> <span class="dashicons dashicons-category"></span> <?php echo esc_html($tab['title'] ?: 'Unbenannter Tab'); ?></h3>
<div class="header-actions">
<button type="button" class="button toggle-collapse">Umschalten</button>
<button type="button" class="button button-link-delete remove-tab">Löschen</button>
</div>
</div>
<div class="backend-tab-content">
<p><label>Tab-Titel (z.B. Minecraft)</label><input type="text" name="mrp_settings[tabs][<?php echo esc_attr($tab_index); ?>][title]" value="<?php echo esc_attr($tab['title']); ?>" class="regular-text"></p>
<h4>Regeln für diesen Tab</h4>
<div class="rules-container">
<?php if (!empty($tab['rules'])) : ?>
<?php foreach ($tab['rules'] as $rule_index => $rule) : ?>
<div class="backend-rule-card" data-rule-index="<?php echo esc_attr($rule_index); ?>">
<div class="backend-rule-header">
<span class="dashicons dashicons-menu drag-handle"></span>
<strong><?php echo esc_html($rule['rule_title'] ?: 'Unbenannte Regel'); ?></strong>
<button type="button" class="button button-link-delete remove-rule">Regel entfernen</button>
</div>
<div class="backend-rule-content">
<p><label>Regel-Titel</label><input type="text" name="mrp_settings[tabs][<?php echo esc_attr($tab_index); ?>][rules][<?php echo esc_attr($rule_index); ?>][rule_title]" value="<?php echo esc_attr($rule['rule_title']); ?>" class="regular-text"></p>
<p><label>Regel-Text</label><textarea name="mrp_settings[tabs][<?php echo esc_attr($tab_index); ?>][rules][<?php echo esc_attr($rule_index); ?>][rule_content]" rows="4" class="large-text"><?php echo esc_textarea($rule['rule_content']); ?></textarea></p>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<button type="button" class="button add-rule">+ Neue Regel hinzufügen</button>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<p style="margin-top: 20px;"><button type="button" id="add-tab" class="button button-primary button-hero">+ Neuen Tab hinzufügen</button></p>
</div>
</div>
</div>
<div class="postbox">
<h2 class="hndle" style="padding: 8px 12px; font-size: 14px;"><?php esc_html_e('Import/Export', 'multi-rules'); ?></h2>
<div class="inside">
<p><?php esc_html_e('Hier können Sie Ihre Einstellungen und Regeln exportieren, um sie zu sichern oder auf einer anderen Seite zu importieren.', 'multi-rules'); ?></p>
<p>
<button type="button" id="mrp-export-button" class="button button-secondary"><?php esc_html_e('Einstellungen exportieren', 'multi-rules'); ?></button>
</p>
<p>
<label for="mrp-import-file"><?php esc_html_e('Einstellungen importieren:', 'multi-rules'); ?></label>
<input type="file" id="mrp-import-file" name="mrp-import-file" accept=".json">
<button type="button" id="mrp-import-button" class="button button-secondary"><?php esc_html_e('Importieren', 'multi-rules'); ?></button>
</p>
</div>
</div>
<?php submit_button('Alle Änderungen speichern', 'primary large', 'submit', true); ?>
</form>
</div>
<style>
/* CSS für den Backend-Repeater */
#mrp-repeater-wrapper{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif}.backend-tab-card{background:#fff;border:1px solid #c3c4c7;border-radius:8px;margin-bottom:20px;box-shadow:0 1px 1px rgba(0,0,0,.04)}.backend-tab-header{display:flex;justify-content:space-between;align-items:center;padding:12px 15px;background:#f8f9f9;border-bottom:1px solid #c3c4c7;border-radius:8px 8px 0 0;cursor:pointer}.backend-tab-header h3{margin:0;font-size:1.2em;display:flex;align-items:center}.backend-tab-header h3 .dashicons{margin-right:10px;color:#50575e}.backend-tab-content{padding:20px;display:none}.backend-tab-card.collapsed .backend-tab-content{display:none}.backend-tab-card:not(.collapsed) .backend-tab-content{display:block}.backend-rule-card{background:#fcfcfc;border:1px dashed #dcdcde;border-radius:5px;margin-bottom:15px}.backend-rule-header{display:flex;justify-content:space-between;align-items:center;padding:10px 15px;background:#f6f7f7;border-bottom:1px dashed #dcdcde;cursor:pointer}.backend-rule-content{padding:15px;display:none}.backend-rule-card.collapsed .backend-rule-content{display:none}.backend-rule-card:not(.collapsed) .backend-rule-content{display:block}.header-actions{display:flex;gap:10px}#mrp-repeater-wrapper p label{display:block;font-weight:600;margin-bottom:5px;color:#1e1e1e}#mrp-repeater-wrapper .button-primary{background-color:#0065cc;border-color:#0065cc}#mrp-repeater-wrapper .button-primary:hover{background-color:#0053a6;border-color:#0053a6}#mrp-repeater-wrapper .button-hero{font-size:14px;height:46px;line-height:44px;padding:0 36px}
/* CSS für Drag-and-Drop */
.drag-handle { cursor: move; color: #8c8f94; margin-right: 10px; }
.ui-sortable-helper { background-color: #f9f9f9; opacity: 0.8; }
.rules-container.ui-sortable { min-height: 50px; border: 1px dashed transparent; }
.rules-container.ui-sortable-placeholder { border: 1px dashed #ccc; background: #f0f0f0; border-radius: 5px; margin: 0 0 15px 0; }
/* CSS für nebeneinander liegende Boxen */
.mrp-two-column-container { display: flex; gap: 20px; margin-top: 20px; }
.mrp-column { flex: 1; }
/* CSS für kompakte Stil-Einstellungen */
.mrp-style-settings { display: flex; flex-direction: column; gap: 15px; }
.mrp-style-row { display: flex; gap: 20px; }
.mrp-style-field { flex: 1; }
.mrp-style-field label { display: block; font-weight: 600; margin-bottom: 5px; }
@media screen and (max-width: 1024px) { .mrp-two-column-container { flex-direction: column; } }
@media screen and (max-width: 768px) { .mrp-style-row { flex-direction: column; gap: 10px; } }
</style>
<script>
jQuery(document).ready(function($) {
var tabCount = $('.backend-tab-card').length;
var $tabsContainer = $('#tabs-container');
var $form = $('#mrp-settings-form');
var enableDragDrop = $('input[name="mrp_settings[enable_drag_drop]"]').is(':checked');
$tabsContainer.find('.backend-tab-card').addClass('collapsed');
$('#add-tab').click(function() {
var template = $('#tab-template').html().replace(/INDEX/g, tabCount);
$tabsContainer.append(template);
if (enableDragDrop) initializeSortable();
tabCount++;
});
$(document).on('click', '.add-rule', function(e) {
e.stopPropagation();
var $tabCard = $(this).closest('.backend-tab-card');
var tabIndex = $tabCard.data('index');
var ruleCount = $tabCard.find('.backend-rule-card').length;
var template = $('#rule-template').html().replace(/TAB_INDEX/g, tabIndex).replace(/RULE_INDEX/g, ruleCount);
$tabCard.find('.rules-container').append(template);
if (enableDragDrop) initializeSortable();
});
$(document).on('click', '.backend-tab-header, .toggle-collapse', function(e) {
e.stopPropagation();
$(this).closest('.backend-tab-card').toggleClass('collapsed');
});
$(document).on('click', '.backend-rule-header', function(e) {
e.stopPropagation();
$(this).closest('.backend-rule-card').toggleClass('collapsed');
});
$(document).on('click', '.remove-tab', function(e) {
e.stopPropagation();
if (confirm('Möchten Sie diesen Tab und alle seine Regeln wirklich entfernen?')) {
$(this).closest('.backend-tab-card').remove();
}
});
$(document).on('click', '.remove-rule', function(e) {
e.stopPropagation();
$(this).closest('.backend-rule-card').remove();
});
function initializeSortable() {
if (!enableDragDrop) return;
$tabsContainer.sortable({ handle: '.backend-tab-header .drag-handle', placeholder: 'ui-sortable-placeholder', stop: function(event, ui) { reindexTabs(); } });
$('.rules-container').sortable({ handle: '.backend-rule-header .drag-handle', placeholder: 'ui-sortable-placeholder', stop: function(event, ui) { reindexRules($(this)); } });
}
if (enableDragDrop) initializeSortable();
function reindexTabs() {
$tabsContainer.find('.backend-tab-card').each(function(i) {
var $card = $(this);
var newIndex = i;
$card.attr('data-index', newIndex);
$card.find('input, textarea').each(function() {
var name = $(this).attr('name');
var newName = name.replace(/tabs\[\d+\]/, 'tabs[' + newIndex + ']');
$(this).attr('name', newName);
});
});
}
function reindexRules($rulesContainer) {
$rulesContainer.find('.backend-rule-card').each(function(i) {
var $card = $(this);
var newIndex = i;
var $tabCard = $rulesContainer.closest('.backend-tab-card');
var tabIndex = $tabCard.data('index');
$card.find('input, textarea').each(function() {
var name = $(this).attr('name');
var newName = name.replace(/rules\[\d+\]/, 'rules[' + newIndex + ']');
$(this).attr('name', newName);
});
});
}
$('#mrp-export-button').on('click', function() {
var nonce = $('#mrp-settings-form input[name="_wpnonce"]').val();
$.post(ajaxurl, { action: 'mrp_export_settings', _wpnonce: nonce }, function(response) {
if (response.success) {
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(response.data, null, 2));
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", "regeln-plugin-export.json");
document.body.appendChild(downloadAnchorNode);
downloadAnchorNode.click();
downloadAnchorNode.remove();
} else { alert('Export fehlgeschlagen: ' + response.data); }
});
});
$('#mrp-import-button').on('click', function() {
var fileInput = document.getElementById('mrp-import-file');
if (!fileInput.files.length) { alert('Bitte wählen Sie eine Datei zum Importieren aus.'); return; }
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function(e) {
try {
var importedData = JSON.parse(e.target.result);
var nonce = $('#mrp-settings-form input[name="_wpnonce"]').val();
$.post(ajaxurl, { action: 'mrp_import_settings', _wpnonce: nonce, data: JSON.stringify(importedData) }, function(response) {
if (response.success) { alert('Einstellungen erfolgreich importiert! Die Seite wird neu geladen.'); location.reload(); } else { alert('Import fehlgeschlagen: ' + response.data); }
});
} catch (error) { alert('Fehler beim Lesen der JSON-Datei.'); }
};
reader.readAsText(file);
});
});
</script>
<template id="tab-template"><div class="backend-tab-card" data-index="INDEX"><div class="backend-tab-header"><h3><span class="dashicons dashicons-menu drag-handle"></span> <span class="dashicons dashicons-category"></span> Neuer Tab</h3><div class="header-actions"><button type="button" class="button toggle-collapse">Umschalten</button><button type="button" class="button button-link-delete remove-tab">Löschen</button></div></div><div class="backend-tab-content"><p><label>Tab-Titel (z.B. Minecraft)</label><input type="text" name="mrp_settings[tabs][INDEX][title]" value="" class="regular-text"></p><h4>Regeln für diesen Tab</h4><div class="rules-container"></div><button type="button" class="button add-rule">+ Neue Regel hinzufügen</button></div></div></template>
<template id="rule-template"><div class="backend-rule-card" data-rule-index="RULE_INDEX"><div class="backend-rule-header"><span class="dashicons dashicons-menu drag-handle"></span><strong>Neue Regel</strong><button type="button" class="button button-link-delete remove-rule">Regel entfernen</button></div><div class="backend-rule-content"><p><label>Regel-Titel</label><input type="text" name="mrp_settings[tabs][TAB_INDEX][rules][RULE_INDEX][rule_title]" value="" class="regular-text"></p><p><label>Regel-Text</label><textarea name="mrp_settings[tabs][TAB_INDEX][rules][RULE_INDEX][rule_content]" rows="4" class="large-text"></textarea></p></div></div></template>
<?php
}
function mrp_repeater_field_render() {}
add_action('wp_ajax_mrp_export_settings', 'mrp_ajax_export_settings');
add_action('wp_ajax_mrp_import_settings', 'mrp_ajax_import_settings');
function mrp_ajax_export_settings() {
check_ajax_referer('mrp_plugin_page-options', '_wpnonce');
if (!current_user_can('manage_options')) wp_die();
$settings = get_option('mrp_settings');
wp_send_json_success($settings);
}
function mrp_ajax_import_settings() {
check_ajax_referer('mrp_plugin_page-options', '_wpnonce');
if (!current_user_can('manage_options')) wp_die();
if ( ! isset( $_POST['data'] ) ) wp_send_json_error( 'Keine Daten empfangen.' );
$raw_data = wp_unslash( $_POST['data'] );
$imported_data = json_decode( $raw_data, true );
if ( is_array( $imported_data ) ) { update_option('mrp_settings', $imported_data); wp_send_json_success(); } else { wp_send_json_error('Ungültiges JSON-Format.'); }
}
add_filter('pre_update_option_mrp_settings', 'mrp_add_last_updated_timestamp', 10, 2);
function mrp_add_last_updated_timestamp($new_value, $old_value) {
if ( is_array( $new_value ) ) { $new_value['last_updated'] = current_time('timestamp'); }
return $new_value;
}
// 6. Shortcode für die Frontend-Anzeige
function mrp_display_rules_shortcode($atts) {
$options = get_option('mrp_settings');
$tabs = isset($options['tabs']) ? $options['tabs'] : array();
if ($options === false || !is_array($options)) { $show_welcome_tab = true; } else { $show_welcome_tab = isset($options['show_welcome_tab']); }
$show_last_updated = isset($options['show_last_updated']) ? $options['show_last_updated'] : '0';
$enable_animations = isset($options['enable_animations']) ? $options['enable_animations'] : '0';
if (empty($tabs) && !$show_welcome_tab) { return '<p style="text-align:center; padding: 40px; color: #666;">' . esc_html__('Keine Regeln wurden im Backend konfiguriert.', 'multi-rules') . '</p>'; }
wp_enqueue_style('mrp-frontend-style', plugin_dir_url(__FILE__) . 'style.css', array(), '8.0');
wp_enqueue_script('mrp-frontend-script', plugin_dir_url(__FILE__) . 'script.js', array('jquery'), '8.0', true);
wp_localize_script('mrp-frontend-script', 'mrp_frontend_vars', [ 'enable_animations' => $enable_animations ]);
ob_start();
$last_updated_html = '';
if ($show_last_updated && isset($options['last_updated']) && is_numeric($options['last_updated'])) {
$last_updated_timestamp = $options['last_updated'];
$date_format = sanitize_text_field( get_option('date_format') );
$formatted_date = date_i18n( $date_format, $last_updated_timestamp );
/* translators: %s: Formatted date. */
$last_updated_html = '<p class="mrp-last-updated">' . sprintf(esc_html__('Zuletzt aktualisiert am: %s', 'multi-rules'), esc_html($formatted_date)) . '</p>';
}
?>
<style id="mrp-custom-inline-styles">
.regel-plugin-container .regel-tab-button {
<?php if (!empty($options['tab_title_font_size'])): ?>font-size: <?php echo intval($options['tab_title_font_size']); ?>px !important;<?php endif; ?>
<?php if (!empty($options['tab_title_font_color'])): ?>color: <?php echo esc_attr($options['tab_title_font_color']); ?> !important;<?php endif; ?>
}
.regel-plugin-container .regel-title-text {
<?php if (!empty($options['rule_title_font_size'])): ?>font-size: <?php echo intval($options['rule_title_font_size']); ?>px !important;<?php endif; ?>
<?php if (!empty($options['rule_title_font_color'])): ?>color: <?php echo esc_attr($options['rule_title_font_color']); ?> !important;<?php endif; ?>
}
.regel-plugin-container .regel-item .regel-content .regel-content-inner, .regel-plugin-container .regel-item .regel-content .regel-content-inner p {
<?php if (!empty($options['rule_content_font_size'])): ?>font-size: <?php echo intval($options['rule_content_font_size']); ?>px !important;<?php endif; ?>
<?php if (!empty($options['rule_content_font_color'])): ?>color: <?php echo esc_attr($options['rule_content_font_color']); ?> !important;<?php endif; ?>
}
.regel-plugin-container .regel-item:nth-child(even) { background-color: #f5f5f5 !important; border-radius: 5px; }
<?php if ($show_welcome_tab): ?>
#tab-welcome {
background-color: <?php echo esc_attr(hex_to_rgba($options['welcome_tab_bg_color'] ?? '#f0f0f0', 0.4)); ?> !important;
padding: 15px;
border-radius: 5px;
/* NEU: Nutzt die spezifische Farbe für den Willkommenstab */
color: <?php echo esc_attr($options['welcome_tab_font_color'] ?? '#6c757d'); ?> !important;
}
/* Zusätzliche Sicherheit: Überschreibt auch die Farbe von Absätzen im Willkommen-Tab */
#tab-welcome p, #tab-welcome li, #tab-welcome h1, #tab-welcome h2, #tab-welcome h3, #tab-welcome ul, #tab-welcome ol {
color: inherit !important;
}
<?php endif; ?>
.mrp-last-updated {
text-align: left;
padding-left: 550px;
font-size: 0.9em;
color: #aaaaaacc;
margin-top: 20px;
font-style: italic;
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.9), -1px -1px 2px rgba(0, 0, 0, 0.6);
}
</style>
<div class="regel-plugin-container">
<div class="regel-tabs-nav">
<?php
$nav_buttons_html = '';
$is_first_tab = true;
if ($show_welcome_tab) { $nav_buttons_html .= '<button class="regel-tab-button active" data-tab="tab-welcome">' . esc_html__('Willkommen', 'multi-rules') . '</button>'; $is_first_tab = false; }
if (!empty($tabs)) { foreach ($tabs as $index => $tab) { $active_class = $is_first_tab ? 'active' : ''; $nav_buttons_html .= '<button class="regel-tab-button ' . esc_attr($active_class) . '" data-tab="tab-' . esc_attr($index) . '">' . esc_html($tab['title']) . '</button>'; $is_first_tab = false; } }
echo wp_kses_post($nav_buttons_html);
?>
</div>
<div class="regel-tabs-content">
<?php $first_panel = true;
if ($show_welcome_tab) { $welcome_content = $options['welcome_tab_content'] ?? ''; ?>
<div id="tab-welcome" class="regel-tab-panel active"><div class="regel-content-inner"><?php echo wp_kses_post(wpautop($welcome_content)); ?></div></div>
<?php $first_panel = false;
}
foreach ($tabs as $index => $tab): ?>
<div id="tab-<?php echo esc_attr($index); ?>" class="regel-tab-panel <?php echo $first_panel ? 'active' : ''; ?>">
<?php if (!empty($tab['rules'])): foreach ($tab['rules'] as $rule): ?>
<div class="regel-item">
<button class="regel-toggle">
<span class="regel-icon icon-plus">+</span>
<span class="regel-icon icon-minus"></span>
<span class="regel-title-text"><?php echo esc_html($rule['rule_title']); ?></span>
</button>
<div class="regel-content">
<div class="regel-content-inner"><?php echo wp_kses_post(wpautop($rule['rule_content'])); ?></div>
</div>
</div>
<?php endforeach; else: ?>
<p style="text-align:center; padding: 20px; color: #888;"><?php esc_html_e('Für diesen Tab wurden noch keine Regeln erstellt.', 'multi-rules'); ?></p>
<?php endif; ?>
</div>
<?php $first_panel = false; endforeach; ?>
</div>
<?php echo wp_kses_post($last_updated_html); ?>
</div>
<?php
return ob_get_clean();
}
add_shortcode('meine_regeln', 'mrp_display_rules_shortcode');
add_action('wp_enqueue_scripts', function() {
$frontend_css = "
.regel-plugin-container{width:100%;margin:20px 0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif}.regel-plugin-container .regel-tabs-nav{border-bottom:1px solid #ddd;display:flex;margin-bottom:20px}.regel-plugin-container .regel-tab-button{background:none;border:none;padding:10px 20px;cursor:pointer;border-bottom:2px solid transparent;transition:all 0.2s ease-in-out;font-weight:500}.regel-plugin-container .regel-tab-button:hover{border-bottom-color:#ccc}.regel-plugin-container .regel-tab-button.active{border-bottom-color:#0073aa}.regel-plugin-container .regel-tabs-content{background:#fff;padding:20px;border-radius:5px;border:1px solid #ddd}.regel-plugin-container .regel-tab-panel{display:none}.regel-plugin-container .regel-tab-panel.active{display:block}.regel-plugin-container .regel-item{border-bottom:1px solid #eee;padding:15px 0}.regel-plugin-container .regel-item:last-child{border-bottom:none}.regel-plugin-container .regel-toggle{width:100%;text-align:left;background:none;border:none;padding:0;cursor:pointer;font-weight:600;display:flex;align-items:center;justify-content:space-between}.regel-plugin-container .regel-toggle .regel-icon{font-size:20px;margin-right:10px;transition:transform 0.2s ease-in-out}.regel-plugin-container .regel-toggle .icon-minus{display:none}.regel-plugin-container .regel-toggle.active .icon-plus{display:none}.regel-plugin-container .regel-toggle.active .icon-minus{display:inline-block}.regel-plugin-container .regel-content{margin-top:10px;padding-left:30px;display:none;overflow:hidden}.regel-plugin-container .regel-content.active{display:block}
";
wp_add_inline_style('mrp-frontend-style', $frontend_css);
$frontend_js = "
jQuery(document).ready(function($) {
var enableAnimations = mrp_frontend_vars.enable_animations === '1';
$('.regel-plugin-container').on('click', '.regel-tab-button', function() {
var targetTab = $(this).data('tab');
$('.regel-tab-button').removeClass('active');
$('.regel-tab-panel').removeClass('active');
$(this).addClass('active');
$('#' + targetTab).addClass('active');
});
$('.regel-plugin-container').on('click', '.regel-toggle', function() {
var $content = $(this).next('.regel-content');
var $toggle = $(this);
if (enableAnimations) { $content.slideToggle(300); } else { $content.toggle(); }
$toggle.toggleClass('active');
});
});
";
wp_add_inline_script('mrp-frontend-script', $frontend_js);
});
function mrp_sanitize_settings( $input ) {
$sanitized_options = array();
if ( ! is_array( $input ) ) return $sanitized_options;
$sanitized_options['show_welcome_tab'] = isset( $input['show_welcome_tab'] ) ? 1 : 0;
$sanitized_options['enable_animations'] = isset( $input['enable_animations'] ) ? 1 : 0;
$sanitized_options['enable_drag_drop'] = isset( $input['enable_drag_drop'] ) ? 1 : 0;
$sanitized_options['show_last_updated'] = isset( $input['show_last_updated'] ) ? 1 : 0;
if ( isset( $input['welcome_tab_content'] ) ) $sanitized_options['welcome_tab_content'] = wp_kses_post( $input['welcome_tab_content'] );
if ( isset( $input['welcome_tab_bg_color'] ) ) $sanitized_options['welcome_tab_bg_color'] = sanitize_hex_color( $input['welcome_tab_bg_color'] );
// NEU: Sanitize für Willkommens-Schriftfarbe
if ( isset( $input['welcome_tab_font_color'] ) ) $sanitized_options['welcome_tab_font_color'] = sanitize_hex_color( $input['welcome_tab_font_color'] );
$sanitized_options['tab_title_font_size'] = isset( $input['tab_title_font_size'] ) ? absint( $input['tab_title_font_size'] ) : 15;
$sanitized_options['tab_title_font_color'] = isset( $input['tab_title_font_color'] ) ? sanitize_hex_color( $input['tab_title_font_color'] ) : '#2c3e50';
$sanitized_options['rule_title_font_size'] = isset( $input['rule_title_font_size'] ) ? absint( $input['rule_title_font_size'] ) : 16;
$sanitized_options['rule_title_font_color'] = isset( $input['rule_title_font_color'] ) ? sanitize_hex_color( $input['rule_title_font_color'] ) : '#2c3e50';
$sanitized_options['rule_content_font_size'] = isset( $input['rule_content_font_size'] ) ? absint( $input['rule_content_font_size'] ) : 15;
$sanitized_options['rule_content_font_color'] = isset( $input['rule_content_font_color'] ) ? sanitize_hex_color( $input['rule_content_font_color'] ) : '#6c757d';
if ( isset( $input['tabs'] ) && is_array( $input['tabs'] ) ) {
$sanitized_options['tabs'] = array();
foreach ( $input['tabs'] as $tab ) {
if ( isset( $tab['title'] ) ) {
$sanitized_tab = array();
$sanitized_tab['title'] = sanitize_text_field( $tab['title'] );
if ( isset( $tab['rules'] ) && is_array( $tab['rules'] ) ) {
$sanitized_tab['rules'] = array();
foreach ( $tab['rules'] as $rule ) {
$sanitized_rule = array();
if ( isset( $rule['rule_title'] ) ) $sanitized_rule['rule_title'] = sanitize_text_field( $rule['rule_title'] );
if ( isset( $rule['rule_content'] ) ) $sanitized_rule['rule_content'] = wp_kses_post( $rule['rule_content'] );
$sanitized_tab['rules'][] = $sanitized_rule;
}
}
$sanitized_options['tabs'][] = $sanitized_tab;
}
}
}
return $sanitized_options;
}