Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90f388f49c | ||
|
|
05a2e1c7b6 | ||
|
|
cfcbcd5b02 | ||
|
|
96d4c07cc6 | ||
|
|
7b58dea6ff | ||
|
|
778563d991 | ||
|
|
d332fac418 |
@@ -31,6 +31,9 @@
|
||||
- Statistik-Widget mit Shortcode `[statistik_manager]`
|
||||
- Anpassbares Banner mit Position, Farbe und Icon
|
||||
|
||||
- **Gast Autoren:**
|
||||
- Alphabetisches Index für Gast Autoren mit Shortcode `[guest_authors]`
|
||||
|
||||
- **Admin-Tools:**
|
||||
- Dashboard-Widget für Plugin-Updates (mit Pre-Release-Unterstützung)
|
||||
- Pinnwand für Administratoren
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/* Allgemeines Styling für die Admin-Seite */
|
||||
.wrap {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.wrap h1 {
|
||||
font-size: 28px;
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
/* Blaues Banner hinter dem Logo */
|
||||
.statistik-manager-logo {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
background: linear-gradient(135deg, #0073aa, #00c6ff); /* Blaues Farbverlauf-Banner */
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Logo im Banner */
|
||||
.statistik-manager-logo img {
|
||||
max-width: 200px;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
/* Container, der die Statistikoptionen und die Werbung nebeneinander anordnet */
|
||||
.statistik-manager-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 30px;
|
||||
align-items: stretch; /* Stellt sicher, dass beide Boxen die gleiche Höhe haben */
|
||||
}
|
||||
|
||||
/* Linke Spalte – Statistik-Einstellungen (größerer Bereich) */
|
||||
.statistik-manager-settings {
|
||||
flex: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Titel in der Auswahlbox "Statistiken anzeigen" */
|
||||
.statistik-manager-settings h2 {
|
||||
font-size: 22px;
|
||||
color: #0073aa;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 2px solid #0073aa;
|
||||
}
|
||||
|
||||
/* Rechte Spalte – Werbung für weitere Plugins (kleinerer Bereich) */
|
||||
.statistik-manager-advertisement {
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
height: fit-content;
|
||||
margin-top: 80px; /* Größerer Abstand nach oben */
|
||||
}
|
||||
|
||||
/* Werbung – Überschrift */
|
||||
.statistik-manager-advertisement h2 {
|
||||
font-size: 20px;
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Werbung – Liste */
|
||||
.statistik-manager-advertisement ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.statistik-manager-advertisement ul li {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.statistik-manager-advertisement ul li a {
|
||||
font-size: 16px;
|
||||
color: #0073aa;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease, transform 0.3s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.statistik-manager-advertisement ul li a:hover {
|
||||
color: #005177;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
/* Formular-Tabelle für die Einstellungen */
|
||||
.form-table {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
padding: 25px 35px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.form-table th {
|
||||
font-size: 16px;
|
||||
color: #444;
|
||||
padding-bottom: 15px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.form-table td {
|
||||
font-size: 15px;
|
||||
color: #666;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* Submit-Button */
|
||||
button.submit, .submit {
|
||||
font-size: 12px; /* Kleinere Schriftgröße */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Zusätzlicher Abstand nach links für den Text in der Tabellenüberschrift */
|
||||
.form-table th {
|
||||
padding-left: 30px; /* Erhöht den Abstand nach links */
|
||||
}
|
||||
|
||||
.statistik-manager-banner {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.statistik-manager-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px; /* Abstand zwischen den Boxen */
|
||||
}
|
||||
|
||||
.statistik-manager-plugins,
|
||||
.statistik-manager-advertisement {
|
||||
background-color: #f5f5f5;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.statistik-manager-plugins h3,
|
||||
.statistik-manager-advertisement h3 {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.statistik-manager-plugins ul {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.statistik-manager-plugins ul li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.statistik-manager-plugins ul li a {
|
||||
text-decoration: none;
|
||||
color: #0073aa;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.statistik-manager-plugins ul li a:hover {
|
||||
color: #005077;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 372 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 641 KiB |
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Admin-Panel-Banner & Plugin-Links
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Admin - Panel Banner
|
||||
*/
|
||||
|
||||
|
||||
// Anzahl Tage, die das Banner nach dem Schließen ausgeblendet bleibt
|
||||
if (!defined('WP_MULTI_BANNER_DAYS')) {
|
||||
define('WP_MULTI_BANNER_DAYS', 7);
|
||||
}
|
||||
|
||||
// Prüft, ob das Banner für den aktuellen Benutzer noch ausgeblendet ist
|
||||
function wp_multi_banner_is_dismissed() {
|
||||
$ts = (int) get_user_meta(get_current_user_id(), 'wp_multi_banner_dismissed', true);
|
||||
return $ts > 0 && (time() - $ts) < (WP_MULTI_BANNER_DAYS * DAY_IN_SECONDS);
|
||||
}
|
||||
|
||||
// Admin-Banner als Notice mit Blauem Hintergrund (#0073aa)
|
||||
function wp_multi_add_warning_banner() {
|
||||
// Nach dem Schließen für WP_MULTI_BANNER_DAYS Tage nicht mehr anzeigen
|
||||
if (wp_multi_banner_is_dismissed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verwende printf für bessere Lesbarkeit und Übersetzbarkeit
|
||||
printf(
|
||||
'<div class="notice notice-warning is-dismissible wp-multi-feedback-notice" data-wpm-nonce="%s" style="background-color: #0073aa; color: white; border-left: 4px solid #005177;">
|
||||
<p><strong>%s</strong> %s <a href="%s" target="_blank" style="color: #FFDD00; text-decoration: none;">%s</a> %s</p>
|
||||
<p><strong>%s:</strong> %s <a href="%s" target="_blank" style="color: #FFDD00; text-decoration: none;">%s</a> %s <a href="%s" target="_blank" style="color: #FFDD00; text-decoration: none;">%s</a> %s</p>
|
||||
</div>',
|
||||
esc_attr(wp_create_nonce('wp_multi_dismiss_banner')),
|
||||
esc_html__('Danke, dass du WP Multi verwendest!', 'wp-multi'),
|
||||
esc_html__('Dein Feedback hilft uns, das Plugin ständig zu verbessern. Wenn du Fehler entdeckst oder Verbesserungsvorschläge hast, besuche bitte unsere', 'wp-multi'),
|
||||
'https://git.viper.ipv64.net/M_Viper/wp-multi',
|
||||
esc_html__('Gitea-Seite', 'wp-multi'),
|
||||
esc_html__('und teile uns deine Ideen mit!', 'wp-multi'),
|
||||
esc_html__('Support', 'wp-multi'),
|
||||
esc_html__('Bei Fragen oder Supportanfragen kannst du uns über', 'wp-multi'),
|
||||
'https://discord.com/invite/FdRs4BRd8D',
|
||||
esc_html__('Discord', 'wp-multi'),
|
||||
esc_html__('oder', 'wp-multi'),
|
||||
'https://t.me/M_Viper04',
|
||||
esc_html__('Telegram', 'wp-multi'),
|
||||
esc_html__('erreichen.', 'wp-multi')
|
||||
);
|
||||
|
||||
// Beim Klick auf das X den Schließ-Zeitpunkt speichern (per AJAX)
|
||||
?>
|
||||
<script>
|
||||
(function () {
|
||||
var notice = document.querySelector('.wp-multi-feedback-notice');
|
||||
if (!notice || typeof ajaxurl === 'undefined') { return; }
|
||||
notice.addEventListener('click', function (e) {
|
||||
if (e.target && e.target.classList.contains('notice-dismiss')) {
|
||||
var body = 'action=wp_multi_dismiss_banner&nonce=' + encodeURIComponent(notice.getAttribute('data-wpm-nonce'));
|
||||
fetch(ajaxurl, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: body
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
add_action('admin_notices', 'wp_multi_add_warning_banner');
|
||||
|
||||
// AJAX: Schließ-Zeitpunkt des Banners für den aktuellen Benutzer merken
|
||||
function wp_multi_dismiss_banner() {
|
||||
check_ajax_referer('wp_multi_dismiss_banner', 'nonce');
|
||||
update_user_meta(get_current_user_id(), 'wp_multi_banner_dismissed', time());
|
||||
wp_send_json_success();
|
||||
}
|
||||
add_action('wp_ajax_wp_multi_dismiss_banner', 'wp_multi_dismiss_banner');
|
||||
|
||||
// Support-Links in der Plugin-Übersicht anzeigen
|
||||
function wp_multi_plugin_row_meta($links, $file) {
|
||||
if ($file === plugin_basename(WP_MULTI_FILE)) {
|
||||
$new_links = array(
|
||||
'support_teams' => sprintf(
|
||||
'<a href="%s" target="_blank" style="color: rgb(255, 0, 0);">%s</a>',
|
||||
esc_url('https://discord.com/invite/FdRs4BRd8D'),
|
||||
esc_html__('Discord Support', 'wp-multi')
|
||||
),
|
||||
'support_telegram' => sprintf(
|
||||
'<a href="%s" target="_blank" style="color: rgb(255, 0, 0);">%s</a>',
|
||||
esc_url('https://t.me/M_Viper04'),
|
||||
esc_html__('Telegram Support', 'wp-multi')
|
||||
),
|
||||
);
|
||||
$links = array_merge($links, $new_links);
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
add_filter('plugin_row_meta', 'wp_multi_plugin_row_meta', 10, 2);
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Zentrale Menü-Registrierung
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Zentrale Menü-Registrierung
|
||||
*
|
||||
* Alle Admin-Seiten von WP Multi hängen als Submenüs am gemeinsamen
|
||||
* Top-Level-Menü "WP Multi" (Slug 'wp-multi'), das das Toolkit mit
|
||||
* admin_menu-Priorität 9 registriert. Diese Funktion läuft mit
|
||||
* Priorität 20 und legt bei fehlendem Toolkit-Menü ein Fallback an.
|
||||
*/
|
||||
function wp_multi_register_admin_menus() {
|
||||
global $admin_page_hooks;
|
||||
|
||||
$parent = 'wp-multi';
|
||||
|
||||
// Fallback: falls das Toolkit-Top-Level (noch) nicht existiert
|
||||
if (empty($admin_page_hooks[$parent])) {
|
||||
add_menu_page(
|
||||
__('WP Multi', 'wp-multi'),
|
||||
__('WP Multi', 'wp-multi'),
|
||||
'manage_options',
|
||||
$parent,
|
||||
'wp_multi_security_settings_page',
|
||||
'dashicons-screenoptions',
|
||||
59
|
||||
);
|
||||
}
|
||||
|
||||
$hooks = array();
|
||||
|
||||
// Sicherheit
|
||||
$hooks[] = add_submenu_page($parent, __('Sicherheit', 'wp-multi'), __('Sicherheit', 'wp-multi'), 'manage_options', 'wp-multi-security', 'wp_multi_security_settings_page');
|
||||
$hooks[] = add_submenu_page($parent, __('WP Multi Statistik', 'wp-multi'), __('Sicherheits-Statistik', 'wp-multi'), 'manage_options', 'wp-multi-statistics', 'wp_multi_statistics_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Sicherheitseinstellungen', 'wp-multi'), __('Benutzer-Sicherheit', 'wp-multi'), 'manage_options', 'wp_multi_users_security_settings', 'wp_multi_users_security_settings_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Blockierte IPs', 'wp-multi'), __('Blockierte IPs', 'wp-multi'), 'manage_options', 'wp_multi_blocked_ips', 'wp_multi_display_blocked_ips');
|
||||
$hooks[] = add_submenu_page($parent, __('Gesperrte Benutzer', 'wp-multi'), __('Gesperrte Benutzer', 'wp-multi'), 'manage_options', 'wp-multi-blocked-users', 'wp_multi_blocked_users_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Login-URL', 'wp-multi'), __('Login-URL', 'wp-multi'), 'manage_options', 'wp_multi_login_url', 'wp_multi_login_url_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Login-Design', 'wp-multi'), __('Login-Design', 'wp-multi'), 'manage_options', 'wp_multi_login_design', 'wp_multi_login_design_page');
|
||||
|
||||
// Analyse & Inhalte
|
||||
$hooks[] = add_submenu_page($parent, __('Benutzer Analytics', 'wp-multi'), __('Benutzer-Analytics', 'wp-multi'), 'manage_options', 'wp_multi_analytics', 'wp_multi_display_user_analytics');
|
||||
$hooks[] = add_submenu_page($parent, __('Gast-Autor Übersicht', 'wp-multi'), __('Gast-Autoren', 'wp-multi'), 'manage_options', 'guest_author_overview', 'wp_multi_guest_author_overview_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Pinwand', 'wp-multi'), __('Pinwand', 'wp-multi'), 'manage_options', 'message-board', 'wp_multi_add_message_board');
|
||||
$hooks[] = add_submenu_page($parent, __('Gemeldete Beiträge', 'wp-multi'), __('Gemeldete Beiträge', 'wp-multi'), 'manage_options', 'reported-posts', 'wp_stat_notice_reported_posts_page');
|
||||
$hooks[] = add_submenu_page($parent, __('WP Stat & Notice', 'wp-multi'), __('Statistik & Notice', 'wp-multi'), 'manage_options', 'statistik_manager', 'statistik_manager_options_page');
|
||||
|
||||
// Werkzeuge
|
||||
$hooks[] = add_submenu_page($parent, __('Custom Shortcodes', 'wp-multi'), __('Shortcodes', 'wp-multi'), 'manage_options', 'wp_multi_shortcodes', 'wp_multi_shortcode_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Automatische Tags', 'wp-multi'), __('Auto-Tags', 'wp-multi'), 'manage_options', 'wp-multi-auto-tags', 'wp_multi_auto_tags_page');
|
||||
$hooks[] = add_submenu_page($parent, __('Custom Text Einstellungen', 'wp-multi'), __('Custom Text', 'wp-multi'), 'manage_options', 'wp_multi_custom_text_settings', 'wp_multi_custom_text_settings_page_content');
|
||||
|
||||
// Benachrichtigungen
|
||||
$hooks[] = add_submenu_page($parent, __('Notify', 'wp-multi'), __('Notify', 'wp-multi'), 'manage_options', 'wp-multi-notify', 'wp_multi_notify_page');
|
||||
$hooks[] = add_submenu_page($parent, __('DC-Notify Einstellungen', 'wp-multi'), __('DC-Notify', 'wp-multi'), 'manage_options', 'wp-multi-dc-notify', 'wp_multi_settings_page');
|
||||
$hooks[] = add_submenu_page($parent, __('TG-Notify Einstellungen', 'wp-multi'), __('TG-Notify', 'wp-multi'), 'manage_options', 'tg-notify', 'tg_notify_page');
|
||||
|
||||
// Custom Admin-Links
|
||||
$hooks[] = add_submenu_page($parent, __('Admin-Link hinzufügen', 'wp-multi'), __('Admin-Links', 'wp-multi'), 'manage_options', 'wp-stat-notice-custom-page', 'wp_stat_notice_add_custom_page_form');
|
||||
|
||||
// Benutzerdefinierte Admin-Link-Seiten (dynamisch aus Option)
|
||||
$custom_pages = get_option('wp_stat_notice_custom_pages', []);
|
||||
if (!empty($custom_pages) && is_array($custom_pages)) {
|
||||
foreach ($custom_pages as $page) {
|
||||
if (!isset($page['title'], $page['slug'])) {
|
||||
continue;
|
||||
}
|
||||
$hooks[] = add_submenu_page($parent, $page['title'], $page['title'], 'manage_options', $page['slug'], 'wp_stat_notice_custom_page');
|
||||
}
|
||||
}
|
||||
|
||||
// Hooks beim Design-System des Toolkits anmelden (lädt das gemeinsame CSS)
|
||||
if (function_exists('wpmt_register_admin_hook')) {
|
||||
foreach ($hooks as $hook) {
|
||||
wpmt_register_admin_hook($hook);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('admin_menu', 'wp_multi_register_admin_menus', 20);
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Inhaltsverzeichnis [alphabetical_index]
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Index Verzeichnis [alphabetical_index]
|
||||
*/
|
||||
|
||||
|
||||
// Shortcode zum Erstellen des Indexes
|
||||
function wp_multi_alphabetical_index($atts) {
|
||||
// Definiere die Argumente für den Shortcode
|
||||
$atts = shortcode_atts(array(
|
||||
'posts_per_page' => 20, // Maximale Beiträge pro Seite
|
||||
), $atts, 'alphabetical_index');
|
||||
|
||||
// Hole alle Beiträge
|
||||
$args = array(
|
||||
'post_type' => 'post',
|
||||
'posts_per_page' => -1,
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
);
|
||||
|
||||
$posts = get_posts($args);
|
||||
|
||||
// Beiträge nach Anfangsbuchstaben gruppieren
|
||||
$alphabet = range('A', 'Z');
|
||||
$posts_by_letter = array();
|
||||
|
||||
foreach ($posts as $post) {
|
||||
$first_letter = strtoupper(substr($post->post_title, 0, 1));
|
||||
if (in_array($first_letter, $alphabet)) {
|
||||
$posts_by_letter[$first_letter][] = $post;
|
||||
}
|
||||
}
|
||||
|
||||
// Holen des aktuellen Buchstabens aus der URL
|
||||
$letter = isset($_GET['letter']) ? strtoupper($_GET['letter']) : ''; // Der Buchstabe aus der URL
|
||||
|
||||
// Bestimme, welche Beiträge angezeigt werden
|
||||
$posts_in_letter = [];
|
||||
if ($letter && isset($posts_by_letter[$letter])) {
|
||||
$posts_in_letter = $posts_by_letter[$letter];
|
||||
}
|
||||
|
||||
// Teile die Beiträge in zwei Hälften für die Boxen
|
||||
$halfway = ceil(count($posts_in_letter) / 2); // Rundet die Hälfte auf
|
||||
$first_half = array_slice($posts_in_letter, 0, $halfway); // Erste Hälfte der Beiträge
|
||||
$second_half = array_slice($posts_in_letter, $halfway); // Zweite Hälfte der Beiträge
|
||||
|
||||
// Ausgabe
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<div class="alphabetical-index">
|
||||
<!-- Links zu den Buchstaben -->
|
||||
<div class="alphabet-links">
|
||||
<?php foreach ($alphabet as $char): ?>
|
||||
<a href="?letter=<?php echo $char; ?>" class="letter-link"><?php echo $char; ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($letter): ?>
|
||||
<!-- Box für den aktuellen Buchstaben -->
|
||||
<div class="letter-heading-box">
|
||||
<h2>Beiträge für: <?php echo $letter; ?></h2>
|
||||
</div>
|
||||
|
||||
<!-- Zeige die Beiträge für den ausgewählten Buchstaben in zwei Boxen -->
|
||||
<div class="letter-pair-container">
|
||||
<div class="letter-box">
|
||||
<ul class="post-list">
|
||||
<?php foreach ($first_half as $post): ?>
|
||||
<li><a href="<?php echo get_permalink($post->ID); ?>"><?php echo $post->post_title; ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="letter-box">
|
||||
<ul class="post-list">
|
||||
<?php foreach ($second_half as $post): ?>
|
||||
<li><a href="<?php echo get_permalink($post->ID); ?>"><?php echo $post->post_title; ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.alphabetical-index {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.alphabet-links {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.alphabet-links a {
|
||||
margin-right: 10px;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
.alphabet-links a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.letter-heading-box {
|
||||
margin-bottom: 20px;
|
||||
background-color: #f0f0f0;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.letter-heading-box h2 {
|
||||
font-size: 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.letter-pair-container {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.letter-box {
|
||||
width: 48%;
|
||||
background-color: #f0f0f0;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.letter-box h2 {
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.post-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.post-list li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.post-list a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.post-list a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
// Shortcode registrieren
|
||||
add_shortcode('alphabetical_index', 'wp_multi_alphabetical_index');
|
||||
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Benutzer-Analytics
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Benutzer-Analytics mit verbesserten Sicherheits-, Performance- und Benutzerfreundlichkeits-Features
|
||||
*/
|
||||
|
||||
|
||||
// global ist nötig, weil die Plugin-Datei bei der Aktivierung innerhalb einer
|
||||
// Funktion eingebunden wird und $wpdb dort sonst nicht verfügbar ist.
|
||||
global $wpdb;
|
||||
define('WP_MULTI_ANALYTICS_TABLE', $wpdb->prefix . 'wp_multi_user_analytics');
|
||||
|
||||
/**
|
||||
* Erstellt die Datenbanktabelle für Benutzer-Analytics.
|
||||
*/
|
||||
function wp_multi_create_analytics_table() {
|
||||
global $wpdb;
|
||||
$table_name = WP_MULTI_ANALYTICS_TABLE;
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
user_id bigint(20) NOT NULL,
|
||||
action varchar(255) NOT NULL,
|
||||
post_id bigint(20) DEFAULT NULL,
|
||||
timestamp datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_timestamp (timestamp),
|
||||
INDEX idx_action (action)
|
||||
) $charset_collate;";
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
||||
dbDelta($sql);
|
||||
}
|
||||
register_activation_hook(WP_MULTI_FILE, 'wp_multi_create_analytics_table');
|
||||
|
||||
/**
|
||||
* Verfolgt Benutzerinteraktionen (Kommentare und Beitragsaufrufe).
|
||||
*
|
||||
* @param int $user_id Benutzer-ID.
|
||||
* @param string $action Aktion (z. B. 'view', 'comment').
|
||||
* @param int $post_id Beitrag-ID (optional).
|
||||
* @return bool Erfolg der Operation.
|
||||
*/
|
||||
function wp_multi_track_user_activity($user_id, $action, $post_id = null) {
|
||||
global $wpdb;
|
||||
$table_name = WP_MULTI_ANALYTICS_TABLE;
|
||||
|
||||
$user_id = absint($user_id);
|
||||
$action = sanitize_text_field($action);
|
||||
$post_id = $post_id ? absint($post_id) : null;
|
||||
|
||||
if ($action === 'view' && is_single()) {
|
||||
$post_id = get_the_ID();
|
||||
}
|
||||
|
||||
if (!$user_id || !$action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'user_id' => $user_id,
|
||||
'action' => $action,
|
||||
'post_id' => $post_id,
|
||||
),
|
||||
array('%d', '%s', '%d')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verfolgt Kommentar-Aktivitäten.
|
||||
*
|
||||
* @param int $comment_id Kommentar-ID.
|
||||
*/
|
||||
function wp_multi_comment_activity($comment_id) {
|
||||
$comment = get_comment($comment_id);
|
||||
$user_id = absint($comment->user_id);
|
||||
if ($user_id) {
|
||||
wp_multi_track_user_activity($user_id, 'comment', $comment->comment_post_ID);
|
||||
}
|
||||
}
|
||||
add_action('comment_post', 'wp_multi_comment_activity');
|
||||
|
||||
/**
|
||||
* Verfolgt Beitragsaufrufe.
|
||||
*/
|
||||
function wp_multi_post_view_activity() {
|
||||
if (is_single() && is_user_logged_in()) {
|
||||
$user_id = get_current_user_id();
|
||||
$post_id = get_the_ID();
|
||||
wp_multi_track_user_activity($user_id, 'view', $post_id);
|
||||
}
|
||||
}
|
||||
add_action('wp_head', 'wp_multi_post_view_activity');
|
||||
|
||||
/**
|
||||
* Ruft rohe Analytics-Daten aus der Datenbank ab.
|
||||
*
|
||||
* @param string $date_query Datum für die Abfrage.
|
||||
* @return array Rohe Analytics-Daten.
|
||||
*/
|
||||
function wp_multi_fetch_raw_analytics($start_datetime = null, $end_datetime = null) {
|
||||
global $wpdb;
|
||||
|
||||
if (!$start_datetime) {
|
||||
$start_datetime = gmdate('Y-m-d H:i:s', strtotime('-7 days'));
|
||||
}
|
||||
|
||||
$where = 'WHERE timestamp >= %s';
|
||||
$params = [$start_datetime];
|
||||
|
||||
if ($end_datetime) {
|
||||
$where .= ' AND timestamp <= %s';
|
||||
$params[] = $end_datetime;
|
||||
}
|
||||
|
||||
$sql = "SELECT DATE(timestamp) AS date, action, post_id, COUNT(*) AS count, user_id, timestamp
|
||||
FROM " . WP_MULTI_ANALYTICS_TABLE . "
|
||||
$where
|
||||
GROUP BY date, action, post_id, user_id, timestamp
|
||||
ORDER BY date ASC";
|
||||
|
||||
return $wpdb->get_results($wpdb->prepare($sql, $params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verarbeitet rohe Analytics-Daten für Diagramm und Tabelle.
|
||||
*
|
||||
* @param array $results Rohe Analytics-Daten.
|
||||
* @return array Verarbeitete Daten.
|
||||
*/
|
||||
function wp_multi_process_analytics_data($results) {
|
||||
$dates = [];
|
||||
$comment_counts = [];
|
||||
$view_counts = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$date = $result->date;
|
||||
if (!in_array($date, $dates)) {
|
||||
$dates[] = $date;
|
||||
}
|
||||
if ($result->action === 'comment') {
|
||||
$comment_counts[$date] = ($comment_counts[$date] ?? 0) + $result->count;
|
||||
} elseif ($result->action === 'view') {
|
||||
$view_counts[$date] = ($view_counts[$date] ?? 0) + $result->count;
|
||||
}
|
||||
}
|
||||
|
||||
$all_dates = [];
|
||||
$datasets = ['comments' => [], 'views' => []];
|
||||
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$date = date('Y-m-d', strtotime("-$i day"));
|
||||
$all_dates[] = $date;
|
||||
$datasets['comments'][] = $comment_counts[$date] ?? 0;
|
||||
$datasets['views'][] = $view_counts[$date] ?? 0;
|
||||
}
|
||||
|
||||
return [
|
||||
'dates' => array_reverse($all_dates),
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => __('Kommentare', 'wp-multi'),
|
||||
'data' => array_reverse($datasets['comments']),
|
||||
'borderColor' => 'rgba(75, 192, 192, 1)',
|
||||
'borderWidth' => 1,
|
||||
'fill' => false,
|
||||
],
|
||||
[
|
||||
'label' => __('Beitragsaufrufe', 'wp-multi'),
|
||||
'data' => array_reverse($datasets['views']),
|
||||
'borderColor' => 'rgba(153, 102, 255, 1)',
|
||||
'borderWidth' => 1,
|
||||
'fill' => false,
|
||||
]
|
||||
],
|
||||
'data' => $results
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruft Analytics-Daten mit Caching ab.
|
||||
*
|
||||
* @param string $date_query Datum für die Abfrage.
|
||||
* @return array Analytics-Daten.
|
||||
*/
|
||||
function wp_multi_get_analytics_data($start_datetime = null, $end_datetime = null) {
|
||||
$cache_key = 'wp_multi_analytics_data_' . md5($start_datetime . '|' . $end_datetime);
|
||||
$cached_data = get_transient($cache_key);
|
||||
|
||||
if ($cached_data !== false) {
|
||||
return $cached_data;
|
||||
}
|
||||
|
||||
$results = wp_multi_fetch_raw_analytics($start_datetime, $end_datetime);
|
||||
$data = wp_multi_process_analytics_data($results);
|
||||
|
||||
set_transient($cache_key, $data, HOUR_IN_SECONDS);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt die Benutzer-Analytics-Seite im Admin-Bereich an.
|
||||
*/
|
||||
function wp_multi_display_user_analytics() {
|
||||
global $wpdb;
|
||||
|
||||
if (!$wpdb->get_var("SHOW TABLES LIKE '" . WP_MULTI_ANALYTICS_TABLE . "'")) {
|
||||
echo '<div class="error"><p>' . esc_html__('Die Analytics-Tabelle existiert nicht. Bitte aktiviere das Plugin erneut.', 'wp-multi') . '</p></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
$time_range = isset($_GET['time_range']) ? sanitize_text_field($_GET['time_range']) : '7days';
|
||||
$start_datetime = gmdate('Y-m-d H:i:s', strtotime('-7 days'));
|
||||
$end_datetime = null;
|
||||
|
||||
if ($time_range === '30days') {
|
||||
$start_datetime = gmdate('Y-m-d H:i:s', strtotime('-30 days'));
|
||||
} elseif ($time_range === 'custom' && isset($_GET['start_date'], $_GET['end_date'])) {
|
||||
$custom_start = sanitize_text_field(wp_unslash($_GET['start_date']));
|
||||
$custom_end = sanitize_text_field(wp_unslash($_GET['end_date']));
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $custom_start) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $custom_end)) {
|
||||
$start_datetime = $custom_start . ' 00:00:00';
|
||||
$end_datetime = $custom_end . ' 23:59:59';
|
||||
}
|
||||
}
|
||||
|
||||
$results = wp_multi_get_analytics_data($start_datetime, $end_datetime);
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Benutzer Analytics', 'wp-multi'),
|
||||
__('Beitragsaufrufe und Kommentar-Aktivität deiner Besucher', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open(__('Zeitraum', 'wp-multi'));
|
||||
?>
|
||||
<form method="get">
|
||||
<input type="hidden" name="page" value="wp_multi_analytics">
|
||||
<select name="time_range" onchange="this.form.submit()" style="max-width:240px;">
|
||||
<option value="7days" <?php selected($time_range, '7days'); ?>><?php esc_html_e('Letzte 7 Tage', 'wp-multi'); ?></option>
|
||||
<option value="30days" <?php selected($time_range, '30days'); ?>><?php esc_html_e('Letzte 30 Tage', 'wp-multi'); ?></option>
|
||||
<option value="custom" <?php selected($time_range, 'custom'); ?>><?php esc_html_e('Benutzerdefiniert', 'wp-multi'); ?></option>
|
||||
</select>
|
||||
<?php if ($time_range === 'custom') : ?>
|
||||
<input type="date" name="start_date" value="<?php echo esc_attr($_GET['start_date'] ?? ''); ?>" style="max-width:180px;">
|
||||
<input type="date" name="end_date" value="<?php echo esc_attr($_GET['end_date'] ?? ''); ?>" style="max-width:180px;">
|
||||
<?php endif; ?>
|
||||
<button type="submit" class="wpm-btn wpm-btn--primary"><?php esc_html_e('Filtern', 'wp-multi'); ?></button>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
if (empty($results['data'])) {
|
||||
wpmt_admin_notice('info', __('Keine Daten für den gewählten Zeitraum verfügbar.', 'wp-multi'));
|
||||
} else {
|
||||
wpmt_admin_card_open(__('Aktivitätsverlauf', 'wp-multi'));
|
||||
?>
|
||||
<canvas id="userActivityChart" style="height: 300px; width: 100%;"></canvas>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
if (typeof Chart !== 'undefined') {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('userActivityChart').getContext('2d');
|
||||
var chart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo wp_json_encode($results['dates']); ?>,
|
||||
datasets: <?php echo wp_json_encode($results['datasets']); ?>,
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: { title: { display: true, text: '<?php echo esc_js(__('Datum', 'wp-multi')); ?>' } },
|
||||
y: { title: { display: true, text: '<?php echo esc_js(__('Anzahl', 'wp-multi')); ?>' }, beginAtZero: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error('Chart.js konnte nicht geladen werden.');
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Einzelne Aktivitäten', 'wp-multi'));
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e('Benutzer ID', 'wp-multi'); ?></th>
|
||||
<th><?php esc_html_e('Aktion', 'wp-multi'); ?></th>
|
||||
<th><?php esc_html_e('Beitrag Titel', 'wp-multi'); ?></th>
|
||||
<th><?php esc_html_e('Beitrag ID', 'wp-multi'); ?></th>
|
||||
<th><?php esc_html_e('Zeitstempel', 'wp-multi'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($results['data'] as $row) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html($row->user_id); ?></td>
|
||||
<td><span class="wpm-badge <?php echo $row->action === 'comment' ? 'wpm-badge--success' : ''; ?>"><?php echo esc_html($row->action); ?></span></td>
|
||||
<td>
|
||||
<?php
|
||||
if ($row->post_id) {
|
||||
$post_title = get_the_title($row->post_id);
|
||||
echo esc_html($post_title ?: __('Kein Titel verfügbar', 'wp-multi'));
|
||||
} else {
|
||||
echo esc_html__('Kein Beitrag', 'wp-multi');
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo esc_html($row->post_id ?: '-'); ?></td>
|
||||
<td><?php echo esc_html($row->timestamp); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
}
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Der Analytics-Menüpunkt wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Anti-Spam Honeypot
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Anti Spam Honey
|
||||
*/
|
||||
|
||||
|
||||
// Standardwerte setzen
|
||||
function wp_multi_set_default_options() {
|
||||
add_option('wp_multi_honeypot_field', 'iwlxja5187');
|
||||
add_option('wp_multi_honeypot_error', 'Spamming or your Javascript is disabled !!');
|
||||
add_option('wp_multi_honeypot_widget', 0);
|
||||
add_option('wp_multi_max_links', 3);
|
||||
add_option('wp_multi_blocked_keywords', 'viagra,casino,bitcoin');
|
||||
add_option('wp_multi_blocked_ips', '');
|
||||
add_option('wp_multi_blocked_comments', 0); // Zähler für blockierte Kommentare
|
||||
add_option('wp_multi_honeypot_hits', 0); // Zähler für Honeypot-Aktivierungen
|
||||
add_option('wp_multi_spammer_ips', []); // Liste der blockierten Spammer-IP-Adressen
|
||||
add_option('wp_multi_spam_submissions', []); // Liste der Spam-Einreichungen
|
||||
}
|
||||
register_activation_hook(WP_MULTI_FILE, 'wp_multi_set_default_options');
|
||||
|
||||
// Die Sicherheits-Menüpunkte werden zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Einstellungsseite mit CSS & JS für Generator
|
||||
function wp_multi_security_settings_page() {
|
||||
wpmt_admin_page_open(
|
||||
__('Sicherheit', 'wp-multi'),
|
||||
__('Anti-Spam, Honeypot und Kommentarfilter konfigurieren', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('wp_multi_security_settings');
|
||||
do_settings_sections('wp-multi-security');
|
||||
submit_button();
|
||||
?>
|
||||
</form>
|
||||
<script>
|
||||
function generateHoneypotName() {
|
||||
let field = document.getElementById('wp_multi_honeypot_field');
|
||||
let randomString = Math.random().toString(36).substring(2, 12);
|
||||
field.value = randomString;
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Statistikseite im Dashboard
|
||||
function wp_multi_statistics_page() {
|
||||
$blocked_comments = get_option('wp_multi_blocked_comments', 0);
|
||||
$honeypot_hits = get_option('wp_multi_honeypot_hits', 0);
|
||||
$spammer_ips = get_option('wp_multi_spammer_ips', []);
|
||||
$spam_submissions = get_option('wp_multi_spam_submissions', []);
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Anti-Spam Statistik', 'wp-multi'),
|
||||
__('Blockierte Kommentare, Honeypot-Treffer und erfasste Spammer-IPs', 'wp-multi')
|
||||
);
|
||||
|
||||
echo '<div class="wpm-stats">';
|
||||
wpmt_admin_stat_card(__('Blockierte Kommentare', 'wp-multi'), number_format_i18n($blocked_comments), 'dashicons-dismiss');
|
||||
wpmt_admin_stat_card(__('Honeypot-Treffer', 'wp-multi'), number_format_i18n($honeypot_hits), 'dashicons-shield');
|
||||
wpmt_admin_stat_card(__('Spammer-IPs', 'wp-multi'), number_format_i18n(count($spammer_ips)), 'dashicons-admin-site-alt3');
|
||||
wpmt_admin_stat_card(__('Spam-Einreichungen', 'wp-multi'), number_format_i18n(count($spam_submissions)), 'dashicons-email-alt');
|
||||
echo '</div>';
|
||||
|
||||
wpmt_admin_card_open(__('Spammer-IP-Adressen', 'wp-multi'));
|
||||
if (!empty($spammer_ips)) {
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr><th><?php esc_html_e('IP-Adresse', 'wp-multi'); ?></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($spammer_ips as $ip) : ?>
|
||||
<tr><td><?php echo esc_html($ip); ?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
wpmt_admin_notice('info', __('Keine Spammer-IP-Adressen gefunden.', 'wp-multi'));
|
||||
}
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
|
||||
// Einstellungen registrieren
|
||||
function wp_multi_register_security_settings() {
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_honeypot_field');
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_honeypot_error');
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_honeypot_widget');
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_max_links');
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_blocked_keywords');
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_blocked_ips');
|
||||
|
||||
add_settings_section('wp_multi_honeypot_section', 'Honeypot Einstellungen', null, 'wp-multi-security');
|
||||
|
||||
add_settings_field('wp_multi_honeypot_field', 'Honey Pot Field Name', 'wp_multi_honeypot_field_callback', 'wp-multi-security', 'wp_multi_honeypot_section');
|
||||
add_settings_field('wp_multi_honeypot_error', 'Honey Pot Error Message', 'wp_multi_honeypot_error_callback', 'wp-multi-security', 'wp_multi_honeypot_section');
|
||||
add_settings_field('wp_multi_honeypot_widget', 'Disable Honeypot Test Widget', 'wp_multi_honeypot_widget_callback', 'wp-multi-security', 'wp_multi_honeypot_section');
|
||||
add_settings_field('wp_multi_max_links', 'Maximale Links im Kommentar', 'wp_multi_max_links_callback', 'wp-multi-security', 'wp_multi_honeypot_section');
|
||||
add_settings_field('wp_multi_blocked_keywords', 'Blockierte Schlüsselwörter', 'wp_multi_blocked_keywords_callback', 'wp-multi-security', 'wp_multi_honeypot_section');
|
||||
add_settings_field('wp_multi_blocked_ips', 'Blockierte IP-Adressen', 'wp_multi_blocked_ips_callback', 'wp-multi-security', 'wp_multi_honeypot_section');
|
||||
}
|
||||
|
||||
add_action('admin_init', 'wp_multi_register_security_settings');
|
||||
|
||||
function wp_multi_honeypot_field_callback() {
|
||||
?>
|
||||
<div class="wp-multi-honeypot-group">
|
||||
<input type="text" id="wp_multi_honeypot_field" name="wp_multi_honeypot_field" value="<?php echo esc_attr(get_option('wp_multi_honeypot_field')); ?>">
|
||||
<button type="button" onclick="generateHoneypotName()">Generieren</button>
|
||||
</div>
|
||||
<small>Verwenden Sie ein zufälliges Zeichenfolgen für das Honeypot-Feld.</small>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_honeypot_error_callback() {
|
||||
?>
|
||||
<input type="text" name="wp_multi_honeypot_error" value="<?php echo esc_attr(get_option('wp_multi_honeypot_error')); ?>">
|
||||
<small>Die Nachricht, die angezeigt wird, wenn ein Honeypot ausgelöst wird.</small>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_honeypot_widget_callback() {
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_honeypot_widget" value="1" <?php checked(1, get_option('wp_multi_honeypot_widget'), true); ?>>
|
||||
<small>Deaktivieren Sie das Honeypot-Test-Widget im Frontend.</small>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_max_links_callback() {
|
||||
?>
|
||||
<input type="number" name="wp_multi_max_links" value="<?php echo esc_attr(get_option('wp_multi_max_links')); ?>">
|
||||
<small>Maximale Anzahl von Links, die in einem Kommentar erlaubt sind.</small>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_blocked_keywords_callback() {
|
||||
?>
|
||||
<input type="text" name="wp_multi_blocked_keywords" value="<?php echo esc_attr(get_option('wp_multi_blocked_keywords')); ?>">
|
||||
<small>Schlüsselwörter, die blockiert werden sollen (durch Kommas getrennt).</small>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_blocked_ips_callback() {
|
||||
?>
|
||||
<textarea name="wp_multi_blocked_ips" rows="5"><?php echo esc_textarea(get_option('wp_multi_blocked_ips')); ?></textarea>
|
||||
<small>Blockierte IP-Adressen (jede Adresse in einer neuen Zeile).</small>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Honeypot-Feld (unsichtbar für Menschen) im Kommentarformular ausgeben
|
||||
function wp_multi_render_honeypot_field() {
|
||||
$field_name = get_option('wp_multi_honeypot_field', 'iwlxja5187');
|
||||
?>
|
||||
<p class="wp-multi-honeypot" style="position:absolute !important; left:-9999px !important; top:-9999px !important;" aria-hidden="true">
|
||||
<label for="<?php echo esc_attr($field_name); ?>"><?php esc_html_e('Website (bitte leer lassen)', 'wp-multi'); ?></label>
|
||||
<input type="text" name="<?php echo esc_attr($field_name); ?>" id="<?php echo esc_attr($field_name); ?>" value="" tabindex="-1" autocomplete="off">
|
||||
</p>
|
||||
<input type="hidden" name="wp_multi_form_time" value="<?php echo esc_attr(time()); ?>">
|
||||
<?php
|
||||
}
|
||||
add_action('comment_form_top', 'wp_multi_render_honeypot_field');
|
||||
|
||||
// Zähler/Statistik für einen geblockten Spam-Versuch aktualisieren
|
||||
function wp_multi_register_spam_hit($reason, $ip = '') {
|
||||
update_option('wp_multi_honeypot_hits', get_option('wp_multi_honeypot_hits', 0) + 1);
|
||||
update_option('wp_multi_blocked_comments', get_option('wp_multi_blocked_comments', 0) + 1);
|
||||
|
||||
if ($ip) {
|
||||
$spammer_ips = get_option('wp_multi_spammer_ips', []);
|
||||
if (!in_array($ip, $spammer_ips, true)) {
|
||||
$spammer_ips[] = $ip;
|
||||
update_option('wp_multi_spammer_ips', $spammer_ips);
|
||||
}
|
||||
}
|
||||
|
||||
$submissions = get_option('wp_multi_spam_submissions', []);
|
||||
$submissions[] = [
|
||||
'reason' => $reason,
|
||||
'ip' => $ip,
|
||||
'timestamp' => current_time('mysql'),
|
||||
];
|
||||
// Auf die letzten 200 Einträge begrenzen, damit die Option nicht unbegrenzt wächst
|
||||
if (count($submissions) > 200) {
|
||||
$submissions = array_slice($submissions, -200);
|
||||
}
|
||||
update_option('wp_multi_spam_submissions', $submissions);
|
||||
}
|
||||
|
||||
// Honeypot-/Zeitfallen-Prüfung sowie IP-/Keyword-/Link-Filter beim Absenden eines Kommentars
|
||||
function wp_multi_validate_comment_submission($commentdata) {
|
||||
$ip = function_exists('get_user_ip') ? get_user_ip() : (isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '');
|
||||
|
||||
// Honeypot-Feld: darf von einem Menschen nie ausgefüllt werden
|
||||
$field_name = get_option('wp_multi_honeypot_field', 'iwlxja5187');
|
||||
if (!empty($_POST[$field_name])) {
|
||||
wp_multi_register_spam_hit('honeypot', $ip);
|
||||
wp_die(esc_html(get_option('wp_multi_honeypot_error', 'Spamming or your Javascript is disabled !!')));
|
||||
}
|
||||
|
||||
// Zeit-Falle: Formular darf nicht schneller als 3 Sekunden nach dem Laden abgeschickt werden
|
||||
if (isset($_POST['wp_multi_form_time'])) {
|
||||
$elapsed = time() - absint($_POST['wp_multi_form_time']);
|
||||
if ($elapsed < 3) {
|
||||
wp_multi_register_spam_hit('honeypot_zeitfalle', $ip);
|
||||
wp_die(esc_html(get_option('wp_multi_honeypot_error', 'Spamming or your Javascript is disabled !!')));
|
||||
}
|
||||
}
|
||||
|
||||
// Blockierte IP-Adressen
|
||||
$blocked_ips = array_filter(array_map('trim', explode("\n", (string) get_option('wp_multi_blocked_ips', ''))));
|
||||
if ($ip && in_array($ip, $blocked_ips, true)) {
|
||||
wp_multi_register_spam_hit('blocked_ip', $ip);
|
||||
wp_die(esc_html__('Deine IP-Adresse wurde für Kommentare gesperrt.', 'wp-multi'));
|
||||
}
|
||||
|
||||
$content = isset($commentdata['comment_content']) ? $commentdata['comment_content'] : '';
|
||||
|
||||
// Blockierte Schlüsselwörter
|
||||
$blocked_keywords = array_filter(array_map('trim', explode(',', (string) get_option('wp_multi_blocked_keywords', ''))));
|
||||
foreach ($blocked_keywords as $keyword) {
|
||||
if ($keyword !== '' && stripos($content, $keyword) !== false) {
|
||||
wp_multi_register_spam_hit('keyword', $ip);
|
||||
wp_die(esc_html__('Dein Kommentar enthält nicht erlaubte Inhalte.', 'wp-multi'));
|
||||
}
|
||||
}
|
||||
|
||||
// Maximale Anzahl an Links im Kommentar
|
||||
$max_links = absint(get_option('wp_multi_max_links', 3));
|
||||
if ($max_links > 0 && preg_match_all('#https?://#i', $content) > $max_links) {
|
||||
wp_multi_register_spam_hit('links', $ip);
|
||||
wp_die(esc_html__('Dein Kommentar enthält zu viele Links.', 'wp-multi'));
|
||||
}
|
||||
|
||||
// Kommentarfilter: Telefonnummern, E-Mails, URLs, IPs, Schimpfwörter durch * ersetzen
|
||||
$commentdata['comment_content'] = wp_multi_apply_comment_content_filter($content);
|
||||
|
||||
return $commentdata;
|
||||
}
|
||||
add_filter('preprocess_comment', 'wp_multi_validate_comment_submission');
|
||||
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Automatische Tags
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Verbessertes Auto-Tag-Plugin mit optimierter Sicherheit, Performance und Benutzerfreundlichkeit
|
||||
*/
|
||||
|
||||
define('WP_MULTI_AUTO_TAGS_OPTION', 'wp_multi_custom_stopwords');
|
||||
define('WP_MULTI_AUTO_TAGS_QUEUE', 'wp_multi_auto_tags_queue');
|
||||
define('WP_MULTI_AUTO_TAGS_NONCE', 'wp_multi_auto_tags_nonce');
|
||||
|
||||
/**
|
||||
* Fügt automatische Tags zu einem Beitrag hinzu.
|
||||
*
|
||||
* @param int $post_id ID des Beitrags.
|
||||
*/
|
||||
function wp_multi_auto_add_tags($post_id) {
|
||||
if (get_post_type($post_id) !== 'post') {
|
||||
return;
|
||||
}
|
||||
|
||||
$existing_tags = wp_get_post_tags($post_id, ['fields' => 'names']);
|
||||
if (!empty($existing_tags)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post = get_post($post_id);
|
||||
if (!$post) {
|
||||
error_log("WP Multi Auto Tags: Beitrag $post_id nicht gefunden.");
|
||||
return;
|
||||
}
|
||||
|
||||
$content = strip_tags($post->post_content);
|
||||
$content = mb_strtolower($content, 'UTF-8');
|
||||
|
||||
// Stopwörter laden
|
||||
$stopwords = wp_multi_get_stopwords();
|
||||
$words = wp_multi_extract_words($content, $stopwords);
|
||||
|
||||
if (empty($words)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$word_counts = array_count_values($words);
|
||||
arsort($word_counts);
|
||||
|
||||
$top_tags = array_slice(array_keys($word_counts), 0, 5);
|
||||
if (!empty($top_tags)) {
|
||||
wp_set_post_tags($post_id, $top_tags, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrahiert relevante Wörter aus dem Inhalt.
|
||||
*
|
||||
* @param string $content Der Inhalt des Beitrags.
|
||||
* @param array $stopwords Liste der Stopwörter.
|
||||
* @return array Liste der extrahierten Wörter.
|
||||
*/
|
||||
function wp_multi_extract_words($content, $stopwords) {
|
||||
preg_match_all('/\b[a-zäöüß]{4,}\b/u', $content, $matches);
|
||||
return array_unique(array_diff($matches[0], $stopwords));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt die kombinierten Stopwörter (Standard + benutzerdefiniert).
|
||||
*
|
||||
* @return array Liste der Stopwörter.
|
||||
*/
|
||||
function wp_multi_get_stopwords() {
|
||||
$cache_key = 'wp_multi_stopwords';
|
||||
$stopwords = get_transient($cache_key);
|
||||
|
||||
if ($stopwords !== false) {
|
||||
return $stopwords;
|
||||
}
|
||||
|
||||
$custom_stopwords = get_option(WP_MULTI_AUTO_TAGS_OPTION, '');
|
||||
$custom_stopwords = array_filter(array_map('trim', explode(',', sanitize_text_field($custom_stopwords))));
|
||||
|
||||
$default_stopwords = [
|
||||
'und', 'oder', 'ein', 'eine', 'der', 'die', 'das', 'in', 'mit', 'auf', 'zu', 'von',
|
||||
'für', 'ist', 'es', 'im', 'an', 'am', 'bei', 'auch', 'aber', 'so', 'dass', 'kann',
|
||||
'wenn', 'wie', 'wir', 'man', 'nur', 'nicht', 'mehr', 'als', 'sein', 'wurde', 'werden',
|
||||
'hat', 'haben', 'schon', 'doch', 'denn', 'diese', 'dieser', 'dieses', 'nach', 'sehr', 'allgemein'
|
||||
];
|
||||
|
||||
$stopwords = array_merge($default_stopwords, $custom_stopwords);
|
||||
set_transient($cache_key, $stopwords, DAY_IN_SECONDS);
|
||||
return $stopwords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fügt das Admin-Menü für automatische Tags hinzu.
|
||||
*/
|
||||
// Der Auto-Tags-Menüpunkt wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
/**
|
||||
* Rendert die Admin-Seite für automatische Tags.
|
||||
*/
|
||||
function wp_multi_auto_tags_page() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('Zugriff verweigert.', 'wp-multi'));
|
||||
}
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Automatische Tags', 'wp-multi'),
|
||||
__('Fügt Beiträgen ohne Tags automatisch passende Schlagwörter hinzu', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open(__('Einstellungen', 'wp-multi'));
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('wp_multi_auto_tags_options');
|
||||
do_settings_sections('wp-multi-auto-tags');
|
||||
wp_nonce_field(WP_MULTI_AUTO_TAGS_NONCE, WP_MULTI_AUTO_TAGS_NONCE);
|
||||
?>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label" for="wp_multi_custom_stopwords"><?php esc_html_e('Stopwörter (kommagetrennt)', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Diese Wörter werden nicht als Tags verwendet. Beispiele: wird, auch, aber', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<textarea id="wp_multi_custom_stopwords" name="wp_multi_custom_stopwords" rows="5"><?php echo esc_textarea(get_option(WP_MULTI_AUTO_TAGS_OPTION, '')); ?></textarea>
|
||||
</div>
|
||||
<p><input type="submit" value="<?php esc_attr_e('Speichern', 'wp-multi'); ?>" class="wpm-btn wpm-btn--primary"></p>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Alle Beiträge verarbeiten', 'wp-multi'));
|
||||
?>
|
||||
<p><?php esc_html_e('Durchsucht alle vorhandenen Beiträge ohne Tags und ergänzt automatisch passende Schlagwörter.', 'wp-multi'); ?></p>
|
||||
<button id="start-auto-tags" class="wpm-btn wpm-btn--primary"><?php esc_html_e('Jetzt ausführen', 'wp-multi'); ?></button>
|
||||
<div id="progress-container" style="display:none; width:100%; background:#f4f4f4; border-radius:8px; margin-top:20px; overflow:hidden;">
|
||||
<div id="progress-bar" style="width:0%; height:30px; background:#2ecc71; text-align:center; color:#fff; line-height:30px; font-weight:bold; transition:width .4s;">0%</div>
|
||||
</div>
|
||||
<p id="status-message" style="margin-top:15px; font-weight:600; color:var(--wpm-primary,#0073aa);"></p>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
?>
|
||||
<script>
|
||||
var wpMultiAutoTags = <?php echo wp_json_encode([
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce(WP_MULTI_AUTO_TAGS_NONCE),
|
||||
'messages' => [
|
||||
'processing' => __('Wird verarbeitet...', 'wp-multi'),
|
||||
'run' => __('Jetzt ausführen', 'wp-multi'),
|
||||
'loading' => __('Lade...', 'wp-multi'),
|
||||
'no_posts' => __('Keine Beiträge gefunden.', 'wp-multi'),
|
||||
'success' => __('Automatische Tags erfolgreich hinzugefügt!', 'wp-multi'),
|
||||
'error' => __('Fehler bei der Verarbeitung.', 'wp-multi'),
|
||||
'start_error' => __('Fehler beim Starten der Verarbeitung.', 'wp-multi'),
|
||||
],
|
||||
]); ?>;
|
||||
jQuery(document).ready(function($) {
|
||||
$('#start-auto-tags').on('click', function() {
|
||||
const button = $(this);
|
||||
const progressContainer = $('#progress-container');
|
||||
const progressBar = $('#progress-bar');
|
||||
const statusMessage = $('#status-message');
|
||||
|
||||
button.prop('disabled', true).text(wpMultiAutoTags.messages.processing);
|
||||
progressContainer.show();
|
||||
progressBar.css('width', '0%').text('0%');
|
||||
statusMessage.text(wpMultiAutoTags.messages.loading);
|
||||
|
||||
$.ajax({
|
||||
url: wpMultiAutoTags.ajaxurl,
|
||||
method: 'POST',
|
||||
data: {
|
||||
action: 'wp_multi_process_auto_tags',
|
||||
nonce: wpMultiAutoTags.nonce,
|
||||
},
|
||||
success: function(response) {
|
||||
if (!response.data.total) {
|
||||
statusMessage.text(wpMultiAutoTags.messages.no_posts);
|
||||
button.prop('disabled', false).text(wpMultiAutoTags.messages.run);
|
||||
return;
|
||||
}
|
||||
|
||||
const total = response.data.total;
|
||||
let processed = 0;
|
||||
const batchSize = 10;
|
||||
|
||||
function processBatch() {
|
||||
$.ajax({
|
||||
url: wpMultiAutoTags.ajaxurl,
|
||||
method: 'POST',
|
||||
data: {
|
||||
action: 'wp_multi_process_auto_tags_step',
|
||||
batchSize: batchSize,
|
||||
nonce: wpMultiAutoTags.nonce,
|
||||
},
|
||||
success: function(result) {
|
||||
if (result.data.done) {
|
||||
processed += batchSize;
|
||||
const percent = Math.min(Math.round((processed / total) * 100), 100);
|
||||
progressBar.css('width', percent + '%').text(percent + '%');
|
||||
|
||||
if (processed < total) {
|
||||
processBatch();
|
||||
} else {
|
||||
button.prop('disabled', false).text(wpMultiAutoTags.messages.run);
|
||||
statusMessage.text(wpMultiAutoTags.messages.success);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
statusMessage.text(wpMultiAutoTags.messages.error);
|
||||
button.prop('disabled', false).text(wpMultiAutoTags.messages.run);
|
||||
},
|
||||
});
|
||||
}
|
||||
processBatch();
|
||||
},
|
||||
error: function() {
|
||||
statusMessage.text(wpMultiAutoTags.messages.start_error);
|
||||
button.prop('disabled', false).text(wpMultiAutoTags.messages.run);
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Registriert die Einstellungen für automatische Tags.
|
||||
*/
|
||||
function wp_multi_auto_tags_settings_init() {
|
||||
register_setting('wp_multi_auto_tags_options', WP_MULTI_AUTO_TAGS_OPTION, [
|
||||
'sanitize_callback' => function($input) {
|
||||
$input = sanitize_text_field($input);
|
||||
return implode(',', array_map('trim', explode(',', $input)));
|
||||
},
|
||||
]);
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_auto_tags_settings_init');
|
||||
|
||||
/**
|
||||
* Verarbeitet die Initialisierung der Auto-Tag-Verarbeitung via AJAX.
|
||||
*/
|
||||
function wp_multi_process_auto_tags() {
|
||||
check_ajax_referer(WP_MULTI_AUTO_TAGS_NONCE, 'nonce');
|
||||
|
||||
$args = [
|
||||
'post_type' => 'post',
|
||||
'posts_per_page' => 100,
|
||||
'fields' => 'ids',
|
||||
'no_found_rows' => true, // Optimierung
|
||||
];
|
||||
|
||||
$posts = get_posts($args);
|
||||
if (empty($posts)) {
|
||||
wp_send_json_success(['total' => 0]);
|
||||
}
|
||||
|
||||
set_transient(WP_MULTI_AUTO_TAGS_QUEUE, $posts, 300);
|
||||
wp_send_json_success(['total' => count($posts)]);
|
||||
}
|
||||
add_action('wp_ajax_wp_multi_process_auto_tags', 'wp_multi_process_auto_tags');
|
||||
|
||||
/**
|
||||
* Verarbeitet einen Batch von Beiträgen für die Auto-Tag-Verarbeitung.
|
||||
*/
|
||||
function wp_multi_process_auto_tags_step() {
|
||||
check_ajax_referer(WP_MULTI_AUTO_TAGS_NONCE, 'nonce');
|
||||
|
||||
$queue = get_transient(WP_MULTI_AUTO_TAGS_QUEUE);
|
||||
$batchSize = isset($_POST['batchSize']) ? absint($_POST['batchSize']) : 10;
|
||||
$batchSize = max(1, min($batchSize, 50));
|
||||
|
||||
if (!$queue || empty($queue)) {
|
||||
wp_send_json_success(['done' => false]);
|
||||
}
|
||||
|
||||
set_time_limit(30); // Timeout verhindern
|
||||
$posts_to_process = array_splice($queue, 0, $batchSize);
|
||||
|
||||
foreach ($posts_to_process as $post_id) {
|
||||
wp_multi_auto_add_tags($post_id);
|
||||
}
|
||||
|
||||
set_transient(WP_MULTI_AUTO_TAGS_QUEUE, $queue, 300);
|
||||
wp_send_json_success(['done' => true]);
|
||||
}
|
||||
add_action('wp_ajax_wp_multi_process_auto_tags_step', 'wp_multi_process_auto_tags_step');
|
||||
|
||||
/**
|
||||
* Fügt Tags automatisch bei neuen oder aktualisierten Beiträgen hinzu.
|
||||
*
|
||||
* @param int $post_id ID des Beitrags.
|
||||
*/
|
||||
function wp_multi_auto_tag_on_save($post_id) {
|
||||
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_multi_auto_add_tags($post_id);
|
||||
}
|
||||
add_action('save_post', 'wp_multi_auto_tag_on_save', 10, 1);
|
||||
|
||||
|
||||
|
||||
+10914
-136
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Benutzer für Kommentare sperren
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* User Kommentar Blocken
|
||||
*/
|
||||
|
||||
function wp_multi_create_blocked_users_table() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'blocked_users';
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
username varchar(100) DEFAULT '' NOT NULL,
|
||||
email varchar(100) DEFAULT '' NOT NULL,
|
||||
ip_address varchar(45) DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) $charset_collate;";
|
||||
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
||||
dbDelta( $sql );
|
||||
}
|
||||
|
||||
function wp_multi_activate() {
|
||||
wp_multi_create_blocked_users_table();
|
||||
}
|
||||
|
||||
register_activation_hook( WP_MULTI_FILE, 'wp_multi_activate' );
|
||||
|
||||
function wp_multi_block_user($username = '', $email = '', $ip_address = '') {
|
||||
global $wpdb;
|
||||
if (empty($username) && empty($email) && empty($ip_address)) {
|
||||
return false;
|
||||
}
|
||||
$result = $wpdb->insert(
|
||||
$wpdb->prefix . 'blocked_users',
|
||||
[
|
||||
'username' => $username,
|
||||
'email' => $email,
|
||||
'ip_address' => $ip_address
|
||||
]
|
||||
);
|
||||
return $result !== false;
|
||||
}
|
||||
|
||||
function wp_multi_delete_blocked_user($id) {
|
||||
global $wpdb;
|
||||
return $wpdb->delete($wpdb->prefix . 'blocked_users', ['id' => $id], ['%d']);
|
||||
}
|
||||
|
||||
// Der Menüpunkt "Gesperrte Benutzer" wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
function wp_multi_blocked_users_page() {
|
||||
global $wpdb;
|
||||
|
||||
$notices = array();
|
||||
|
||||
if (isset($_POST['block_username']) || isset($_POST['block_email']) || isset($_POST['block_ip'])) {
|
||||
check_admin_referer('wp_multi_block_user');
|
||||
$username = sanitize_text_field($_POST['block_username']);
|
||||
$email = sanitize_email($_POST['block_email']);
|
||||
$ip_address = sanitize_text_field($_POST['block_ip']);
|
||||
if (wp_multi_block_user($username, $email, $ip_address)) {
|
||||
$notices[] = array('success', __('Benutzer wurde gesperrt!', 'wp-multi'));
|
||||
} else {
|
||||
$notices[] = array('error', __('Fehler beim Sperren des Benutzers!', 'wp-multi'));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['delete']) && isset($_GET['_wpnonce'])) {
|
||||
if (wp_verify_nonce($_GET['_wpnonce'], 'wp_multi_delete_user_' . $_GET['delete'])) {
|
||||
$user_id = intval($_GET['delete']);
|
||||
if ($user_id > 0 && wp_multi_delete_blocked_user($user_id)) {
|
||||
$notices[] = array('success', __('Benutzer wurde gelöscht!', 'wp-multi'));
|
||||
} else {
|
||||
$notices[] = array('error', __('Fehler beim Löschen des Benutzers!', 'wp-multi'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$search_query = '';
|
||||
if (isset($_GET['search'])) {
|
||||
$search_query = sanitize_text_field($_GET['search']);
|
||||
}
|
||||
|
||||
$blocked_users = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}blocked_users WHERE username LIKE %s OR email LIKE %s OR ip_address LIKE %s",
|
||||
'%' . $search_query . '%', '%' . $search_query . '%', '%' . $search_query . '%'
|
||||
));
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Gesperrte Benutzer', 'wp-multi'),
|
||||
__('Benutzer per Name, E-Mail oder IP von Kommentaren ausschließen', 'wp-multi')
|
||||
);
|
||||
|
||||
foreach ($notices as $notice) {
|
||||
wpmt_admin_notice($notice[0], $notice[1]);
|
||||
}
|
||||
|
||||
echo '<div class="wpm-grid wpm-grid--2">';
|
||||
|
||||
wpmt_admin_card_open(__('Benutzer sperren', 'wp-multi'));
|
||||
?>
|
||||
<form method="post">
|
||||
<?php wp_nonce_field('wp_multi_block_user'); ?>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php _e('Benutzername', 'wp-multi'); ?></label>
|
||||
<input type="text" name="block_username" placeholder="Benutzername">
|
||||
</div>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php _e('E-Mail-Adresse', 'wp-multi'); ?></label>
|
||||
<input type="email" name="block_email" placeholder="E-Mail-Adresse">
|
||||
</div>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php _e('IP-Adresse', 'wp-multi'); ?></label>
|
||||
<input type="text" name="block_ip" placeholder="IP-Adresse">
|
||||
</div>
|
||||
<p><input type="submit" class="wpm-btn wpm-btn--primary" value="<?php esc_attr_e('Benutzer sperren', 'wp-multi'); ?>"></p>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Suchen', 'wp-multi'));
|
||||
?>
|
||||
<form method="get">
|
||||
<input type="hidden" name="page" value="wp-multi-blocked-users">
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php _e('Suchbegriff', 'wp-multi'); ?></label>
|
||||
<input type="text" name="search" value="<?php echo esc_attr($search_query); ?>" placeholder="<?php esc_attr_e('Benutzername, E-Mail oder IP', 'wp-multi'); ?>">
|
||||
</div>
|
||||
<p><input type="submit" class="wpm-btn" value="<?php esc_attr_e('Suchen', 'wp-multi'); ?>"></p>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
echo '</div>';
|
||||
|
||||
wpmt_admin_card_open(__('Gesperrte Benutzer', 'wp-multi'));
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php _e('Benutzername', 'wp-multi'); ?></th>
|
||||
<th><?php _e('E-Mail-Adresse', 'wp-multi'); ?></th>
|
||||
<th><?php _e('IP-Adresse', 'wp-multi'); ?></th>
|
||||
<th><?php _e('Aktionen', 'wp-multi'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($blocked_users) : ?>
|
||||
<?php foreach ($blocked_users as $user) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html($user->username); ?></td>
|
||||
<td><?php echo esc_html($user->email); ?></td>
|
||||
<td><?php echo esc_html($user->ip_address); ?></td>
|
||||
<td>
|
||||
<a href="<?php echo esc_url(wp_nonce_url(admin_url('admin.php?page=wp-multi-blocked-users&delete=' . $user->id), 'wp_multi_delete_user_' . $user->id)); ?>" class="wpm-btn wpm-btn--danger"><?php _e('Löschen', 'wp-multi'); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr>
|
||||
<td colspan="4"><?php _e('Keine gesperrten Benutzer gefunden.', 'wp-multi'); ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
function wp_multi_check_blocked_user($commentdata) {
|
||||
global $wpdb;
|
||||
$username = isset($commentdata['comment_author']) ? $commentdata['comment_author'] : '';
|
||||
$email = isset($commentdata['comment_author_email']) ? $commentdata['comment_author_email'] : '';
|
||||
$ip_address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
|
||||
$blocked_user = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}blocked_users WHERE username = %s OR email = %s OR ip_address = %s",
|
||||
$username, $email, $ip_address
|
||||
));
|
||||
if ($blocked_user) {
|
||||
wp_die('Ihr Kommentar konnte nicht abgesendet werden, da Sie gesperrt sind. Bitte wenden Sie sich an den Support.');
|
||||
}
|
||||
return $commentdata;
|
||||
}
|
||||
add_filter('preprocess_comment', 'wp_multi_check_blocked_user');
|
||||
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Gast-Lesezeichen
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Verbessertes Gast-Lesezeichen-Plugin mit erhöhter Sicherheit und Benutzerfreundlichkeit
|
||||
*/
|
||||
|
||||
|
||||
define('STATISTIK_MANAGER_BOOKMARK_POST_TYPE', 'bookmark');
|
||||
define('STATISTIK_MANAGER_COOKIE_NAME', 'guest_token');
|
||||
define('STATISTIK_MANAGER_COOKIE_DURATION', 30 * DAY_IN_SECONDS);
|
||||
define('STATISTIK_MANAGER_BOOKMARKS_CACHE_KEY', 'statistik_manager_bookmarks_');
|
||||
|
||||
/**
|
||||
* Erstellt den benutzerdefinierten Post-Typ für Lesezeichen.
|
||||
*/
|
||||
function statistik_manager_create_bookmark_post_type() {
|
||||
register_post_type(STATISTIK_MANAGER_BOOKMARK_POST_TYPE, [
|
||||
'labels' => [
|
||||
'name' => __('Lesezeichen', 'statistik-manager'),
|
||||
'singular_name' => __('Lesezeichen', 'statistik-manager'),
|
||||
],
|
||||
'public' => false,
|
||||
'show_ui' => false,
|
||||
'show_in_menu' => false,
|
||||
'supports' => ['title', 'custom-fields'],
|
||||
]);
|
||||
}
|
||||
add_action('init', 'statistik_manager_create_bookmark_post_type');
|
||||
|
||||
/**
|
||||
* Generiert oder holt den Gast-Token.
|
||||
*
|
||||
* @return string Der Gast-Token.
|
||||
*/
|
||||
function statistik_manager_get_guest_token() {
|
||||
$guest_token = isset($_COOKIE[STATISTIK_MANAGER_COOKIE_NAME]) ? sanitize_text_field($_COOKIE[STATISTIK_MANAGER_COOKIE_NAME]) : null;
|
||||
|
||||
if (!$guest_token) {
|
||||
$guest_token = wp_generate_uuid4();
|
||||
setcookie(
|
||||
STATISTIK_MANAGER_COOKIE_NAME,
|
||||
$guest_token,
|
||||
time() + STATISTIK_MANAGER_COOKIE_DURATION,
|
||||
COOKIEPATH,
|
||||
COOKIE_DOMAIN,
|
||||
is_ssl(), // Secure
|
||||
true // HttpOnly
|
||||
);
|
||||
}
|
||||
|
||||
return $guest_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert ein Lesezeichen für einen Gast.
|
||||
*
|
||||
* @param int $post_id Post-ID des Lesezeichens.
|
||||
*/
|
||||
function statistik_manager_save_bookmark($post_id) {
|
||||
$guest_token = statistik_manager_get_guest_token();
|
||||
update_post_meta($post_id, '_guest_token', $guest_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruft die Lesezeichen eines Gastes ab.
|
||||
*
|
||||
* @return array Liste der Lesezeichen.
|
||||
*/
|
||||
function statistik_manager_get_guest_bookmarks() {
|
||||
$guest_token = statistik_manager_get_guest_token();
|
||||
$cache_key = STATISTIK_MANAGER_BOOKMARKS_CACHE_KEY . md5($guest_token);
|
||||
$bookmarks = get_transient($cache_key);
|
||||
|
||||
if ($bookmarks !== false) {
|
||||
return $bookmarks;
|
||||
}
|
||||
|
||||
$args = [
|
||||
'post_type' => STATISTIK_MANAGER_BOOKMARK_POST_TYPE,
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => '_guest_token',
|
||||
'value' => $guest_token,
|
||||
],
|
||||
],
|
||||
'posts_per_page' => -1,
|
||||
'post_status' => 'publish',
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
|
||||
$bookmarks_query = new WP_Query($args);
|
||||
$bookmarks = $bookmarks_query->posts;
|
||||
|
||||
set_transient($cache_key, $bookmarks, HOUR_IN_SECONDS);
|
||||
return $bookmarks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht ein Lesezeichen via AJAX.
|
||||
*/
|
||||
function statistik_manager_delete_bookmark() {
|
||||
check_ajax_referer('statistik_manager_bookmark_nonce', 'nonce');
|
||||
|
||||
if (!isset($_POST['bookmark_id']) || !isset($_COOKIE[STATISTIK_MANAGER_COOKIE_NAME])) {
|
||||
wp_send_json_error(['message' => __('Ungültige Anfrage.', 'statistik-manager')]);
|
||||
}
|
||||
|
||||
$bookmark_id = absint($_POST['bookmark_id']);
|
||||
$guest_token = sanitize_text_field($_COOKIE[STATISTIK_MANAGER_COOKIE_NAME]);
|
||||
$stored_token = get_post_meta($bookmark_id, '_guest_token', true);
|
||||
|
||||
if ($stored_token !== $guest_token) {
|
||||
wp_send_json_error(['message' => __('Du kannst nur deine eigenen Lesezeichen löschen.', 'statistik-manager')]);
|
||||
}
|
||||
|
||||
wp_delete_post($bookmark_id, true);
|
||||
delete_transient(STATISTIK_MANAGER_BOOKMARKS_CACHE_KEY . md5($guest_token));
|
||||
wp_send_json_success(['message' => __('Lesezeichen erfolgreich gelöscht.', 'statistik-manager')]);
|
||||
}
|
||||
add_action('wp_ajax_delete_bookmark', 'statistik_manager_delete_bookmark');
|
||||
add_action('wp_ajax_nopriv_delete_bookmark', 'statistik_manager_delete_bookmark');
|
||||
|
||||
/**
|
||||
* Fügt ein Lesezeichen via AJAX hinzu.
|
||||
*/
|
||||
function statistik_manager_add_bookmark_ajax() {
|
||||
check_ajax_referer('statistik_manager_bookmark_nonce', 'nonce');
|
||||
|
||||
if (!isset($_POST['bookmark_url']) || !isset($_POST['bookmark_name'])) {
|
||||
wp_send_json_error(['message' => __('Bitte alle Felder ausfüllen.', 'statistik-manager')]);
|
||||
}
|
||||
|
||||
$bookmark_url = esc_url_raw($_POST['bookmark_url']);
|
||||
$bookmark_name = sanitize_text_field($_POST['bookmark_name']);
|
||||
|
||||
if (empty($bookmark_url) || empty($bookmark_name)) {
|
||||
wp_send_json_error(['message' => __('Ungültige URL oder Name.', 'statistik-manager')]);
|
||||
}
|
||||
|
||||
// Prüfen, ob die URL bereits existiert
|
||||
$guest_token = statistik_manager_get_guest_token();
|
||||
$args = [
|
||||
'post_type' => STATISTIK_MANAGER_BOOKMARK_POST_TYPE,
|
||||
'meta_query' => [
|
||||
'relation' => 'AND',
|
||||
[
|
||||
'key' => '_guest_token',
|
||||
'value' => $guest_token,
|
||||
],
|
||||
[
|
||||
'key' => '_bookmark_url',
|
||||
'value' => $bookmark_url,
|
||||
],
|
||||
],
|
||||
'posts_per_page' => 1,
|
||||
];
|
||||
|
||||
$existing = new WP_Query($args);
|
||||
if ($existing->have_posts()) {
|
||||
wp_send_json_error(['message' => __('Diese URL ist bereits ein Lesezeichen.', 'statistik-manager')]);
|
||||
}
|
||||
|
||||
// Neues Lesezeichen erstellen
|
||||
$post_id = wp_insert_post([
|
||||
'post_type' => STATISTIK_MANAGER_BOOKMARK_POST_TYPE,
|
||||
'post_title' => $bookmark_name,
|
||||
'post_status' => 'publish',
|
||||
'meta_input' => [
|
||||
'_bookmark_url' => $bookmark_url,
|
||||
'_guest_token' => $guest_token,
|
||||
],
|
||||
]);
|
||||
|
||||
if (is_wp_error($post_id)) {
|
||||
wp_send_json_error(['message' => __('Fehler beim Hinzufügen des Lesezeichens.', 'statistik-manager')]);
|
||||
}
|
||||
|
||||
delete_transient(STATISTIK_MANAGER_BOOKMARKS_CACHE_KEY . md5($guest_token));
|
||||
wp_send_json_success([
|
||||
'message' => __('Lesezeichen erfolgreich hinzugefügt.', 'statistik-manager'),
|
||||
'html' => '<li><button class="delete-bookmark-btn" data-bookmark-id="' . esc_attr($post_id) . '">' . esc_html__('Löschen', 'statistik-manager') . '</button><a href="' . esc_url($bookmark_url) . '" target="_blank">' . esc_html($bookmark_name) . '</a></li>',
|
||||
]);
|
||||
}
|
||||
add_action('wp_ajax_add_bookmark', 'statistik_manager_add_bookmark_ajax');
|
||||
add_action('wp_ajax_nopriv_add_bookmark', 'statistik_manager_add_bookmark_ajax');
|
||||
|
||||
/**
|
||||
* Zeigt die Lesezeichen eines Gastes an.
|
||||
*
|
||||
* @return string HTML-Ausgabe der Lesezeichen.
|
||||
*/
|
||||
function statistik_manager_display_bookmarks() {
|
||||
$bookmarks = statistik_manager_get_guest_bookmarks();
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="statistik-manager-bookmarks">
|
||||
<h3><?php esc_html_e('Gespeicherte Lesezeichen', 'statistik-manager'); ?></h3>
|
||||
<?php if (empty($bookmarks)) : ?>
|
||||
<p><?php esc_html_e('Keine Lesezeichen gefunden.', 'statistik-manager'); ?></p>
|
||||
<?php else : ?>
|
||||
<ul>
|
||||
<?php foreach ($bookmarks as $bookmark) : ?>
|
||||
<li>
|
||||
<button class="delete-bookmark-btn" data-bookmark-id="<?php echo esc_attr($bookmark->ID); ?>">
|
||||
<?php esc_html_e('Löschen', 'statistik-manager'); ?>
|
||||
</button>
|
||||
<a href="<?php echo esc_url(get_post_meta($bookmark->ID, '_bookmark_url', true)); ?>" target="_blank">
|
||||
<?php echo esc_html(get_the_title($bookmark)); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcode zum Anzeigen der Lesezeichen.
|
||||
*
|
||||
* @return string HTML-Ausgabe.
|
||||
*/
|
||||
function statistik_manager_bookmarks_shortcode() {
|
||||
return statistik_manager_display_bookmarks();
|
||||
}
|
||||
add_shortcode('display_bookmarks', 'statistik_manager_bookmarks_shortcode');
|
||||
|
||||
/**
|
||||
* Shortcode zum Hinzufügen eines Lesezeichens.
|
||||
*
|
||||
* @return string HTML-Ausgabe.
|
||||
*/
|
||||
function statistik_manager_add_bookmark_shortcode() {
|
||||
ob_start();
|
||||
?>
|
||||
<form id="add-bookmark-form" class="statistik-manager-bookmark-form">
|
||||
<input type="hidden" name="nonce" value="<?php echo esc_attr(wp_create_nonce('statistik_manager_bookmark_nonce')); ?>">
|
||||
<div class="form-field">
|
||||
<label for="bookmark_name"><?php esc_html_e('Name des Lesezeichens:', 'statistik-manager'); ?></label>
|
||||
<input type="text" name="bookmark_name" id="bookmark_name" required>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="bookmark_url"><?php esc_html_e('URL des Lesezeichens:', 'statistik-manager'); ?></label>
|
||||
<input type="url" name="bookmark_url" id="bookmark_url" required>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<button type="submit"><?php esc_html_e('Lesezeichen hinzufügen', 'statistik-manager'); ?></button>
|
||||
</div>
|
||||
<div class="form-message"></div>
|
||||
</form>
|
||||
<style>
|
||||
.statistik-manager-bookmark-form { max-width: 500px; margin: 20px 0; }
|
||||
.statistik-manager-bookmark-form .form-field { margin-bottom: 15px; }
|
||||
.statistik-manager-bookmark-form label { display: block; margin-bottom: 5px; font-weight: bold; }
|
||||
.statistik-manager-bookmark-form input { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
|
||||
.statistik-manager-bookmark-form button { background-color: #0073aa; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
|
||||
.statistik-manager-bookmark-form button:hover { background-color: #005177; }
|
||||
.statistik-manager-bookmark-form .form-message { margin-top: 10px; color: green; }
|
||||
.statistik-manager-bookmark-form .form-message.error { color: red; }
|
||||
.statistik-manager-bookmarks ul { list-style: none; padding: 0; }
|
||||
.statistik-manager-bookmarks li { margin-bottom: 10px; display: flex; align-items: center; }
|
||||
.statistik-manager-bookmarks button { margin-right: 10px; background-color: #d63638; color: white; padding: 5px 10px; border: none; border-radius: 4px; cursor: pointer; }
|
||||
.statistik-manager-bookmarks button:hover { background-color: #a12b2d; }
|
||||
@media (max-width: 600px) {
|
||||
.statistik-manager-bookmark-form input, .statistik-manager-bookmark-form button { font-size: 14px; }
|
||||
.statistik-manager-bookmarks li { flex-direction: column; align-items: flex-start; }
|
||||
.statistik-manager-bookmarks button { margin-bottom: 5px; }
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('add_bookmark', 'statistik_manager_add_bookmark_shortcode');
|
||||
|
||||
/**
|
||||
* Fügt JavaScript für AJAX-Interaktionen hinzu.
|
||||
*/
|
||||
function statistik_manager_add_bookmark_script() {
|
||||
if (!is_singular() && !has_shortcode(get_the_content(), 'add_bookmark') && !has_shortcode(get_the_content(), 'display_bookmarks')) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
$('#add-bookmark-form').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $form = $(this);
|
||||
var $message = $form.find('.form-message');
|
||||
var data = {
|
||||
action: 'add_bookmark',
|
||||
nonce: $form.find('[name="nonce"]').val(),
|
||||
bookmark_url: $form.find('#bookmark_url').val(),
|
||||
bookmark_name: $form.find('#bookmark_name').val(),
|
||||
};
|
||||
|
||||
$.post('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', data, function(response) {
|
||||
$message.removeClass('error');
|
||||
if (response.success) {
|
||||
$message.addClass('success').text(response.data.message);
|
||||
$('.statistik-manager-bookmarks ul').append(response.data.html);
|
||||
$form.find('#bookmark_url, #bookmark_name').val('');
|
||||
} else {
|
||||
$message.addClass('error').text(response.data.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '.delete-bookmark-btn', function() {
|
||||
var $button = $(this);
|
||||
var bookmarkId = $button.data('bookmark-id');
|
||||
var data = {
|
||||
action: 'delete_bookmark',
|
||||
nonce: $('#add-bookmark-form [name="nonce"]').val(),
|
||||
bookmark_id: bookmarkId,
|
||||
};
|
||||
|
||||
$.post('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', data, function(response) {
|
||||
var $message = $('.statistik-manager-bookmark-form .form-message');
|
||||
$message.removeClass('error success');
|
||||
if (response.success) {
|
||||
$message.addClass('success').text(response.data.message);
|
||||
$button.closest('li').remove();
|
||||
} else {
|
||||
$message.addClass('error').text(response.data.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
add_action('wp_footer', 'statistik_manager_add_bookmark_script');
|
||||
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Brute-Force-Schutz
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Schutz vor Brute-Force-Angriffen mit wöchentlicher Zusammenfassung
|
||||
* Sperr-E-Mails entfernt, Zusammenfassung deaktivierbar unter Benutzer mit verbessertem Design
|
||||
*/
|
||||
|
||||
// Funktion zur Erfassung der echten IP-Adresse des Benutzers
|
||||
function get_user_ip() {
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) {
|
||||
return $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
$ip = trim($ips[0]);
|
||||
return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
return filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
|
||||
}
|
||||
|
||||
// Funktion zur Verfolgung von fehlgeschlagenen Anmeldeversuchen
|
||||
function wp_multi_log_failed_login($username) {
|
||||
global $wpdb;
|
||||
|
||||
$ip = get_user_ip();
|
||||
if ($ip === '0.0.0.0') {
|
||||
return;
|
||||
}
|
||||
|
||||
$blocked_table = $wpdb->prefix . 'blocked_ips';
|
||||
$attempts_table = $wpdb->prefix . 'login_attempts';
|
||||
$block_threshold = 5;
|
||||
|
||||
// Anmeldeversuch in attempts-Tabelle speichern
|
||||
$wpdb->insert(
|
||||
$attempts_table,
|
||||
array(
|
||||
'ip' => $ip,
|
||||
'username' => $username,
|
||||
'attempt_time' => current_time('mysql'),
|
||||
),
|
||||
array('%s', '%s', '%s')
|
||||
);
|
||||
|
||||
// Prüfen, ob IP bereits in blocked_ips existiert
|
||||
$row = $wpdb->get_row($wpdb->prepare("SELECT * FROM $blocked_table WHERE ip = %s", $ip));
|
||||
|
||||
if ($row) {
|
||||
$wpdb->update(
|
||||
$blocked_table,
|
||||
array(
|
||||
'attempts' => $row->attempts + 1,
|
||||
'last_attempt' => current_time('mysql'),
|
||||
),
|
||||
array('ip' => $ip),
|
||||
array('%d', '%s'),
|
||||
array('%s')
|
||||
);
|
||||
$attempts = $row->attempts + 1;
|
||||
} else {
|
||||
$wpdb->insert(
|
||||
$blocked_table,
|
||||
array(
|
||||
'ip' => $ip,
|
||||
'attempts' => 1,
|
||||
'last_attempt' => current_time('mysql'),
|
||||
),
|
||||
array('%s', '%d', '%s')
|
||||
);
|
||||
$attempts = 1;
|
||||
}
|
||||
|
||||
// IP sperren, wenn Schwellenwert erreicht
|
||||
if ($attempts >= $block_threshold) {
|
||||
wp_die(
|
||||
__('Deine IP-Adresse wurde aufgrund zu vieler Fehlversuche gesperrt. Bitte versuche es später noch einmal.', 'wp-multi'),
|
||||
__('Zugriff gesperrt', 'wp-multi'),
|
||||
array('response' => 403)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Hook für fehlgeschlagene Anmeldungen
|
||||
add_action('wp_login_failed', 'wp_multi_log_failed_login', 10, 1);
|
||||
|
||||
// Funktion zur Erstellung der Tabellen
|
||||
function wp_multi_create_blocked_ips_table() {
|
||||
global $wpdb;
|
||||
|
||||
$blocked_table = $wpdb->prefix . 'blocked_ips';
|
||||
$attempts_table = $wpdb->prefix . 'login_attempts';
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
$version = get_option('wp_multi_blocked_ips_version', '1.0');
|
||||
|
||||
if (version_compare($version, '1.1', '<')) {
|
||||
$sql_blocked = "CREATE TABLE $blocked_table (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
ip varchar(45) NOT NULL,
|
||||
attempts int NOT NULL DEFAULT 0,
|
||||
last_attempt datetime NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY ip (ip)
|
||||
) $charset_collate;";
|
||||
|
||||
$sql_attempts = "CREATE TABLE $attempts_table (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
ip varchar(45) NOT NULL,
|
||||
username varchar(255) NOT NULL,
|
||||
attempt_time datetime NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY ip (ip),
|
||||
KEY attempt_time (attempt_time)
|
||||
) $charset_collate;";
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
||||
dbDelta($sql_blocked);
|
||||
dbDelta($sql_attempts);
|
||||
update_option('wp_multi_blocked_ips_version', '1.1');
|
||||
}
|
||||
}
|
||||
register_activation_hook(WP_MULTI_FILE, 'wp_multi_create_blocked_ips_table');
|
||||
|
||||
// Wöchentliche Zusammenfassung
|
||||
function wp_multi_send_weekly_summary() {
|
||||
global $wpdb;
|
||||
|
||||
// Prüfen, ob Zusammenfassung aktiviert ist
|
||||
$summary_enabled = get_option('wp_multi_summary_enabled', 1);
|
||||
if (!$summary_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attempts_table = $wpdb->prefix . 'login_attempts';
|
||||
$last_email_time = get_option('wp_multi_last_summary_email', 0);
|
||||
$current_time = time();
|
||||
|
||||
// Prüfen, ob eine Woche vergangen ist (7 Tage = 604800 Sekunden)
|
||||
if (($current_time - $last_email_time) < 604800) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Zeitraum für die Zusammenfassung (letzte Woche)
|
||||
$week_ago = date('Y-m-d H:i:s', strtotime('-7 days'));
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
// Gesamtzahl der Anmeldeversuche
|
||||
$total_attempts = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM $attempts_table WHERE attempt_time >= %s",
|
||||
$week_ago
|
||||
)
|
||||
);
|
||||
$total_attempts = $total_attempts ? $total_attempts : 0;
|
||||
|
||||
// Top 10 IPs mit den meisten Anmeldeversuchen
|
||||
$top_attempts = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT ip, username, COUNT(*) as attempt_count, MAX(attempt_time) as last_attempt
|
||||
FROM $attempts_table
|
||||
WHERE attempt_time >= %s
|
||||
GROUP BY ip, username
|
||||
ORDER BY attempt_count DESC
|
||||
LIMIT 10",
|
||||
$week_ago
|
||||
)
|
||||
);
|
||||
|
||||
// E-Mail-Inhalt
|
||||
$message = __("Wöchentliche Anmeldeversuche-Zusammenfassung\n\n", 'wp-multi');
|
||||
$message .= sprintf(__("Zeitraum: %s bis %s\n\n", 'wp-multi'), $week_ago, $now);
|
||||
$message .= sprintf(__("Gesamtzahl der Anmeldeversuche: %d\n\n", 'wp-multi'), $total_attempts);
|
||||
$message .= __("Top 10 Anmeldeversuche (nach IP und Benutzername):\n", 'wp-multi');
|
||||
|
||||
if ($top_attempts) {
|
||||
foreach ($top_attempts as $index => $attempt) {
|
||||
$message .= sprintf(
|
||||
__("%d. IP: %s, Benutzername: %s, Versuche: %d, Letzter Versuch: %s\n", 'wp-multi'),
|
||||
$index + 1,
|
||||
$attempt->ip,
|
||||
$attempt->username,
|
||||
$attempt->attempt_count,
|
||||
$attempt->last_attempt
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$message .= __("Keine Anmeldeversuche in diesem Zeitraum.\n", 'wp-multi');
|
||||
}
|
||||
|
||||
// E-Mail an Admin senden
|
||||
$admin_email = get_option('admin_email');
|
||||
wp_mail(
|
||||
$admin_email,
|
||||
__('Wöchentliche Anmeldeversuche-Zusammenfassung', 'wp-multi'),
|
||||
$message,
|
||||
array('Content-Type: text/plain; charset=UTF-8')
|
||||
);
|
||||
|
||||
// Aktualisiere den Zeitstempel der letzten E-Mail
|
||||
update_option('wp_multi_last_summary_email', $current_time);
|
||||
}
|
||||
|
||||
// Planen der wöchentlichen Zusammenfassung (jeden Montag um 8:00 Uhr)
|
||||
function wp_multi_schedule_weekly_summary() {
|
||||
if (!wp_next_scheduled('wp_multi_weekly_summary_event')) {
|
||||
wp_schedule_event(strtotime('next Monday 08:00'), 'weekly', 'wp_multi_weekly_summary_event');
|
||||
}
|
||||
}
|
||||
add_action('wp', 'wp_multi_schedule_weekly_summary');
|
||||
|
||||
// Hook für die Ausführung der Zusammenfassung
|
||||
add_action('wp_multi_weekly_summary_event', 'wp_multi_send_weekly_summary');
|
||||
|
||||
// Einstellungsoption für die Zusammenfassung
|
||||
function wp_multi_users_register_settings() {
|
||||
add_option('wp_multi_summary_enabled', 1);
|
||||
register_setting('wp_multi_users_settings_group', 'wp_multi_summary_enabled', array(
|
||||
'type' => 'integer',
|
||||
'sanitize_callback' => 'absint',
|
||||
'default' => 1,
|
||||
));
|
||||
|
||||
// Settings Section hinzufügen
|
||||
add_settings_section(
|
||||
'wp_multi_security_section',
|
||||
__('Brute-Force-Schutz Einstellungen', 'wp-multi'),
|
||||
'wp_multi_security_section_callback',
|
||||
'wp_multi_users_security_settings'
|
||||
);
|
||||
|
||||
// Settings Field hinzufügen
|
||||
add_settings_field(
|
||||
'wp_multi_summary_enabled',
|
||||
__('Wöchentliche Zusammenfassung', 'wp-multi'),
|
||||
'wp_multi_summary_enabled_callback',
|
||||
'wp_multi_users_security_settings',
|
||||
'wp_multi_security_section'
|
||||
);
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_users_register_settings');
|
||||
|
||||
// Callback für die Settings Section
|
||||
function wp_multi_security_section_callback() {
|
||||
echo '<p>' . __('Konfiguriere die Sicherheitseinstellungen für den Brute-Force-Schutz deiner Website. Aktiviere oder deaktiviere die wöchentliche Zusammenfassung der fehlgeschlagenen Anmeldeversuche.', 'wp-multi') . '</p>';
|
||||
}
|
||||
|
||||
// Callback für das Settings Field
|
||||
function wp_multi_summary_enabled_callback() {
|
||||
$summary_enabled = get_option('wp_multi_summary_enabled', 1);
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_summary_enabled" id="wp_multi_summary_enabled" value="1" <?php checked(1, $summary_enabled); ?> />
|
||||
<label for="wp_multi_summary_enabled"><?php _e('Wöchentliche E-Mail-Zusammenfassung für fehlgeschlagene Anmeldeversuche aktivieren', 'wp-multi'); ?></label>
|
||||
<p class="description"><?php _e('Wenn aktiviert, erhält der Administrator jeden Montag um 8:00 Uhr eine E-Mail mit einer Zusammenfassung der fehlgeschlagenen Anmeldeversuche der letzten Woche.', 'wp-multi'); ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Blockierte IPs & Sicherheitseinstellungen werden zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Einstellungsseite unter Benutzer
|
||||
function wp_multi_users_security_settings_page() {
|
||||
wpmt_admin_page_open(
|
||||
__('Benutzer-Sicherheit', 'wp-multi'),
|
||||
__('Brute-Force-Schutz und Benachrichtigungen für fehlgeschlagene Logins', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open(__('Brute-Force-Schutz', 'wp-multi'));
|
||||
?>
|
||||
<p><?php _e('Verwalte die Einstellungen für den Schutz vor Brute-Force-Angriffen. Passe die Benachrichtigungen für fehlgeschlagene Anmeldeversuche an.', 'wp-multi'); ?></p>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('wp_multi_users_settings_group');
|
||||
do_settings_sections('wp_multi_users_security_settings');
|
||||
submit_button(__('Einstellungen speichern', 'wp-multi'));
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Anzeige der blockierten IPs im Admin-Bereich
|
||||
function wp_multi_display_blocked_ips() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'blocked_ips';
|
||||
|
||||
$five_days_ago = date('Y-m-d H:i:s', strtotime('-5 days'));
|
||||
$per_page = 50;
|
||||
$page = max(1, isset($_GET['paged']) ? intval($_GET['paged']) : 1);
|
||||
$offset = ($page - 1) * $per_page;
|
||||
|
||||
$blocked_ips = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT * FROM $table_name WHERE last_attempt >= %s ORDER BY last_attempt DESC LIMIT %d OFFSET %d",
|
||||
$five_days_ago,
|
||||
$per_page,
|
||||
$offset
|
||||
)
|
||||
);
|
||||
|
||||
$total_ips = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE last_attempt >= %s", $five_days_ago));
|
||||
$total_pages = ceil($total_ips / $per_page);
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Blockierte IPs', 'wp-multi'),
|
||||
__('Vom Brute-Force-Schutz erfasste IP-Adressen der letzten 5 Tage', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
if (empty($blocked_ips)) {
|
||||
wpmt_admin_notice('info', __('Keine blockierten IPs gefunden.', 'wp-multi'));
|
||||
} else {
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php _e('ID', 'wp-multi'); ?></th>
|
||||
<th><?php _e('IP-Adresse', 'wp-multi'); ?></th>
|
||||
<th><?php _e('Versuche', 'wp-multi'); ?></th>
|
||||
<th><?php _e('Letzter Versuch', 'wp-multi'); ?></th>
|
||||
<th><?php _e('Aktionen', 'wp-multi'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($blocked_ips as $ip) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html($ip->id); ?></td>
|
||||
<td><?php echo esc_html($ip->ip); ?></td>
|
||||
<td><span class="wpm-badge <?php echo $ip->attempts >= 5 ? 'wpm-badge--danger' : 'wpm-badge--warning'; ?>"><?php echo esc_html($ip->attempts); ?></span></td>
|
||||
<td><?php echo esc_html($ip->last_attempt); ?></td>
|
||||
<td>
|
||||
<a class="wpm-btn wpm-btn--danger" href="<?php echo esc_url(wp_nonce_url(admin_url('admin-post.php?action=remove_blocked_ip&id=' . $ip->id), 'wp_multi_remove_blocked_ip_' . $ip->id)); ?>">
|
||||
<?php _e('Entfernen', 'wp-multi'); ?>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php if ($total_pages > 1) : ?>
|
||||
<div class="tablenav">
|
||||
<div class="tablenav-pages">
|
||||
<?php
|
||||
echo paginate_links(array(
|
||||
'base' => add_query_arg('paged', '%#%'),
|
||||
'format' => '',
|
||||
'prev_text' => __('«'),
|
||||
'next_text' => __('»'),
|
||||
'total' => $total_pages,
|
||||
'current' => $page,
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
}
|
||||
wpmt_admin_card_close();
|
||||
|
||||
// Aufräumen: alte Einträge mit wenigen Versuchen entfernen
|
||||
$three_days_ago = date('Y-m-d H:i:s', strtotime('-3 days'));
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM $table_name WHERE attempts < 10 AND last_attempt < %s",
|
||||
$three_days_ago
|
||||
)
|
||||
);
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Funktion zum Entfernen einer blockierten IP
|
||||
function wp_multi_remove_blocked_ip() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('Du hast nicht die erforderlichen Berechtigungen.', 'wp-multi'), '', array('response' => 403));
|
||||
}
|
||||
|
||||
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||
|
||||
if (!$id || !isset($_GET['_wpnonce']) || !wp_verify_nonce(wp_unslash($_GET['_wpnonce']), 'wp_multi_remove_blocked_ip_' . $id)) {
|
||||
wp_die(__('Ungültige oder abgelaufene Anfrage.', 'wp-multi'), '', array('response' => 403));
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if ($id > 0) {
|
||||
$table_name = $wpdb->prefix . 'blocked_ips';
|
||||
$wpdb->delete($table_name, array('id' => $id), array('%d'));
|
||||
}
|
||||
|
||||
wp_safe_redirect(admin_url('admin.php?page=wp_multi_blocked_ips'));
|
||||
exit;
|
||||
}
|
||||
add_action('admin_post_remove_blocked_ip', 'wp_multi_remove_blocked_ip');
|
||||
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Kommentarfilter (Telefon/E-Mail/URL/IP/Schimpfwörter)
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Kommentarfilter: Telefonnummern, E-Mails, URLs, IPs und Schimpfwörter
|
||||
*/
|
||||
|
||||
// Einstellungen für den Kommentarfilter registrieren (auf der bestehenden "Sicherheit"-Seite)
|
||||
function wp_multi_comment_filter_register_settings() {
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_filter_phone', ['sanitize_callback' => 'absint', 'default' => 0]);
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_filter_email', ['sanitize_callback' => 'absint', 'default' => 0]);
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_filter_url', ['sanitize_callback' => 'absint', 'default' => 0]);
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_filter_ip', ['sanitize_callback' => 'absint', 'default' => 0]);
|
||||
register_setting('wp_multi_security_settings', 'wp_multi_filter_swearwords', ['sanitize_callback' => 'absint', 'default' => 0]);
|
||||
|
||||
add_settings_section(
|
||||
'wp_multi_comment_filter_section',
|
||||
__('Kommentarfilter', 'wp-multi'),
|
||||
'wp_multi_comment_filter_section_callback',
|
||||
'wp-multi-security'
|
||||
);
|
||||
|
||||
add_settings_field('wp_multi_filter_phone', __('Telefonnummern filtern', 'wp-multi'), 'wp_multi_filter_phone_callback', 'wp-multi-security', 'wp_multi_comment_filter_section');
|
||||
add_settings_field('wp_multi_filter_email', __('E-Mail-Adressen filtern', 'wp-multi'), 'wp_multi_filter_email_callback', 'wp-multi-security', 'wp_multi_comment_filter_section');
|
||||
add_settings_field('wp_multi_filter_url', __('URLs filtern', 'wp-multi'), 'wp_multi_filter_url_callback', 'wp-multi-security', 'wp_multi_comment_filter_section');
|
||||
add_settings_field('wp_multi_filter_ip', __('IP-Adressen filtern', 'wp-multi'), 'wp_multi_filter_ip_callback', 'wp-multi-security', 'wp_multi_comment_filter_section');
|
||||
add_settings_field('wp_multi_filter_swearwords', __('Schimpfwörter filtern', 'wp-multi'), 'wp_multi_filter_swearwords_callback', 'wp-multi-security', 'wp_multi_comment_filter_section');
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_comment_filter_register_settings');
|
||||
|
||||
function wp_multi_comment_filter_section_callback() {
|
||||
echo '<p>' . esc_html__('Lege fest, welche Inhalte in Kommentaren automatisch durch * ersetzt werden, statt den ganzen Kommentar zu blockieren.', 'wp-multi') . '</p>';
|
||||
}
|
||||
|
||||
function wp_multi_filter_phone_callback() {
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_filter_phone" value="1" <?php checked(1, get_option('wp_multi_filter_phone', 0)); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_filter_email_callback() {
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_filter_email" value="1" <?php checked(1, get_option('wp_multi_filter_email', 0)); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_filter_url_callback() {
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_filter_url" value="1" <?php checked(1, get_option('wp_multi_filter_url', 0)); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_filter_ip_callback() {
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_filter_ip" value="1" <?php checked(1, get_option('wp_multi_filter_ip', 0)); ?>>
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_multi_filter_swearwords_callback() {
|
||||
?>
|
||||
<input type="checkbox" name="wp_multi_filter_swearwords" value="1" <?php checked(1, get_option('wp_multi_filter_swearwords', 0)); ?>>
|
||||
<small><?php esc_html_e('Nutzt die Wortliste aus includes/bad-words.json.', 'wp-multi'); ?></small>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Lädt die Schimpfwortliste aus includes/bad-words.json (gecached via Transient)
|
||||
function wp_multi_get_bad_words() {
|
||||
$cache_key = 'wp_multi_bad_words';
|
||||
$words = get_transient($cache_key);
|
||||
if ($words !== false) {
|
||||
return $words;
|
||||
}
|
||||
|
||||
$words = [];
|
||||
$file_path = plugin_dir_path(WP_MULTI_FILE) . 'includes/bad-words.json';
|
||||
if (file_exists($file_path)) {
|
||||
$data = json_decode(file_get_contents($file_path), true);
|
||||
if (is_array($data) && !empty($data['words']) && is_array($data['words'])) {
|
||||
$words = $data['words'];
|
||||
}
|
||||
}
|
||||
|
||||
set_transient($cache_key, $words, DAY_IN_SECONDS);
|
||||
return $words;
|
||||
}
|
||||
|
||||
// Baut die (teuren) Regex-Patterns aus der Schimpfwortliste und cached sie.
|
||||
// Die Wortliste hat mehrere tausend Einträge - in ein einziges Regex gepackt
|
||||
// überschreitet das die PCRE-Größenlimits, daher wird in Blöcken gearbeitet.
|
||||
function wp_multi_get_bad_words_patterns() {
|
||||
$cache_key = 'wp_multi_bad_words_patterns';
|
||||
$patterns = get_transient($cache_key);
|
||||
if ($patterns !== false) {
|
||||
return $patterns;
|
||||
}
|
||||
|
||||
$words = wp_multi_get_bad_words();
|
||||
$patterns = [];
|
||||
foreach (array_chunk($words, 500) as $chunk) {
|
||||
$patterns[] = '/\b(' . implode('|', array_map('preg_quote', $chunk)) . ')\b/iu';
|
||||
}
|
||||
|
||||
set_transient($cache_key, $patterns, DAY_IN_SECONDS);
|
||||
return $patterns;
|
||||
}
|
||||
|
||||
// Ersetzt einen Regex-Treffer durch eine gleich lange Folge von *
|
||||
function wp_multi_mask_match($matches) {
|
||||
$match = $matches[0];
|
||||
return str_repeat('*', function_exists('mb_strlen') ? mb_strlen($match) : strlen($match));
|
||||
}
|
||||
|
||||
// Wendet den Kommentarfilter (Telefon, E-Mail, URL, IP, Schimpfwörter) auf einen Text an
|
||||
function wp_multi_apply_comment_content_filter($content) {
|
||||
if (get_option('wp_multi_filter_phone', 0)) {
|
||||
$content = preg_replace_callback('/(?:\+?\d[\d\s\-\/\(\)]{6,}\d)/', 'wp_multi_mask_match', $content);
|
||||
}
|
||||
|
||||
if (get_option('wp_multi_filter_email', 0)) {
|
||||
$content = preg_replace_callback('/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/', 'wp_multi_mask_match', $content);
|
||||
}
|
||||
|
||||
if (get_option('wp_multi_filter_url', 0)) {
|
||||
$content = preg_replace_callback('#\b(?:https?://|www\.)[^\s<>"]+#i', 'wp_multi_mask_match', $content);
|
||||
}
|
||||
|
||||
if (get_option('wp_multi_filter_ip', 0)) {
|
||||
$content = preg_replace_callback('/\b(?:\d{1,3}\.){3}\d{1,3}\b/', 'wp_multi_mask_match', $content);
|
||||
}
|
||||
|
||||
if (get_option('wp_multi_filter_swearwords', 0)) {
|
||||
foreach (wp_multi_get_bad_words_patterns() as $pattern) {
|
||||
$content = preg_replace_callback($pattern, 'wp_multi_mask_match', $content);
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Text-Copy-Schutz
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Text Copy Schutz und Schutz vor Entwicklertools
|
||||
*/
|
||||
|
||||
|
||||
// JavaScript für die Kopierschutz-Funktion einbinden
|
||||
function wp_multi_enqueue_scripts() {
|
||||
wp_add_inline_script('jquery', "
|
||||
jQuery(document).ready(function($) {
|
||||
// Verhindert das Öffnen der Entwicklertools mit F12, Strg+Shift+I und Strg+Shift+C
|
||||
$(document).keydown(function(e) {
|
||||
// Blockiert F12, Strg + Shift + I, Strg + Shift + C (Entwicklertools)
|
||||
if (e.keyCode == 123 || (e.ctrlKey && e.shiftKey && e.keyCode == 73) || (e.ctrlKey && e.shiftKey && e.keyCode == 67)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// Verhindert das Öffnen des Quellcodes mit Strg + U (view-source)
|
||||
if ((e.ctrlKey && e.keyCode == 85) || (e.ctrlKey && e.shiftKey && e.keyCode == 85)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// Verhindert den Zugriff auf die Konsole mit Strg + Shift + J (Konsole-Tab)
|
||||
if ((e.ctrlKey && e.shiftKey && e.keyCode == 74) || (e.metaKey && e.altKey && e.keyCode == 74)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// Verhindert das Öffnen des Quellcodes mit view-source
|
||||
if (e.ctrlKey && e.keyCode == 85) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Verhindert das Öffnen des Kontextmenüs (Rechtsklick)
|
||||
$('body').on('contextmenu', function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// Kopierschutz-Funktion
|
||||
$('body').on('copy', function(e) {
|
||||
e.preventDefault();
|
||||
var selectedText = window.getSelection().toString();
|
||||
var numericText = selectedText.replace(/./g, function(char) {
|
||||
return Math.floor(Math.random() * 10);
|
||||
});
|
||||
|
||||
e.originalEvent.clipboardData.setData('text/plain', numericText);
|
||||
});
|
||||
});
|
||||
");
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'wp_multi_enqueue_scripts');
|
||||
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Custom Admin-Links
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Custom Link im Admin Sidebar hinzufügen
|
||||
*/
|
||||
|
||||
|
||||
// Die benutzerdefinierten Admin-Link-Seiten werden zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Callback-Funktion für das Anzeigen der benutzerdefinierten Seiten
|
||||
function wp_stat_notice_custom_page() {
|
||||
$current_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : '';
|
||||
$custom_pages = get_option('wp_stat_notice_custom_pages', []);
|
||||
|
||||
if (empty($custom_pages) || !is_array($custom_pages)) {
|
||||
wpmt_admin_page_open(__('Benutzerdefinierte Seite', 'wp-stat-notice'));
|
||||
wpmt_admin_notice('error', __('Keine benutzerdefinierten Seiten gefunden.', 'wp-stat-notice'));
|
||||
wpmt_admin_page_close();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($custom_pages as $page) {
|
||||
if ($page['slug'] === $current_slug) {
|
||||
wpmt_admin_page_open($page['title']);
|
||||
wpmt_admin_card_open();
|
||||
if (isset($page['url']) && filter_var($page['url'], FILTER_VALIDATE_URL)) {
|
||||
echo '<script>window.open("' . esc_url($page['url']) . '", "_blank");</script>';
|
||||
echo '<p>' . __('Die externe Seite wird in einem neuen Fenster geöffnet.', 'wp-stat-notice') . '</p>';
|
||||
echo '<p><a href="' . esc_url($page['url']) . '" target="_blank" class="wpm-btn wpm-btn--primary">' . esc_html__('Seite manuell öffnen', 'wp-stat-notice') . '</a></p>';
|
||||
} else {
|
||||
echo '<p>' . __('Dies ist eine benutzerdefinierte Seite im Admin-Bereich.', 'wp-stat-notice') . '</p>';
|
||||
}
|
||||
wpmt_admin_card_close();
|
||||
wpmt_admin_page_close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wpmt_admin_page_open(__('Benutzerdefinierte Seite', 'wp-stat-notice'));
|
||||
wpmt_admin_notice('error', __('Seite nicht gefunden.', 'wp-stat-notice'));
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Funktion zum Hinzufügen und Verwalten benutzerdefinierter Seiten
|
||||
function wp_stat_notice_add_custom_page_form() {
|
||||
$dashicons = [
|
||||
'dashicons-admin-links', 'dashicons-admin-site', 'dashicons-admin-home',
|
||||
'dashicons-admin-plugins', 'dashicons-admin-users', 'dashicons-analytics',
|
||||
'dashicons-archive', 'dashicons-book', 'dashicons-calendar',
|
||||
'dashicons-camera', 'dashicons-cart', 'dashicons-cloud',
|
||||
'dashicons-clipboard', 'dashicons-clock', 'dashicons-cloud-upload',
|
||||
'dashicons-email', 'dashicons-heart', 'dashicons-laptop',
|
||||
'dashicons-lock', 'dashicons-phone', 'dashicons-rss',
|
||||
'dashicons-search', 'dashicons-settings', 'dashicons-share',
|
||||
'dashicons-tag', 'dashicons-thumbs-up', 'dashicons-welcome-learn-more',
|
||||
'dashicons-welcome-write-blog'
|
||||
];
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php _e('Benutzerdefinierten Adminlink hinzufügen', 'wp-stat-notice'); ?></h1>
|
||||
|
||||
<!-- Formular zum Hinzufügen -->
|
||||
<form method="post" action="">
|
||||
<?php wp_nonce_field('wp_stat_notice_add_page', 'wp_stat_notice_nonce'); ?>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row"><label for="page_title"><?php _e('Titel der Seite', 'wp-stat-notice'); ?></label></th>
|
||||
<td><input type="text" name="page_title" id="page_title" required class="regular-text"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="page_url"><?php _e('URL der Seite (optional)', 'wp-stat-notice'); ?></label></th>
|
||||
<td><input type="url" name="page_url" id="page_url" class="regular-text" placeholder="https://example.com"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="page_slug"><?php _e('Slug der Seite', 'wp-stat-notice'); ?></label></th>
|
||||
<td><input type="text" name="page_slug" id="page_slug" required class="regular-text"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="page_icon"><?php _e('Dashicon auswählen', 'wp-stat-notice'); ?></label></th>
|
||||
<td>
|
||||
<select name="page_icon" id="page_icon" onchange="updateIconPreview(this)">
|
||||
<?php foreach ($dashicons as $dashicon): ?>
|
||||
<option value="<?php echo esc_attr($dashicon); ?>"><?php echo esc_html($dashicon); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div id="icon-preview" class="dashicons" style="font-size: 24px; margin-top: 10px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p><input type="submit" name="add_custom_page" class="button button-primary" value="<?php _e('Seite hinzufügen', 'wp-stat-notice'); ?>"></p>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
// Formularverarbeitung für Hinzufügen
|
||||
if (isset($_POST['add_custom_page']) && check_admin_referer('wp_stat_notice_add_page', 'wp_stat_notice_nonce')) {
|
||||
$title = sanitize_text_field($_POST['page_title']);
|
||||
$url = !empty($_POST['page_url']) ? esc_url_raw($_POST['page_url']) : '';
|
||||
$slug = sanitize_key($_POST['page_slug']);
|
||||
$icon = in_array($_POST['page_icon'], $dashicons, true) ? $_POST['page_icon'] : 'dashicons-admin-links';
|
||||
|
||||
if (empty($title) || empty($slug)) {
|
||||
echo '<div class="notice notice-error"><p>' . __('Titel und Slug sind erforderlich.', 'wp-stat-notice') . '</p></div>';
|
||||
} else {
|
||||
$custom_pages = get_option('wp_stat_notice_custom_pages', []);
|
||||
$slugs = array_column($custom_pages, 'slug');
|
||||
if (in_array($slug, $slugs)) {
|
||||
echo '<div class="notice notice-error"><p>' . __('Dieser Slug wird bereits verwendet.', 'wp-stat-notice') . '</p></div>';
|
||||
} else {
|
||||
$custom_pages[] = ['title' => $title, 'url' => $url, 'slug' => $slug, 'icon' => $icon];
|
||||
update_option('wp_stat_notice_custom_pages', $custom_pages);
|
||||
echo '<div class="updated"><p>' . __('Benutzerdefinierte Seite wurde hinzugefügt!', 'wp-stat-notice') . '</p></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verwaltung der Seiten
|
||||
$custom_pages = get_option('wp_stat_notice_custom_pages', []);
|
||||
if (!empty($custom_pages)) {
|
||||
echo '<h2>' . __('Verwaltung der benutzerdefinierten Seiten', 'wp-stat-notice') . '</h2>';
|
||||
echo '<table class="widefat fixed" cellspacing="0">';
|
||||
echo '<thead><tr><th>' . __('Titel', 'wp-stat-notice') . '</th><th>' . __('URL', 'wp-stat-notice') . '</th><th>' . __('Slug', 'wp-stat-notice') . '</th><th>' . __('Aktionen', 'wp-stat-notice') . '</th></tr></thead>';
|
||||
echo '<tbody>';
|
||||
foreach ($custom_pages as $index => $page) {
|
||||
echo '<tr>';
|
||||
echo '<td>' . esc_html($page['title']) . '</td>';
|
||||
echo '<td>' . esc_html($page['url'] ?: '-') . '</td>';
|
||||
echo '<td>' . esc_html($page['slug']) . '</td>';
|
||||
$delete_url = wp_nonce_url(admin_url('admin.php?page=wp-stat-notice-custom-page&delete=' . $index), 'wp_stat_notice_delete_page_' . $index);
|
||||
echo '<td><a href="' . esc_url(admin_url('admin.php?page=wp-stat-notice-custom-page&edit=' . $index)) . '">' . __('Bearbeiten', 'wp-stat-notice') . '</a> | ';
|
||||
echo '<a href="' . esc_url($delete_url) . '" onclick="return confirm(\'' . esc_js(__('Möchtest du diese Seite wirklich löschen?', 'wp-stat-notice')) . '\')">' . __('Löschen', 'wp-stat-notice') . '</a></td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
|
||||
// Bearbeiten
|
||||
if (isset($_GET['edit']) && isset($custom_pages[(int) $_GET['edit']])) {
|
||||
$edit_index = (int) $_GET['edit'];
|
||||
$edit_page = $custom_pages[$edit_index];
|
||||
|
||||
echo '<h2>' . __('Seite bearbeiten', 'wp-stat-notice') . '</h2>';
|
||||
?>
|
||||
<form method="post" action="">
|
||||
<?php wp_nonce_field('wp_stat_notice_edit_page', 'wp_stat_notice_nonce'); ?>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row"><label for="edit_page_title"><?php _e('Titel der Seite', 'wp-stat-notice'); ?></label></th>
|
||||
<td><input type="text" name="edit_page_title" id="edit_page_title" value="<?php echo esc_attr($edit_page['title']); ?>" required class="regular-text"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="edit_page_url"><?php _e('URL der Seite (optional)', 'wp-stat-notice'); ?></label></th>
|
||||
<td><input type="url" name="edit_page_url" id="edit_page_url" value="<?php echo esc_attr($edit_page['url']); ?>" class="regular-text"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="edit_page_slug"><?php _e('Slug der Seite', 'wp-stat-notice'); ?></label></th>
|
||||
<td><input type="text" name="edit_page_slug" id="edit_page_slug" value="<?php echo esc_attr($edit_page['slug']); ?>" required class="regular-text"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="edit_page_icon"><?php _e('Dashicon', 'wp-stat-notice'); ?></label></th>
|
||||
<td>
|
||||
<select name="edit_page_icon" id="edit_page_icon" onchange="updateIconPreview(this)">
|
||||
<?php foreach ($dashicons as $dashicon): ?>
|
||||
<option value="<?php echo esc_attr($dashicon); ?>" <?php selected($edit_page['icon'], $dashicon); ?>><?php echo esc_html($dashicon); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div id="icon-preview" class="dashicons <?php echo esc_attr($edit_page['icon']); ?>" style="font-size: 24px; margin-top: 10px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p><input type="submit" name="save_custom_page" class="button button-primary" value="<?php _e('Änderungen speichern', 'wp-stat-notice'); ?>"></p>
|
||||
</form>
|
||||
<?php
|
||||
|
||||
if (isset($_POST['save_custom_page']) && check_admin_referer('wp_stat_notice_edit_page', 'wp_stat_notice_nonce')) {
|
||||
$title = sanitize_text_field($_POST['edit_page_title']);
|
||||
$url = !empty($_POST['edit_page_url']) ? esc_url_raw($_POST['edit_page_url']) : '';
|
||||
$slug = sanitize_key($_POST['edit_page_slug']);
|
||||
$icon = in_array($_POST['edit_page_icon'], $dashicons, true) ? $_POST['edit_page_icon'] : 'dashicons-admin-links';
|
||||
|
||||
if (empty($title) || empty($slug)) {
|
||||
echo '<div class="notice notice-error"><p>' . __('Titel und Slug sind erforderlich.', 'wp-stat-notice') . '</p></div>';
|
||||
} else {
|
||||
$custom_pages[$edit_index] = ['title' => $title, 'url' => $url, 'slug' => $slug, 'icon' => $icon];
|
||||
update_option('wp_stat_notice_custom_pages', $custom_pages);
|
||||
echo '<div class="updated"><p>' . __('Seite erfolgreich bearbeitet!', 'wp-stat-notice') . '</p></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Löschen
|
||||
if (isset($_GET['delete']) && isset($custom_pages[(int) $_GET['delete']])) {
|
||||
check_admin_referer('wp_stat_notice_delete_page_' . (int) $_GET['delete']);
|
||||
$delete_index = (int) $_GET['delete'];
|
||||
unset($custom_pages[$delete_index]);
|
||||
$custom_pages = array_values($custom_pages);
|
||||
update_option('wp_stat_notice_custom_pages', $custom_pages);
|
||||
echo '<div class="updated"><p>' . __('Seite wurde gelöscht.', 'wp-stat-notice') . '</p></div>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateIconPreview(select) {
|
||||
const preview = select.nextElementSibling;
|
||||
preview.className = 'dashicons ' + select.value;
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('#page_icon, #edit_page_icon').forEach(select => {
|
||||
updateIconPreview(select);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Der Menüpunkt "Admin-Link hinzufügen" wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Custom Text Box
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Custom Text Box
|
||||
*/
|
||||
|
||||
// Funktion zur Registrierung der zusätzlichen Einstellungen für benutzerdefinierte Texte
|
||||
function wp_multi_custom_text_register_settings() {
|
||||
add_option('wp_multi_custom_texts', '');
|
||||
add_option('wp_multi_second_custom_text', '');
|
||||
add_option('wp_multi_enable_custom_texts', '1');
|
||||
register_setting('wp_multi_custom_text_options_group', 'wp_multi_custom_texts');
|
||||
register_setting('wp_multi_custom_text_options_group', 'wp_multi_second_custom_text');
|
||||
register_setting('wp_multi_custom_text_options_group', 'wp_multi_enable_custom_texts');
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_custom_text_register_settings');
|
||||
|
||||
// Der Custom-Text-Menüpunkt wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Funktion zum Erstellen der Einstellungsseite
|
||||
function wp_multi_custom_text_settings_page_content() {
|
||||
wpmt_admin_page_open(
|
||||
__('Custom Text', 'wp-multi'),
|
||||
__('Vordefinierte Textboxen am Ende deiner Beiträge', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields('wp_multi_custom_text_options_group'); ?>
|
||||
<table class="form-table">
|
||||
<tr valign="top">
|
||||
<th scope="row"><?php _e('Custom Texte aktivieren', 'wp-multi'); ?></th>
|
||||
<td>
|
||||
<input type="checkbox" name="wp_multi_enable_custom_texts" value="1" <?php checked(1, get_option('wp_multi_enable_custom_texts'), true); ?> />
|
||||
<p class="description"><?php _e('Aktiviere oder deaktiviere die Anzeige der benutzerdefinierten Texte auf der Webseite.', 'wp-multi'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<th scope="row"><?php _e('Custom Texte', 'wp-multi'); ?></th>
|
||||
<td>
|
||||
<textarea name="wp_multi_custom_texts" rows="10" cols="50" class="large-text"><?php echo esc_textarea(get_option('wp_multi_custom_texts')); ?></textarea>
|
||||
<p class="description"><?php _e('Gib jeden Text in einer neuen Zeile ein.', 'wp-multi'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<th scope="row"><?php _e('Zweiter Custom Text', 'wp-multi'); ?></th>
|
||||
<td>
|
||||
<textarea name="wp_multi_second_custom_text" rows="10" cols="50" class="large-text"><?php echo esc_textarea(get_option('wp_multi_second_custom_text')); ?></textarea>
|
||||
<p class="description"><?php _e('Gib den zweiten Custom Text ein, der über der ersten Box angezeigt wird.', 'wp-multi'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Anzeige der Custom Texts in einer Box im Frontend
|
||||
function wp_multi_custom_text_display($content) {
|
||||
$enable_custom_texts = get_option('wp_multi_enable_custom_texts', '1');
|
||||
if ($enable_custom_texts !== '1') {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if (is_single()) {
|
||||
global $post;
|
||||
$guest_author_name = get_post_meta($post->ID, '_guest_author', true);
|
||||
$author_name = !empty($guest_author_name) ? $guest_author_name : get_the_author();
|
||||
$custom_texts = get_option('wp_multi_custom_texts', '');
|
||||
$second_custom_texts = get_option('wp_multi_second_custom_text', '');
|
||||
$custom_texts_array = array_filter(array_map('trim', explode("\n", $custom_texts)));
|
||||
$second_custom_texts_array = array_filter(array_map('trim', explode("\n", $second_custom_texts)));
|
||||
$selected_custom_text = get_post_meta($post->ID, '_custom_text_choice', true);
|
||||
$selected_second_custom_text = get_post_meta($post->ID, '_second_custom_text_choice', true);
|
||||
|
||||
if (empty($custom_texts_array) && empty($second_custom_texts_array)) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$output = '<div class="custom-text-box" style="margin-top: 40px; padding: 20px; background-color: #f0f0f0; border: 2px solid #ddd; border-radius: 10px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); max-width: 400px; width: auto; font-size: 16px; line-height: 1.2; clear: both; margin-left: auto; margin-right: 0; display: block; margin-bottom: 20px; position: relative;">';
|
||||
$output .= '<p><strong>' . __('Autor:', 'wp-multi') . ' ' . esc_html($author_name);
|
||||
if ($selected_second_custom_text !== '' && isset($second_custom_texts_array[$selected_second_custom_text])) {
|
||||
$output .= ' | ' . esc_html($second_custom_texts_array[$selected_second_custom_text]);
|
||||
}
|
||||
$output .= '</strong></p>';
|
||||
if ($selected_custom_text !== '' && isset($custom_texts_array[$selected_custom_text])) {
|
||||
$output .= '<p><em>' . esc_html($custom_texts_array[$selected_custom_text]) . '</em></p>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
|
||||
return $content . $output;
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
add_filter('the_content', 'wp_multi_custom_text_display');
|
||||
|
||||
// Funktion zum Hinzufügen der Meta-Box für beide Custom Texts
|
||||
function wp_multi_add_custom_text_fields($post) {
|
||||
$custom_texts = get_option('wp_multi_custom_texts');
|
||||
$custom_texts_array = array_filter(array_map('trim', explode("\n", $custom_texts)));
|
||||
$second_custom_text = get_option('wp_multi_second_custom_text');
|
||||
$second_custom_text_array = array_filter(array_map('trim', explode("\n", $second_custom_text)));
|
||||
$selected_custom_text = get_post_meta($post->ID, '_custom_text_choice', true);
|
||||
$selected_second_custom_text = get_post_meta($post->ID, '_second_custom_text_choice', true);
|
||||
wp_nonce_field('wp_multi_custom_text_choice_nonce', 'wp_multi_custom_text_choice_nonce_field');
|
||||
?>
|
||||
<label for="custom_text_choice"><?php _e('Wähle den Custom Text (unterer Bereich):', 'wp-multi'); ?></label>
|
||||
<select name="custom_text_choice" id="custom_text_choice" class="widefat">
|
||||
<option value=""><?php _e('Keinen Text auswählen', 'wp-multi'); ?></option>
|
||||
<?php foreach ($custom_texts_array as $key => $value) { ?>
|
||||
<option value="<?php echo esc_attr($key); ?>" <?php selected($selected_custom_text, $key); ?>><?php echo esc_html($value); ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<label for="second_custom_text_choice"><?php _e('Wähle den zweiten Custom Text (oberer Bereich):', 'wp-multi'); ?></label>
|
||||
<select name="second_custom_text_choice" id="second_custom_text_choice" class="widefat">
|
||||
<option value=""><?php _e('Keinen Text auswählen', 'wp-multi'); ?></option>
|
||||
<?php foreach ($second_custom_text_array as $key => $value) { ?>
|
||||
<option value="<?php echo esc_attr($key); ?>" <?php selected($selected_second_custom_text, $key); ?>><?php echo esc_html($value); ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Meta-Box hinzufügen
|
||||
add_action('add_meta_boxes', function() {
|
||||
add_meta_box('wp_multi_custom_text', __('Custom Text Auswahl', 'wp-multi'), 'wp_multi_add_custom_text_fields', 'post', 'normal', 'high');
|
||||
});
|
||||
|
||||
// Speichern der benutzerdefinierten Textauswahl im Beitrag
|
||||
function wp_multi_save_custom_text_choice($post_id) {
|
||||
if (!isset($_POST['wp_multi_custom_text_choice_nonce_field']) || !wp_verify_nonce($_POST['wp_multi_custom_text_choice_nonce_field'], 'wp_multi_custom_text_choice_nonce')) {
|
||||
return;
|
||||
}
|
||||
if (!current_user_can('edit_post', $post_id)) {
|
||||
return;
|
||||
}
|
||||
if (isset($_POST['custom_text_choice'])) {
|
||||
update_post_meta($post_id, '_custom_text_choice', sanitize_text_field(wp_unslash($_POST['custom_text_choice'])));
|
||||
}
|
||||
if (isset($_POST['second_custom_text_choice'])) {
|
||||
update_post_meta($post_id, '_second_custom_text_choice', sanitize_text_field(wp_unslash($_POST['second_custom_text_choice'])));
|
||||
}
|
||||
}
|
||||
add_action('save_post', 'wp_multi_save_custom_text_choice');
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Login deaktivieren (pro Benutzer)
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Login deaktivieren
|
||||
*/
|
||||
|
||||
|
||||
// Checkbox zum Benutzerprofil hinzufügen
|
||||
function wp_multi_add_disable_login_checkbox($user) {
|
||||
?>
|
||||
<h3>Login deaktivieren</h3>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th><label for="disable_login">Login deaktivieren</label></th>
|
||||
<td>
|
||||
<input type="checkbox" name="disable_login" id="disable_login" value="1" <?php checked( get_user_meta($user->ID, 'disable_login', true), 1 ); ?> />
|
||||
<span class="description">Markiere diese Option, um den Login des Benutzers zu deaktivieren.</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Speichern der Checkbox-Option
|
||||
function wp_multi_save_disable_login_checkbox($user_id) {
|
||||
if ( isset( $_POST['disable_login'] ) ) {
|
||||
update_user_meta( $user_id, 'disable_login', 1 );
|
||||
} else {
|
||||
delete_user_meta( $user_id, 'disable_login' );
|
||||
}
|
||||
}
|
||||
|
||||
// Die Checkbox in das Benutzerprofil einfügen
|
||||
add_action( 'show_user_profile', 'wp_multi_add_disable_login_checkbox' );
|
||||
add_action( 'edit_user_profile', 'wp_multi_add_disable_login_checkbox' );
|
||||
|
||||
// Speichern der Checkbox-Option
|
||||
add_action( 'personal_options_update', 'wp_multi_save_disable_login_checkbox' );
|
||||
add_action( 'edit_user_profile_update', 'wp_multi_save_disable_login_checkbox' );
|
||||
|
||||
// Login blockieren, wenn die Checkbox aktiviert ist
|
||||
function wp_multi_block_login_if_disabled($user_login, $user) {
|
||||
// Prüfen, ob der Benutzer das Flag "Login deaktivieren" gesetzt hat
|
||||
if ( get_user_meta( $user->ID, 'disable_login', true ) ) {
|
||||
// Fehlermeldung anzeigen, wenn der Login deaktiviert ist
|
||||
wp_die( 'Dein Login wurde deaktiviert. Bitte kontaktiere den Administrator.' );
|
||||
}
|
||||
}
|
||||
|
||||
// Der Filter wird bei jedem Login-Versuch angewendet
|
||||
add_action( 'wp_login', 'wp_multi_block_login_if_disabled', 10, 2 );
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Sperre Trash-Mail-Adressen
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Sperre Trash Mail Adressen
|
||||
*/
|
||||
|
||||
|
||||
// Funktion zum Laden der Liste von Einweg-Mail-Anbietern
|
||||
function load_disposable_email_list() {
|
||||
$file_path = plugin_dir_path(WP_MULTI_FILE) . 'includes/disposable_email_blocklist.conf'; // Pfad zur Datei im includes-Ordner
|
||||
if (file_exists($file_path)) {
|
||||
return file($file_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
// Funktion zum Überprüfen der E-Mail-Adresse eines Kommentators
|
||||
function check_disposable_email($commentdata) {
|
||||
$disposable_list = load_disposable_email_list();
|
||||
$email = $commentdata['comment_author_email'];
|
||||
$domain = substr(strrchr($email, "@"), 1); // Nur die Domain extrahieren
|
||||
|
||||
// Überprüfen, ob die Domain auf der Liste steht
|
||||
if (in_array($domain, $disposable_list)) {
|
||||
wp_die(__('Fehler: Trash-Mail-Adressen sind in Kommentaren nicht erlaubt.'));
|
||||
}
|
||||
|
||||
return $commentdata;
|
||||
}
|
||||
|
||||
// Die Funktion wird beim Absenden eines Kommentars ausgeführt
|
||||
add_filter('preprocess_comment', 'check_disposable_email');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Gast-Autoren
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Gast Autoren
|
||||
*/
|
||||
|
||||
// Gast-Autor Eingabefeld in der Sidebar im Admin-Bereich hinzufügen
|
||||
function wp_multi_add_guest_author_field() {
|
||||
add_meta_box(
|
||||
'guest_author_meta_box',
|
||||
__('Gast-Autor', 'wp-multi'),
|
||||
'wp_multi_guest_author_field',
|
||||
['post', 'page', 'dein_custom_post_type'],
|
||||
'side',
|
||||
'high'
|
||||
);
|
||||
}
|
||||
add_action('add_meta_boxes', 'wp_multi_add_guest_author_field');
|
||||
|
||||
// Callback-Funktion, die das Eingabefeld anzeigt
|
||||
function wp_multi_guest_author_field($post) {
|
||||
$guest_author = get_post_meta($post->ID, '_guest_author', true);
|
||||
wp_nonce_field('wp_multi_guest_author_nonce', 'wp_multi_guest_author_nonce_field');
|
||||
?>
|
||||
<label for="guest_author"><?php _e('Gast-Autor Name:', 'wp-multi'); ?></label>
|
||||
<input type="text" id="guest_author" name="guest_author" value="<?php echo esc_attr($guest_author); ?>" class="widefat" />
|
||||
<?php
|
||||
}
|
||||
|
||||
// Speichern der Gast-Autor Daten
|
||||
function wp_multi_save_guest_author_meta($post_id) {
|
||||
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
||||
if (!isset($_POST['wp_multi_guest_author_nonce_field']) || !wp_verify_nonce($_POST['wp_multi_guest_author_nonce_field'], 'wp_multi_guest_author_nonce')) return;
|
||||
if (!current_user_can('edit_post', $post_id)) return;
|
||||
if (isset($_POST['guest_author'])) {
|
||||
$guest_author = sanitize_text_field(wp_unslash($_POST['guest_author']));
|
||||
update_post_meta($post_id, '_guest_author', $guest_author);
|
||||
} else {
|
||||
delete_post_meta($post_id, '_guest_author');
|
||||
}
|
||||
}
|
||||
add_action('save_post', 'wp_multi_save_guest_author_meta');
|
||||
|
||||
// Gast-Autor anzeigen anstelle des regulären Autors im Frontend
|
||||
function wp_multi_display_guest_author($author_name) {
|
||||
if ((is_single() || is_archive() || is_home()) && !is_admin()) {
|
||||
$post = get_post();
|
||||
if ($post) {
|
||||
$guest_author = get_post_meta($post->ID, '_guest_author', true);
|
||||
if (!empty($guest_author)) {
|
||||
$author_name = $guest_author;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $author_name;
|
||||
}
|
||||
add_filter('the_author', 'wp_multi_display_guest_author');
|
||||
|
||||
// Anzeige des Gast-Autors in der Beitragsübersicht (Backend)
|
||||
function wp_multi_add_guest_author_column($columns) {
|
||||
if (isset($columns['author'])) {
|
||||
$columns['guest_author'] = __('Gast-Autor', 'wp-multi');
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
add_filter('manage_posts_columns', 'wp_multi_add_guest_author_column');
|
||||
|
||||
function wp_multi_display_guest_author_column($column_name, $post_id) {
|
||||
if ($column_name == 'guest_author') {
|
||||
$guest_author = get_post_meta($post_id, '_guest_author', true);
|
||||
echo !empty($guest_author) ? esc_html($guest_author) : __('Kein Gast-Autor', 'wp-multi');
|
||||
}
|
||||
}
|
||||
add_action('manage_posts_custom_column', 'wp_multi_display_guest_author_column', 10, 2);
|
||||
|
||||
// Der Gast-Autoren-Menüpunkt wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Callback-Funktion für die Gast-Autor-Übersicht
|
||||
function wp_multi_guest_author_overview_page() {
|
||||
// Sortierparameter aus URL lesen
|
||||
$orderby = isset($_GET['orderby']) ? sanitize_key($_GET['orderby']) : 'guest_author';
|
||||
$order = isset($_GET['order']) && in_array(strtoupper($_GET['order']), ['ASC', 'DESC']) ? strtoupper($_GET['order']) : 'ASC';
|
||||
|
||||
// Gültige Sortierfelder
|
||||
$valid_orderby = ['guest_author' => 'pm.meta_value', 'posts' => 'post_count'];
|
||||
$sql_orderby = isset($valid_orderby[$orderby]) ? $valid_orderby[$orderby] : 'pm.meta_value';
|
||||
$sql_order = $order;
|
||||
|
||||
// Basis-URL für Sortier-Links
|
||||
$base_url = add_query_arg(['page' => 'guest_author_overview'], admin_url('admin.php'));
|
||||
|
||||
global $wpdb;
|
||||
$query = "
|
||||
SELECT pm.meta_value AS guest_author, COUNT(*) AS post_count
|
||||
FROM {$wpdb->posts} p
|
||||
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
|
||||
WHERE pm.meta_key = '_guest_author'
|
||||
AND pm.meta_value != ''
|
||||
AND p.post_status = 'publish'
|
||||
GROUP BY pm.meta_value
|
||||
ORDER BY {$sql_orderby} {$sql_order}
|
||||
";
|
||||
$guest_authors = $wpdb->get_results($query);
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Gast-Autoren', 'wp-multi'),
|
||||
__('Alle Gast-Autoren mit Anzahl ihrer veröffentlichten Beiträge', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="<?php echo esc_url(add_query_arg(['orderby' => 'guest_author', 'order' => ($orderby === 'guest_author' && $order === 'ASC') ? 'DESC' : 'ASC'], $base_url)); ?>">
|
||||
<?php _e('Gast-Autor', 'wp-multi'); ?>
|
||||
<?php if ($orderby === 'guest_author') : ?>
|
||||
<span><?php echo ($order === 'ASC') ? '↑' : '↓'; ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a href="<?php echo esc_url(add_query_arg(['orderby' => 'posts', 'order' => ($orderby === 'posts' && $order === 'ASC') ? 'DESC' : 'ASC'], $base_url)); ?>">
|
||||
<?php _e('Anzahl der Beiträge', 'wp-multi'); ?>
|
||||
<?php if ($orderby === 'posts') : ?>
|
||||
<span><?php echo ($order === 'ASC') ? '↑' : '↓'; ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($guest_authors) : ?>
|
||||
<?php foreach ($guest_authors as $author) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html($author->guest_author); ?></td>
|
||||
<td><span class="wpm-badge"><?php echo esc_html($author->post_count); ?></span></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr><td colspan="2"><?php _e('Keine Gast-Autoren gefunden.', 'wp-multi'); ?></td></tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
|
||||
// Funktion zum Erstellen der Gastautoren-Beitragsseite
|
||||
function wp_multi_create_guest_author_page() {
|
||||
$page_title = __('Gastautor Beiträge', 'wp-multi');
|
||||
$page_slug = 'gastautor-beitraege';
|
||||
$page = get_page_by_path($page_slug);
|
||||
|
||||
if (!$page) {
|
||||
$page_id = wp_insert_post(array(
|
||||
'post_title' => $page_title,
|
||||
'post_name' => $page_slug,
|
||||
'post_content' => '[guest_author_posts]',
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'page',
|
||||
));
|
||||
|
||||
if ($page_id && !is_wp_error($page_id)) {
|
||||
update_option('wp_multi_guest_author_page_id', $page_id);
|
||||
}
|
||||
} else {
|
||||
update_option('wp_multi_guest_author_page_id', $page->ID);
|
||||
}
|
||||
}
|
||||
add_action('init', 'wp_multi_create_guest_author_page');
|
||||
|
||||
// Shortcode für Gastautoren-Liste
|
||||
function wp_multi_guest_author_shortcode() {
|
||||
ob_start();
|
||||
global $wpdb;
|
||||
|
||||
// Alle Gastautoren mit Beitragsanzahl abrufen
|
||||
$query = "
|
||||
SELECT pm.meta_value AS guest_author, COUNT(*) AS post_count
|
||||
FROM {$wpdb->posts} p
|
||||
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
|
||||
WHERE pm.meta_key = '_guest_author'
|
||||
AND pm.meta_value != ''
|
||||
AND p.post_status = 'publish'
|
||||
GROUP BY pm.meta_value
|
||||
ORDER BY pm.meta_value ASC
|
||||
";
|
||||
$guest_authors = $wpdb->get_results($query);
|
||||
|
||||
// URL der Gastautoren-Beitragsseite
|
||||
$guest_author_page_id = get_option('wp_multi_guest_author_page_id');
|
||||
$guest_author_page_url = $guest_author_page_id ? get_permalink($guest_author_page_id) : '#';
|
||||
|
||||
?>
|
||||
<div id="guest-author-section" class="container mx-auto px-4 py-8">
|
||||
<!-- Gastautoren-Liste -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
||||
<?php if ($guest_authors) : ?>
|
||||
<?php foreach ($guest_authors as $author) : ?>
|
||||
<a href="<?php echo esc_url(add_query_arg('guest_author', urlencode($author->guest_author), $guest_author_page_url)); ?>" class="guest-author-card bg-white p-6 rounded-lg shadow-md hover:shadow-lg transition">
|
||||
<h3 class="text-xl font-semibold text-gray-800"><?php echo esc_html($author->guest_author); ?></h3>
|
||||
<p class="text-gray-600"><?php echo esc_html($author->post_count); ?> <?php _e('Beiträge', 'wp-multi'); ?></p>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<p class="col-span-2 text-center text-gray-600"><?php _e('Keine Gastautoren gefunden.', 'wp-multi'); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tailwind CSS CDN -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<?php
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('guest_authors', 'wp_multi_guest_author_shortcode');
|
||||
|
||||
// Shortcode für Gastautoren-Beiträge
|
||||
function wp_multi_guest_author_posts_shortcode() {
|
||||
ob_start();
|
||||
|
||||
$guest_author = isset($_GET['guest_author']) ? sanitize_text_field(wp_unslash($_GET['guest_author'])) : '';
|
||||
|
||||
?>
|
||||
<div id="guest-author-posts" class="container mx-auto px-4 py-8">
|
||||
<h2 class="text-2xl font-semibold text-gray-800 mb-4">
|
||||
<?php
|
||||
if ($guest_author) {
|
||||
printf(__('Beiträge von %s', 'wp-multi'), esc_html($guest_author));
|
||||
} else {
|
||||
_e('Beiträge auswählen', 'wp-multi');
|
||||
}
|
||||
?>
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<?php
|
||||
if ($guest_author) {
|
||||
$args = array(
|
||||
'post_type' => ['post', 'page', 'dein_custom_post_type'],
|
||||
'post_status' => 'publish',
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_guest_author',
|
||||
'value' => $guest_author,
|
||||
'compare' => '='
|
||||
)
|
||||
),
|
||||
'tax_query' => array(
|
||||
array(
|
||||
'taxonomy' => 'category',
|
||||
'field' => 'slug',
|
||||
'terms' => 'series',
|
||||
'operator' => 'NOT IN'
|
||||
)
|
||||
),
|
||||
'posts_per_page' => -1
|
||||
);
|
||||
|
||||
$query = new WP_Query($args);
|
||||
|
||||
|
||||
|
||||
if ($query->have_posts()) {
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
// Beitragsinhalt abrufen und kürzen
|
||||
$content = get_the_content();
|
||||
$content = wp_strip_all_tags($content); // HTML-Tags entfernen
|
||||
$trimmed_content = wp_trim_words($content, 30, '...');
|
||||
?>
|
||||
<div class="post-card bg-white p-6 rounded-lg shadow-md">
|
||||
<h3 class="text-lg font-medium text-gray-800">
|
||||
<a href="<?php the_permalink(); ?>" class="hover:text-blue-600"><?php the_title(); ?></a>
|
||||
</h3>
|
||||
<p class="text-gray-600 line-clamp-3"><?php echo esc_html($trimmed_content); ?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
wp_reset_postdata();
|
||||
} else {
|
||||
?>
|
||||
<p class="col-span-2 text-gray-600"><?php _e('Keine Beiträge gefunden.', 'wp-multi'); ?></p>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
?>
|
||||
<p class="col-span-2 text-gray-600"><?php _e('Wählen Sie einen Gastautor aus, um die Beiträge anzuzeigen.', 'wp-multi'); ?></p>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tailwind CSS CDN -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<?php
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('guest_author_posts', 'wp_multi_guest_author_posts_shortcode');
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Login-Design
|
||||
*
|
||||
* Ermöglicht die eigene Gestaltung der WordPress-Login-Seite:
|
||||
* Logo, Hintergrund (Farbe/Bild), Formular-Farbe, Button- und Linkfarbe
|
||||
* sowie eigenes CSS. Wird über den Loader in wp-multi.php eingebunden.
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Einstellungen registrieren
|
||||
*/
|
||||
function wp_multi_login_design_register() {
|
||||
$group = 'wp_multi_login_design_group';
|
||||
register_setting($group, 'wp_multi_login_form_text', ['sanitize_callback' => 'sanitize_hex_color', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_logo', ['sanitize_callback' => 'esc_url_raw', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_logo_home', ['sanitize_callback' => 'absint', 'default' => 1]);
|
||||
register_setting($group, 'wp_multi_login_bg_color', ['sanitize_callback' => 'sanitize_hex_color', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_bg_image', ['sanitize_callback' => 'esc_url_raw', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_bg_size', ['sanitize_callback' => 'wp_multi_login_design_sanitize_bg_size', 'default' => 'cover']);
|
||||
register_setting($group, 'wp_multi_login_form_bg', ['sanitize_callback' => 'sanitize_hex_color', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_button', ['sanitize_callback' => 'sanitize_hex_color', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_link', ['sanitize_callback' => 'sanitize_hex_color', 'default' => '']);
|
||||
register_setting($group, 'wp_multi_login_custom_css', ['sanitize_callback' => 'wp_multi_login_design_sanitize_css', 'default' => '']);
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_login_design_register');
|
||||
|
||||
// Eigenes CSS grob absichern (kein </style>-Ausbruch, keine Tags)
|
||||
function wp_multi_login_design_sanitize_css($css) {
|
||||
$css = (string) $css;
|
||||
$css = wp_strip_all_tags($css);
|
||||
return trim($css);
|
||||
}
|
||||
|
||||
// Anzeige-Art des Hintergrundbilds (Whitelist)
|
||||
function wp_multi_login_design_sanitize_bg_size($value) {
|
||||
$allowed = array('cover', 'contain', 'stretch', 'tile', 'center');
|
||||
return in_array($value, $allowed, true) ? $value : 'cover';
|
||||
}
|
||||
|
||||
// Liefert die CSS-Regeln für die gewählte Hintergrund-Anzeigeart
|
||||
function wp_multi_login_design_bg_rules($mode) {
|
||||
switch ($mode) {
|
||||
case 'contain':
|
||||
return 'background-size:contain !important; background-repeat:no-repeat !important; background-position:center !important;';
|
||||
case 'stretch':
|
||||
return 'background-size:100% 100% !important; background-repeat:no-repeat !important; background-position:center !important;';
|
||||
case 'tile':
|
||||
return 'background-size:auto !important; background-repeat:repeat !important;';
|
||||
case 'center':
|
||||
return 'background-size:auto !important; background-repeat:no-repeat !important; background-position:center !important;';
|
||||
case 'cover':
|
||||
default:
|
||||
return 'background-size:cover !important; background-repeat:no-repeat !important; background-position:center !important;';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ausgabe auf der Login-Seite
|
||||
*/
|
||||
function wp_multi_login_design_styles() {
|
||||
$form_text = get_option('wp_multi_login_form_text', '');
|
||||
$logo = get_option('wp_multi_login_logo', '');
|
||||
$bg_color = get_option('wp_multi_login_bg_color', '');
|
||||
$bg_image = get_option('wp_multi_login_bg_image', '');
|
||||
$form_bg = get_option('wp_multi_login_form_bg', '');
|
||||
$button = get_option('wp_multi_login_button', '');
|
||||
$link = get_option('wp_multi_login_link', '');
|
||||
$css = get_option('wp_multi_login_custom_css', '');
|
||||
|
||||
// Nur ausgeben, wenn überhaupt etwas konfiguriert ist
|
||||
if (!$logo && !$bg_color && !$bg_image && !$form_bg && !$button && !$link && !$css && !$form_text) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo "<style id=\"wp-multi-login-design\">\n";
|
||||
|
||||
if ($logo) {
|
||||
printf(
|
||||
"#login h1 a, .login h1 a { background-image:url(%s) !important; background-size:contain !important; background-position:center !important; width:auto !important; height:90px !important; }\n",
|
||||
esc_url($logo)
|
||||
);
|
||||
}
|
||||
if ($bg_color) {
|
||||
printf("body.login { background-color:%s !important; }\n", esc_attr($bg_color));
|
||||
}
|
||||
if ($bg_image) {
|
||||
$bg_size = get_option('wp_multi_login_bg_size', 'cover');
|
||||
printf(
|
||||
"body.login { background-image:url(%s) !important; %s }\n",
|
||||
esc_url($bg_image),
|
||||
wp_multi_login_design_bg_rules($bg_size)
|
||||
);
|
||||
}
|
||||
if ($form_bg) {
|
||||
printf(".login form { background:%s !important; border-radius:8px !important; }\n", esc_attr($form_bg));
|
||||
}
|
||||
if ($button) {
|
||||
printf(".login .button-primary { background:%1\$s !important; border-color:%1\$s !important; box-shadow:none !important; text-shadow:none !important; }\n", esc_attr($button));
|
||||
}
|
||||
if ($link) {
|
||||
printf(".login #nav a, .login #backtoblog a, .login .wp-login-lost-password a { color:%s !important; }\n", esc_attr($link));
|
||||
}
|
||||
if ($form_text) {
|
||||
printf(".login form label, .login form .forgetmenot label { color:%s !important; }\n", esc_attr($form_text));
|
||||
}
|
||||
|
||||
if ($css) {
|
||||
// bereits beim Speichern von Tags befreit
|
||||
echo $css . "\n";
|
||||
}
|
||||
|
||||
echo "</style>\n";
|
||||
}
|
||||
add_action('login_enqueue_scripts', 'wp_multi_login_design_styles');
|
||||
|
||||
// Logo-Link auf die eigene Startseite statt wordpress.org
|
||||
function wp_multi_login_design_headerurl($url) {
|
||||
return get_option('wp_multi_login_logo_home', 1) ? home_url('/') : $url;
|
||||
}
|
||||
add_filter('login_headerurl', 'wp_multi_login_design_headerurl');
|
||||
|
||||
// Logo-Titel = Seitenname
|
||||
function wp_multi_login_design_headertext($text) {
|
||||
return get_option('wp_multi_login_logo_home', 1) ? get_bloginfo('name') : $text;
|
||||
}
|
||||
add_filter('login_headertext', 'wp_multi_login_design_headertext');
|
||||
|
||||
/*
|
||||
* Assets für die Einstellungsseite (Color-Picker + Medienauswahl)
|
||||
*/
|
||||
function wp_multi_login_design_admin_assets($hook) {
|
||||
if ($hook !== 'wp-multi_page_wp_multi_login_design' && $hook !== 'toplevel_page_wp_multi_login_design') {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_style('wp-color-picker');
|
||||
wp_enqueue_script('wp-color-picker');
|
||||
wp_enqueue_media();
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'wp_multi_login_design_admin_assets');
|
||||
|
||||
/*
|
||||
* Einstellungsseite
|
||||
*/
|
||||
function wp_multi_login_design_page() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('Zugriff verweigert.', 'wp-multi'));
|
||||
}
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Login-Design', 'wp-multi'),
|
||||
__('Die WordPress-Login-Seite nach deinen Wünschen gestalten', 'wp-multi')
|
||||
);
|
||||
|
||||
$logo = get_option('wp_multi_login_logo', '');
|
||||
$bg_image = get_option('wp_multi_login_bg_image', '');
|
||||
|
||||
wpmt_admin_notice('info', sprintf(
|
||||
__('Vorschau: %s (in neuem Tab öffnen – als eingeloggter Nutzer wirst du ggf. direkt weitergeleitet, dann kurz ausloggen).', 'wp-multi'),
|
||||
'<a href="' . esc_url(wp_login_url()) . '" target="_blank">' . esc_html(wp_login_url()) . '</a>'
|
||||
));
|
||||
|
||||
wpmt_admin_card_open(__('Gestaltung', 'wp-multi'));
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields('wp_multi_login_design_group'); ?>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Logo', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Ersetzt das WordPress-Logo über dem Formular.', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<div>
|
||||
<input type="text" id="wp_multi_login_logo" name="wp_multi_login_logo" value="<?php echo esc_attr($logo); ?>" placeholder="https://…/logo.png" style="max-width:420px;">
|
||||
<button type="button" class="wpm-btn wpm-media-btn" data-target="wp_multi_login_logo"><?php esc_html_e('Medien', 'wp-multi'); ?></button>
|
||||
<div class="wpm-preview"><?php if ($logo) echo '<img src="' . esc_url($logo) . '" style="max-height:60px;margin-top:8px;">'; ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Logo verlinkt zur Startseite', 'wp-multi'); ?></label>
|
||||
<div><label><input type="checkbox" name="wp_multi_login_logo_home" value="1" <?php checked(1, get_option('wp_multi_login_logo_home', 1)); ?>> <?php esc_html_e('Ja (statt zu wordpress.org)', 'wp-multi'); ?></label></div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Seiten-Hintergrundfarbe', 'wp-multi'); ?></label>
|
||||
<div><input type="text" class="wpm-color" name="wp_multi_login_bg_color" value="<?php echo esc_attr(get_option('wp_multi_login_bg_color', '')); ?>" data-default-color=""></div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Hintergrundbild', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Optional. Überlagert die Hintergrundfarbe.', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<div>
|
||||
<input type="text" id="wp_multi_login_bg_image" name="wp_multi_login_bg_image" value="<?php echo esc_attr($bg_image); ?>" placeholder="https://…/bg.jpg" style="max-width:420px;">
|
||||
<button type="button" class="wpm-btn wpm-media-btn" data-target="wp_multi_login_bg_image"><?php esc_html_e('Medien', 'wp-multi'); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Hintergrundbild-Anzeige', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Wie das Bild die Login-Seite füllt.', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<div>
|
||||
<?php $bg_size = get_option('wp_multi_login_bg_size', 'cover'); ?>
|
||||
<select name="wp_multi_login_bg_size" style="max-width:280px;">
|
||||
<option value="cover" <?php selected($bg_size, 'cover'); ?>><?php esc_html_e('Ausfüllen (beschneidet ggf.)', 'wp-multi'); ?></option>
|
||||
<option value="contain" <?php selected($bg_size, 'contain'); ?>><?php esc_html_e('Anpassen (ganz sichtbar)', 'wp-multi'); ?></option>
|
||||
<option value="stretch" <?php selected($bg_size, 'stretch'); ?>><?php esc_html_e('Strecken (exakt füllen)', 'wp-multi'); ?></option>
|
||||
<option value="tile" <?php selected($bg_size, 'tile'); ?>><?php esc_html_e('Kacheln (wiederholen)', 'wp-multi'); ?></option>
|
||||
<option value="center" <?php selected($bg_size, 'center'); ?>><?php esc_html_e('Zentriert (Originalgröße)', 'wp-multi'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Formular-Hintergrund', 'wp-multi'); ?></label>
|
||||
<div><input type="text" class="wpm-color" name="wp_multi_login_form_bg" value="<?php echo esc_attr(get_option('wp_multi_login_form_bg', '')); ?>" data-default-color=""></div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Formular-Textfarbe', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Farbe der Beschriftungen im Formular (z. B. hell auf dunklem Formular-Hintergrund).', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<div><input type="text" class="wpm-color" name="wp_multi_login_form_text" value="<?php echo esc_attr(get_option('wp_multi_login_form_text', '')); ?>" data-default-color=""></div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Button-Farbe', 'wp-multi'); ?></label>
|
||||
<div><input type="text" class="wpm-color" name="wp_multi_login_button" value="<?php echo esc_attr(get_option('wp_multi_login_button', '')); ?>" data-default-color=""></div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Link-Farbe', 'wp-multi'); ?></label>
|
||||
<div><input type="text" class="wpm-color" name="wp_multi_login_link" value="<?php echo esc_attr(get_option('wp_multi_login_link', '')); ?>" data-default-color=""></div>
|
||||
</div>
|
||||
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label"><?php esc_html_e('Eigenes CSS (Profi)', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Wird zusätzlich auf der Login-Seite ausgegeben.', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<div><textarea name="wp_multi_login_custom_css" rows="6" style="width:100%;max-width:560px;font-family:monospace;"><?php echo esc_textarea(get_option('wp_multi_login_custom_css', '')); ?></textarea></div>
|
||||
</div>
|
||||
|
||||
<?php submit_button(__('Speichern', 'wp-multi')); ?>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
jQuery(function ($) {
|
||||
// Farbwähler
|
||||
if ($.fn.wpColorPicker) { $('.wpm-color').wpColorPicker(); }
|
||||
// Medienauswahl
|
||||
$('.wpm-media-btn').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
var targetId = $(this).data('target');
|
||||
var frame = wp.media({ title: '<?php echo esc_js(__('Bild auswählen', 'wp-multi')); ?>', multiple: false });
|
||||
frame.on('select', function () {
|
||||
var att = frame.state().get('selection').first().toJSON();
|
||||
$('#' + targetId).val(att.url);
|
||||
if (targetId === 'wp_multi_login_logo') {
|
||||
$('.wpm-preview').html('<img src="' + att.url + '" style="max-height:60px;margin-top:8px;">');
|
||||
}
|
||||
});
|
||||
frame.open();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Custom Login-URL
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Custom Login-URL — Admin-Panel-Adresse ändern (versteckt wp-admin / wp-login.php)
|
||||
*
|
||||
* Ersetzt die Standard-Login-Adresse durch einen eigenen Slug, z. B. /team/.
|
||||
* Standardmäßig DEAKTIVIERT (leerer Slug), damit ohne bewusste Aktivierung
|
||||
* nichts an der Erreichbarkeit des Backends geändert wird.
|
||||
*/
|
||||
|
||||
// Liefert den konfigurierten Login-Slug (leer = Feature aus)
|
||||
function wp_multi_login_slug() {
|
||||
$slug = get_option('wp_multi_login_slug', '');
|
||||
return is_string($slug) ? trim($slug, '/') : '';
|
||||
}
|
||||
|
||||
// Feature ist nur aktiv, wenn ein Slug gesetzt ist UND Permalinks aktiv sind
|
||||
function wp_multi_login_active() {
|
||||
return wp_multi_login_slug() !== '' && get_option('permalink_structure') && !is_multisite();
|
||||
}
|
||||
|
||||
// Vollständige neue Login-URL
|
||||
function wp_multi_login_new_url($scheme = null) {
|
||||
return user_trailingslashit(home_url('/', $scheme) . wp_multi_login_slug());
|
||||
}
|
||||
|
||||
// Pfad-Anteil (ohne Domain) der Home-URL, z. B. "" oder "/blog"
|
||||
function wp_multi_login_home_path() {
|
||||
return untrailingslashit((string) parse_url(home_url(), PHP_URL_PATH));
|
||||
}
|
||||
|
||||
// Sendet eine echte 404-Antwort und beendet die Ausführung (verstecktes Login)
|
||||
function wp_multi_login_die_404() {
|
||||
status_header(404);
|
||||
nocache_headers();
|
||||
if (function_exists('wp_die')) {
|
||||
// Nutze die Theme-404 wenn möglich, sonst schlichte Meldung
|
||||
wp_die(__('Seite nicht gefunden.', 'wp-multi'), '404', array('response' => 404));
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ersetzt "wp-login.php" in generierten URLs durch den eigenen Slug
|
||||
function wp_multi_login_filter_url($url, $scheme = null) {
|
||||
if (strpos($url, 'wp-login.php') === false) {
|
||||
return $url;
|
||||
}
|
||||
if (is_ssl()) {
|
||||
$scheme = 'https';
|
||||
}
|
||||
$query = parse_url($url, PHP_URL_QUERY);
|
||||
$args = array();
|
||||
if ($query) {
|
||||
parse_str($query, $args);
|
||||
}
|
||||
$new = wp_multi_login_new_url($scheme);
|
||||
if (!empty($args)) {
|
||||
// add_query_arg kodiert selbst; parse_str liefert bereits dekodierte Werte.
|
||||
$new = add_query_arg($args, $new);
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
|
||||
function wp_multi_login_filter_site_url($url, $path, $scheme, $blog_id = null) {
|
||||
return wp_multi_login_filter_url($url, $scheme);
|
||||
}
|
||||
|
||||
function wp_multi_login_filter_wp_redirect($location) {
|
||||
return wp_multi_login_filter_url($location);
|
||||
}
|
||||
|
||||
// Registriert die Filter und den Request-Handler, sobald WordPress geladen ist
|
||||
function wp_multi_login_init() {
|
||||
if (!wp_multi_login_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter('site_url', 'wp_multi_login_filter_site_url', 10, 4);
|
||||
add_filter('network_site_url', 'wp_multi_login_filter_site_url', 10, 4);
|
||||
add_filter('wp_redirect', 'wp_multi_login_filter_wp_redirect', 10, 1);
|
||||
add_filter('login_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
|
||||
add_filter('logout_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
|
||||
add_filter('lostpassword_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
|
||||
add_filter('register_url', 'wp_multi_login_filter_wp_redirect', 10, 1);
|
||||
}
|
||||
add_action('plugins_loaded', 'wp_multi_login_init', 1);
|
||||
|
||||
// Fängt die eingehende Anfrage ab: geheimer Slug lädt das Login, wp-login.php/wp-admin werden versteckt
|
||||
function wp_multi_login_handle_request() {
|
||||
if (!wp_multi_login_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Systemendpunkte niemals blockieren
|
||||
if ((defined('DOING_AJAX') && DOING_AJAX) || (defined('DOING_CRON') && DOING_CRON) || (defined('REST_REQUEST') && REST_REQUEST)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
|
||||
$path = untrailingslashit((string) parse_url($uri, PHP_URL_PATH));
|
||||
$home_path = wp_multi_login_home_path();
|
||||
$login_path = $home_path . '/' . wp_multi_login_slug();
|
||||
|
||||
// 1) Aufruf des geheimen Slugs → echtes wp-login.php ausliefern
|
||||
if ($path === $login_path) {
|
||||
$GLOBALS['pagenow'] = 'wp-login.php';
|
||||
require_once ABSPATH . 'wp-login.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2) Direkter Aufruf von wp-login.php (nicht über den Slug) → verstecken
|
||||
if (strpos($uri, 'wp-login.php') !== false) {
|
||||
wp_multi_login_die_404();
|
||||
}
|
||||
|
||||
// 3) Der gesamte /wp-admin-Bereich für nicht eingeloggte Besucher → verstecken,
|
||||
// statt zum versteckten Login weiterzuleiten. admin-ajax.php und admin-post.php
|
||||
// bleiben ausdrücklich erreichbar (auch für Gäste / nopriv-Aktionen).
|
||||
if (!is_user_logged_in()) {
|
||||
$admin_path = $home_path . '/wp-admin';
|
||||
$in_admin = ($path === $admin_path || strpos($path, $admin_path . '/') === 0);
|
||||
$is_endpoint = (strpos($uri, 'admin-ajax.php') !== false || strpos($uri, 'admin-post.php') !== false);
|
||||
if ($in_admin && !$is_endpoint) {
|
||||
wp_multi_login_die_404();
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('wp_loaded', 'wp_multi_login_handle_request');
|
||||
|
||||
// Einstellung registrieren (mit Sanitisierung gegen reservierte Slugs)
|
||||
function wp_multi_login_register_setting() {
|
||||
register_setting('wp_multi_login_url_group', 'wp_multi_login_slug', array(
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'wp_multi_login_sanitize_slug',
|
||||
'default' => '',
|
||||
));
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_login_register_setting');
|
||||
|
||||
function wp_multi_login_sanitize_slug($value) {
|
||||
$value = sanitize_title(trim((string) $value, '/'));
|
||||
$reserved = array('wp-admin', 'wp-login', 'wp-content', 'wp-includes', 'admin-ajax', 'admin-post', 'wp-json', 'index');
|
||||
if (in_array($value, $reserved, true)) {
|
||||
add_settings_error('wp_multi_login_slug', 'reserved', __('Dieser Slug ist reserviert und kann nicht verwendet werden.', 'wp-multi'));
|
||||
return '';
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Admin-Seite "Login-URL"
|
||||
function wp_multi_login_url_page() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('Zugriff verweigert.', 'wp-multi'));
|
||||
}
|
||||
|
||||
$slug = wp_multi_login_slug();
|
||||
$pretty = (bool) get_option('permalink_structure');
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Login-URL', 'wp-multi'),
|
||||
__('Eigene Adresse für das Login / Admin-Panel festlegen', 'wp-multi')
|
||||
);
|
||||
|
||||
if (is_multisite()) {
|
||||
wpmt_admin_notice('error', __('Dieses Feature ist in einem Multisite-Netzwerk nicht verfügbar.', 'wp-multi'));
|
||||
wpmt_admin_page_close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$pretty) {
|
||||
wpmt_admin_notice('warning', __('Für dieses Feature müssen „hübsche Permalinks" aktiviert sein (Einstellungen → Permalinks, nicht „Einfach"). Solange das nicht der Fall ist, bleibt die Login-URL unverändert.', 'wp-multi'));
|
||||
}
|
||||
|
||||
wpmt_admin_notice('warning', __('Achtung: Merke dir die neue Adresse gut! Wenn du sie vergisst, kommst du nicht mehr ins Backend und musst das Feld per Datenbank oder FTP zurücksetzen. Leeres Feld = Standard-Login (/wp-login.php) bleibt aktiv.', 'wp-multi'));
|
||||
|
||||
if ($slug && $pretty) {
|
||||
wpmt_admin_notice('success', sprintf(
|
||||
__('Aktive Login-Adresse: %s', 'wp-multi'),
|
||||
'<a href="' . esc_url(wp_multi_login_new_url()) . '"><strong>' . esc_html(wp_multi_login_new_url()) . '</strong></a>'
|
||||
));
|
||||
}
|
||||
|
||||
wpmt_admin_card_open(__('Einstellung', 'wp-multi'));
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields('wp_multi_login_url_group'); ?>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label" for="wp_multi_login_slug"><?php esc_html_e('Login-Slug', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php esc_html_e('Nur Kleinbuchstaben, Zahlen und Bindestriche. Leer lassen = deaktiviert.', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<div>
|
||||
<span style="color:var(--wpm-text-muted);"><?php echo esc_html(trailingslashit(home_url('/'))); ?></span>
|
||||
<input type="text" id="wp_multi_login_slug" name="wp_multi_login_slug" value="<?php echo esc_attr($slug); ?>" placeholder="team" style="max-width:220px; display:inline-block;">
|
||||
</div>
|
||||
</div>
|
||||
<?php submit_button(__('Speichern', 'wp-multi')); ?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Pinnwand
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Admin - Pinnwand
|
||||
*/
|
||||
|
||||
|
||||
// Funktion zum Erstellen der Datenbanktabelle für Nachrichten
|
||||
function wp_multi_create_message_board_table() {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'message_board'; // Tabelle für Nachrichten
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
message text NOT NULL,
|
||||
user_id bigint(20) NOT NULL,
|
||||
created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) $charset_collate;";
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
}
|
||||
register_activation_hook(WP_MULTI_FILE, 'wp_multi_create_message_board_table');
|
||||
|
||||
// Funktion zum Anzeigen der Nachrichten im Adminbereich
|
||||
function wp_multi_add_message_board() {
|
||||
if (!current_user_can('administrator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'message_board';
|
||||
$created = false;
|
||||
|
||||
// Nachricht erstellen (VOR der Ausgabe, damit sie sofort erscheint)
|
||||
if (isset($_POST['submit_message']) && !empty($_POST['new_message'])) {
|
||||
if (!isset($_POST['wp_multi_pinwand_nonce_field']) || !wp_verify_nonce(wp_unslash($_POST['wp_multi_pinwand_nonce_field']), 'wp_multi_pinwand_create_message')) {
|
||||
wp_die(__('Ungültige oder abgelaufene Anfrage.', 'wp-multi'));
|
||||
}
|
||||
$wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'message' => sanitize_textarea_field(wp_unslash($_POST['new_message'])),
|
||||
'user_id' => get_current_user_id(),
|
||||
)
|
||||
);
|
||||
$created = true;
|
||||
}
|
||||
|
||||
$messages = $wpdb->get_results("SELECT * FROM $table_name ORDER BY created_at DESC");
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Pinwand', 'wp-multi'),
|
||||
__('Interne Nachrichten für das Admin-Team', 'wp-multi')
|
||||
);
|
||||
|
||||
if ($created) {
|
||||
wpmt_admin_notice('success', __('Nachricht wurde erfolgreich erstellt.', 'wp-multi'));
|
||||
}
|
||||
|
||||
wpmt_admin_card_open(__('Neue Nachricht erstellen', 'wp-multi'));
|
||||
?>
|
||||
<form method="post">
|
||||
<?php wp_nonce_field('wp_multi_pinwand_create_message', 'wp_multi_pinwand_nonce_field'); ?>
|
||||
<textarea name="new_message" rows="4" required style="width:100%;"></textarea>
|
||||
<p><input type="submit" name="submit_message" value="<?php esc_attr_e('Nachricht erstellen', 'wp-multi'); ?>" class="wpm-btn wpm-btn--primary"></p>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Nachrichten', 'wp-multi'));
|
||||
if ($messages) {
|
||||
echo '<div class="wpm-modules">';
|
||||
foreach ($messages as $message) {
|
||||
$user_info = get_userdata($message->user_id);
|
||||
$author = $user_info ? $user_info->user_login : __('Unbekannt', 'wp-multi');
|
||||
printf(
|
||||
'<div class="wpm-module" style="cursor:pointer;" onclick="openMessagePopup(%d)"><span class="dashicons dashicons-admin-comments"></span><span><span class="wpm-module__title">%s</span><p class="wpm-module__desc">%s</p><p class="wpm-module__desc">%s</p></span></div>',
|
||||
(int) $message->id,
|
||||
esc_html($author),
|
||||
esc_html(date('d-m-Y H:i', strtotime($message->created_at))),
|
||||
esc_html(wp_trim_words($message->message, 20))
|
||||
);
|
||||
}
|
||||
echo '</div>';
|
||||
} else {
|
||||
wpmt_admin_notice('info', __('Keine Nachrichten vorhanden.', 'wp-multi'));
|
||||
}
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
?>
|
||||
|
||||
<div id="messagePopup" style="display:none; position:fixed; top:20%; left:50%; transform:translateX(-50%); background:#fff; padding:24px; border-radius:12px; box-shadow:0 4px 30px rgba(0,0,0,.2); z-index:99999; max-width:600px; width:90%;">
|
||||
<div id="messageContent"></div>
|
||||
<div style="display:flex; gap:10px; margin-top:20px;">
|
||||
<button onclick="closeMessagePopup()" class="wpm-btn wpm-btn--primary"><?php esc_html_e('Schließen', 'wp-multi'); ?></button>
|
||||
<button id="deleteMessageBtn" class="wpm-btn wpm-btn--danger" onclick="deleteMessage()"><?php esc_html_e('Löschen', 'wp-multi'); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var wpMultiPinwandNonce = '<?php echo esc_js(wp_create_nonce('wp_multi_pinwand_nonce')); ?>';
|
||||
|
||||
function openMessagePopup(messageId) {
|
||||
var data = { 'action': 'wp_multi_get_message', 'message_id': messageId, 'nonce': wpMultiPinwandNonce };
|
||||
jQuery.post(ajaxurl, data, function(response) {
|
||||
var messageData = JSON.parse(response);
|
||||
document.getElementById('messageContent').innerHTML = '<h3>' + messageData.created_at + ' (' + messageData.user + ')</h3><p>' + messageData.message + '</p>';
|
||||
document.getElementById('messagePopup').style.display = 'block';
|
||||
document.getElementById('deleteMessageBtn').setAttribute('data-message-id', messageId);
|
||||
});
|
||||
}
|
||||
|
||||
function closeMessagePopup() {
|
||||
document.getElementById('messagePopup').style.display = 'none';
|
||||
}
|
||||
|
||||
function deleteMessage() {
|
||||
var messageId = document.getElementById('deleteMessageBtn').getAttribute('data-message-id');
|
||||
var data = { 'action': 'wp_multi_delete_message', 'message_id': messageId, 'nonce': wpMultiPinwandNonce };
|
||||
jQuery.post(ajaxurl, data, function(response) {
|
||||
if (response == 'success') { closeMessagePopup(); location.reload(); }
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Der Pinwand-Menüpunkt wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Funktion zum Abrufen der vollständigen Nachricht
|
||||
function wp_multi_get_message() {
|
||||
check_ajax_referer('wp_multi_pinwand_nonce', 'nonce');
|
||||
|
||||
if (!current_user_can('administrator')) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
if (isset($_POST['message_id'])) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'message_board';
|
||||
$message_id = intval($_POST['message_id']);
|
||||
$message = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $message_id));
|
||||
|
||||
if ($message) {
|
||||
// Datum im gewünschten Format (DD-MM-JJJJ HH:MM:SS)
|
||||
$formatted_date = date('d-m-Y H:i:s', strtotime($message->created_at));
|
||||
|
||||
echo json_encode([
|
||||
'created_at' => $formatted_date,
|
||||
'message' => nl2br(esc_textarea($message->message)),
|
||||
'user' => get_userdata($message->user_id)->user_login
|
||||
]);
|
||||
}
|
||||
}
|
||||
wp_die();
|
||||
}
|
||||
|
||||
add_action('wp_ajax_wp_multi_get_message', 'wp_multi_get_message');
|
||||
|
||||
// Funktion zum Löschen einer Nachricht
|
||||
function wp_multi_delete_message() {
|
||||
check_ajax_referer('wp_multi_pinwand_nonce', 'nonce');
|
||||
|
||||
if (!current_user_can('administrator')) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
if (isset($_POST['message_id'])) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'message_board';
|
||||
$message_id = intval($_POST['message_id']);
|
||||
$wpdb->delete($table_name, array('id' => $message_id), array('%d'));
|
||||
|
||||
echo 'success';
|
||||
}
|
||||
wp_die();
|
||||
}
|
||||
add_action('wp_ajax_wp_multi_delete_message', 'wp_multi_delete_message');
|
||||
|
||||
// Funktion zum Deaktivieren der Pinwand bei der Deinstallation
|
||||
function wp_multi_delete_message_board_table() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'message_board';
|
||||
$wpdb->query("DROP TABLE IF EXISTS $table_name");
|
||||
}
|
||||
register_deactivation_hook(WP_MULTI_FILE, 'wp_multi_delete_message_board_table');
|
||||
|
||||
// Funktion, um das Dashboard-Widget zu registrieren
|
||||
function wp_multi_dashboard_widget() {
|
||||
wp_add_dashboard_widget(
|
||||
'wp_multi_pinwand_widget', // Widget-ID
|
||||
'Pinwand Übersicht', // Widget-Titel
|
||||
'wp_multi_dashboard_widget_content' // Callback-Funktion
|
||||
);
|
||||
}
|
||||
add_action('wp_dashboard_setup', 'wp_multi_dashboard_widget');
|
||||
|
||||
// Callback-Funktion, die den Inhalt des Widgets erstellt
|
||||
function wp_multi_dashboard_widget_content() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'message_board';
|
||||
$messages = $wpdb->get_results("SELECT * FROM $table_name ORDER BY created_at DESC LIMIT 5"); // Zeige die neuesten 5 Nachrichten an
|
||||
|
||||
if ($messages) {
|
||||
echo '<ul>';
|
||||
foreach ($messages as $message) {
|
||||
$user_info = get_userdata($message->user_id);
|
||||
echo '<li>';
|
||||
echo '<strong>' . esc_html($user_info->user_login) . ' (' . date('d-m-Y H:i:s', strtotime($message->created_at)) . ')</strong>: ';
|
||||
echo wp_trim_words($message->message, 10) . '...'; // Zeigt nur eine Vorschau der Nachricht
|
||||
echo '</li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
} else {
|
||||
echo '<p>Keine neuen Nachrichten.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Notify Dashboard-Zähler
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Admin-Dashboard Nachrichten sende Zähler
|
||||
*/
|
||||
|
||||
|
||||
// Admin Dashboard Widget für Telegram und Discord Nachrichten Zähler
|
||||
function wp_multi_add_dashboard_widgets() {
|
||||
wp_add_dashboard_widget(
|
||||
'wp_multi_dashboard_widget',
|
||||
'Telegram & Discord Nachrichten Zähler',
|
||||
'wp_multi_display_dashboard_widget'
|
||||
);
|
||||
}
|
||||
add_action('wp_dashboard_setup', 'wp_multi_add_dashboard_widgets');
|
||||
|
||||
// Callback-Funktion, die den Inhalt des Widgets anzeigt
|
||||
function wp_multi_display_dashboard_widget() {
|
||||
// Telegram-Nachrichtenzähler
|
||||
$telegram_message_count = get_option('wp_multi_telegram_message_count', 0);
|
||||
// Discord-Nachrichtenzähler
|
||||
$discord_message_count = get_option('wp_multi_discord_message_count', 0);
|
||||
|
||||
// Ausgabe der Zähler
|
||||
echo '<p><strong>Telegram Nachrichten gesendet:</strong> ' . esc_html($telegram_message_count) . '</p>';
|
||||
echo '<p><strong>Discord Nachrichten gesendet:</strong> ' . esc_html($discord_message_count) . '</p>';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Discord-Benachrichtigung
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Discord Notify
|
||||
*/
|
||||
|
||||
// Einstellungsseite für Discord Webhook
|
||||
function wp_multi_settings_page() {
|
||||
wpmt_admin_page_open(
|
||||
__('DC-Notify', 'wp-multi'),
|
||||
__('Discord-Benachrichtigungen bei neuen Beiträgen', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('wp_multi_discord_options_group');
|
||||
do_settings_sections('wp-multi');
|
||||
?>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row">Discord Webhook URL</th>
|
||||
<td>
|
||||
<input type="text" name="wp_multi_discord_webhook" value="<?php echo esc_attr(get_option('wp_multi_discord_webhook')); ?>" size="50">
|
||||
<p class="description">Geben Sie die Webhook-URL für Discord ein, um Benachrichtigungen zu senden.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Bot Name</th>
|
||||
<td>
|
||||
<input type="text" name="wp_multi_discord_bot_name" value="<?php echo esc_attr(get_option('wp_multi_discord_bot_name', 'WP Multi Bot')); ?>" size="50">
|
||||
<p class="description">Geben Sie den Namen des Bots ein, der in Discord angezeigt werden soll.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Discord Nachricht (Vorlage)</th>
|
||||
<td>
|
||||
<textarea name="wp_multi_discord_message_template" rows="4" cols="50"><?php echo esc_textarea(get_option('wp_multi_discord_message_template', 'Beitrag "{post_title}" von {post_author} | Link: {post_url}')); ?></textarea>
|
||||
<p class="description">Passen Sie die Nachricht an, die an Discord gesendet wird. Verwenden Sie Platzhalter wie {post_title}, {post_author}, und {post_url}.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Discord Benutzerrollen ID (für Ping)</th>
|
||||
<td>
|
||||
<input type="text" name="wp_multi_discord_role_id" value="<?php echo esc_attr(get_option('wp_multi_discord_role_id')); ?>" size="50">
|
||||
<p class="description">Geben Sie die ID der Discord-Benutzerrolle ein, die gepingt werden soll (z. B. @everyone).</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Discord Avatar-URL</th>
|
||||
<td>
|
||||
<input type="text" name="wp_multi_discord_avatar_url" value="<?php echo esc_attr(get_option('wp_multi_discord_avatar_url')); ?>" size="50">
|
||||
<p class="description">Geben Sie die URL des Avatar-Bildes ein, das in den Discord-Nachrichten angezeigt werden soll.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Footer Text (Custom Text 2)</th>
|
||||
<td>
|
||||
<input type="text" name="wp_multi_discord_footer_text" value="<?php echo esc_attr(get_option('wp_multi_discord_footer_text')); ?>" size="50">
|
||||
<p class="description">Geben Sie den benutzerdefinierten Text ein, der am Ende der Nachricht angezeigt wird (z. B. "Powered by WP Multi"). Sie können auch Platzhalter wie {post_title}, {post_author} und {post_url} verwenden.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Funktion, um die Einstellungen zu registrieren
|
||||
function wp_multi_register_settings() {
|
||||
register_setting('wp_multi_discord_options_group', 'wp_multi_discord_webhook');
|
||||
register_setting('wp_multi_discord_options_group', 'wp_multi_discord_bot_name');
|
||||
register_setting('wp_multi_discord_options_group', 'wp_multi_discord_message_template');
|
||||
register_setting('wp_multi_discord_options_group', 'wp_multi_discord_role_id');
|
||||
register_setting('wp_multi_discord_options_group', 'wp_multi_discord_avatar_url');
|
||||
register_setting('wp_multi_discord_options_group', 'wp_multi_discord_footer_text');
|
||||
}
|
||||
add_action('admin_init', 'wp_multi_register_settings');
|
||||
|
||||
// Funktion, um die Discord-Benachrichtigung zu senden
|
||||
function wp_multi_send_discord_notification($ID, $post) {
|
||||
$send_notification = get_post_meta($ID, '_wp_multi_checkbox', true);
|
||||
if ($send_notification !== '1') {
|
||||
return;
|
||||
}
|
||||
|
||||
$webhook_url = get_option('wp_multi_discord_webhook');
|
||||
if (empty($webhook_url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bot_name = get_option('wp_multi_discord_bot_name', 'WP Multi Bot');
|
||||
$avatar_url = get_option('wp_multi_discord_avatar_url');
|
||||
$post_title = esc_html(get_the_title($ID));
|
||||
$post_url = esc_url(get_permalink($ID));
|
||||
$post_author = esc_html(get_the_author_meta('display_name', $post->post_author));
|
||||
$content = get_post_field('post_content', $ID);
|
||||
$excerpt = wp_trim_words($content, 60, '...');
|
||||
$role_id = get_option('wp_multi_discord_role_id');
|
||||
$mention_role = (!empty($role_id) && is_numeric($role_id)) ? "<@&" . esc_attr($role_id) . ">" : '';
|
||||
$footer_text = get_option('wp_multi_discord_footer_text');
|
||||
$footer = !empty($footer_text) ? str_replace(
|
||||
['{post_title}', '{post_author}', '{post_url}'],
|
||||
[$post_title, $post_author, $post_url],
|
||||
$footer_text
|
||||
) : '';
|
||||
|
||||
$message_template = get_option('wp_multi_discord_message_template', 'Beitrag "{post_title}" von {post_author} | Link: {post_url}');
|
||||
$message = str_replace(
|
||||
['{post_title}', '{post_author}', '{post_url}'],
|
||||
[$post_title, $post_author, $post_url],
|
||||
$message_template
|
||||
);
|
||||
$message .= "\n\n" . $excerpt . "\n\n" . $footer;
|
||||
|
||||
$data = json_encode([
|
||||
'username' => $bot_name,
|
||||
'avatar_url' => $avatar_url,
|
||||
'content' => $mention_role . "\n" . $message
|
||||
]);
|
||||
|
||||
$response = wp_remote_post($webhook_url, [
|
||||
'method' => 'POST',
|
||||
'body' => $data,
|
||||
'headers' => ['Content-Type' => 'application/json']
|
||||
]);
|
||||
|
||||
if (!is_wp_error($response)) {
|
||||
wp_multi_increment_discord_message_count();
|
||||
} else {
|
||||
error_log('Discord Webhook Fehler: ' . $response->get_error_message());
|
||||
}
|
||||
}
|
||||
add_action('publish_post', 'wp_multi_send_discord_notification', 10, 2);
|
||||
|
||||
// Funktion zum Erhöhen des Discord-Nachrichtenzählers
|
||||
function wp_multi_increment_discord_message_count() {
|
||||
$current_count = get_option('wp_multi_discord_message_count', 0);
|
||||
update_option('wp_multi_discord_message_count', $current_count + 1);
|
||||
}
|
||||
|
||||
// Funktion, um die Checkbox in der Sidebar des Beitrag Editors hinzuzufügen
|
||||
function wp_multi_add_checkbox_to_sidebar() {
|
||||
global $post;
|
||||
wp_nonce_field('wp_multi_checkbox_nonce', 'wp_multi_checkbox_nonce_field');
|
||||
$value = get_post_meta($post->ID, '_wp_multi_checkbox', true);
|
||||
?>
|
||||
<div class="misc-pub-section">
|
||||
<label for="wp_multi_checkbox">
|
||||
<input type="checkbox" name="wp_multi_checkbox" id="wp_multi_checkbox" value="1" <?php checked($value, '1'); ?>>
|
||||
Discord Benachrichtigung senden
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
add_action('post_submitbox_misc_actions', 'wp_multi_add_checkbox_to_sidebar');
|
||||
|
||||
// Funktion, um den Wert der Checkbox zu speichern
|
||||
function wp_multi_save_checkbox_value($post_id) {
|
||||
if (!isset($_POST['wp_multi_checkbox_nonce_field']) || !wp_verify_nonce($_POST['wp_multi_checkbox_nonce_field'], 'wp_multi_checkbox_nonce')) {
|
||||
return;
|
||||
}
|
||||
if (isset($_POST['wp_multi_checkbox']) && $_POST['wp_multi_checkbox'] === '1') {
|
||||
update_post_meta($post_id, '_wp_multi_checkbox', '1');
|
||||
} else {
|
||||
delete_post_meta($post_id, '_wp_multi_checkbox');
|
||||
}
|
||||
}
|
||||
add_action('save_post', 'wp_multi_save_checkbox_value');
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Telegram-Benachrichtigung
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Telegram Notify
|
||||
*/
|
||||
|
||||
|
||||
// Admin-Seiten Callback
|
||||
function tg_notify_page() {
|
||||
wpmt_admin_page_open(
|
||||
__('TG-Notify', 'wp-stat-notice'),
|
||||
__('Telegram-Benachrichtigungen bei neuen Beiträgen', 'wp-stat-notice')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('tg_notify_options_group');
|
||||
do_settings_sections('tg-notify');
|
||||
submit_button('Speichern', 'primary', 'submit', true);
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Einstellungen registrieren
|
||||
function tg_notify_register_settings() {
|
||||
register_setting('tg_notify_options_group', 'tg_notify_bot_name');
|
||||
register_setting('tg_notify_options_group', 'tg_notify_bot_token');
|
||||
register_setting('tg_notify_options_group', 'tg_notify_chat_ids');
|
||||
register_setting('tg_notify_options_group', 'tg_notify_custom_message');
|
||||
|
||||
add_settings_section('tg_notify_main_section', __('Telegram Einstellungen', 'wp-stat-notice'), null, 'tg-notify');
|
||||
|
||||
add_settings_field('tg_notify_bot_name', __('Bot Name', 'wp-stat-notice'), 'tg_notify_bot_name_callback', 'tg-notify', 'tg_notify_main_section');
|
||||
add_settings_field('tg_notify_bot_token', __('Bot Token', 'wp-stat-notice'), 'tg_notify_bot_token_callback', 'tg-notify', 'tg_notify_main_section');
|
||||
add_settings_field('tg_notify_chat_ids', __('Kanal IDs', 'wp-stat-notice'), 'tg_notify_chat_ids_callback', 'tg-notify', 'tg_notify_main_section');
|
||||
add_settings_field('tg_notify_custom_message', __('Custom Nachricht', 'wp-stat-notice'), 'tg_notify_custom_message_callback', 'tg-notify', 'tg_notify_main_section');
|
||||
}
|
||||
add_action('admin_init', 'tg_notify_register_settings');
|
||||
|
||||
// Callback-Funktionen
|
||||
function tg_notify_bot_name_callback() {
|
||||
$value = get_option('tg_notify_bot_name', '');
|
||||
echo '<input type="text" name="tg_notify_bot_name" value="' . esc_attr($value) . '" class="regular-text">';
|
||||
}
|
||||
function tg_notify_bot_token_callback() {
|
||||
$value = get_option('tg_notify_bot_token', '');
|
||||
echo '<input type="text" name="tg_notify_bot_token" value="' . esc_attr($value) . '" class="regular-text">';
|
||||
}
|
||||
function tg_notify_chat_ids_callback() {
|
||||
$value = get_option('tg_notify_chat_ids', '');
|
||||
echo '<textarea name="tg_notify_chat_ids" class="large-text code" rows="3">' . esc_textarea($value) . '</textarea>';
|
||||
echo '<p>Kanal ohne Thema: -1001234567890</p>';
|
||||
echo '<p>Kanal mit Thema: -1001234567890_123</p>';
|
||||
}
|
||||
function tg_notify_custom_message_callback() {
|
||||
$value = get_option('tg_notify_custom_message', '');
|
||||
echo '<textarea name="tg_notify_custom_message" class="large-text code" rows="5">' . esc_textarea($value) . '</textarea>';
|
||||
echo '<p>Verfügbare Variablen: {title}, {author}, {link}</p>';
|
||||
}
|
||||
|
||||
// Checkbox beim Beitrag hinzufügen
|
||||
function tg_notify_add_meta_box() {
|
||||
add_meta_box(
|
||||
'tg_notify_meta_box',
|
||||
__('Telegram Benachrichtigung', 'wp-stat-notice'),
|
||||
'tg_notify_meta_box_callback',
|
||||
'post',
|
||||
'side',
|
||||
'high'
|
||||
);
|
||||
}
|
||||
add_action('add_meta_boxes', 'tg_notify_add_meta_box');
|
||||
|
||||
function tg_notify_meta_box_callback($post) {
|
||||
$value = get_post_meta($post->ID, '_tg_notify_send', true);
|
||||
|
||||
// Standardmäßig auf 1 setzen, wenn der Beitrag neu ist
|
||||
if (empty($value) && get_post_status($post->ID) !== 'publish') {
|
||||
$value = 1;
|
||||
}
|
||||
|
||||
wp_nonce_field('tg_notify_meta_box', 'tg_notify_meta_box_nonce');
|
||||
echo '<label><input type="checkbox" name="tg_notify_send" value="1" ' . checked($value, 1, false) . '> ' . __('Benachrichtigung senden', 'wp-stat-notice') . '</label>';
|
||||
}
|
||||
|
||||
function tg_notify_save_post($post_id) {
|
||||
// Sicherheitsprüfungen
|
||||
if (!isset($_POST['tg_notify_meta_box_nonce']) || !wp_verify_nonce($_POST['tg_notify_meta_box_nonce'], 'tg_notify_meta_box')) return;
|
||||
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
||||
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) return;
|
||||
if (!current_user_can('edit_post', $post_id)) return;
|
||||
|
||||
// Prüfen, ob der Beitrag wirklich veröffentlicht wurde
|
||||
if (get_post_status($post_id) !== 'publish') return;
|
||||
|
||||
// Prüfen, ob die Nachricht bereits gesendet wurde
|
||||
$already_sent = get_post_meta($post_id, '_tg_notify_sent', true);
|
||||
if ($already_sent) return;
|
||||
|
||||
$send_notification = isset($_POST['tg_notify_send']) ? 1 : 0;
|
||||
update_post_meta($post_id, '_tg_notify_send', $send_notification);
|
||||
|
||||
if ($send_notification) {
|
||||
tg_notify_send_telegram_message($post_id);
|
||||
update_post_meta($post_id, '_tg_notify_sent', 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_action('save_post', 'tg_notify_save_post');
|
||||
|
||||
function tg_notify_send_telegram_message($post_id) {
|
||||
$bot_token = get_option('tg_notify_bot_token');
|
||||
$chat_ids = explode("\n", get_option('tg_notify_chat_ids'));
|
||||
$message_template = get_option('tg_notify_custom_message');
|
||||
|
||||
$post = get_post($post_id);
|
||||
// Überprüfen, ob der Beitrag von einem Gast-Author stammt
|
||||
$author_name = get_the_author_meta('display_name', $post->post_author);
|
||||
if (empty($author_name)) {
|
||||
// Falls kein Name vorhanden ist (Gast-Author), den Gast-Namen verwenden oder einen Platzhalter setzen
|
||||
$author_name = 'Gast-Author';
|
||||
}
|
||||
|
||||
// Nachricht formatieren
|
||||
$message = str_replace(
|
||||
['{title}', '{author}', '{link}'],
|
||||
[$post->post_title, $author_name, get_permalink($post_id)],
|
||||
$message_template
|
||||
);
|
||||
|
||||
foreach ($chat_ids as $chat_id) {
|
||||
$chat_id = trim($chat_id);
|
||||
if (!empty($chat_id)) {
|
||||
// Überprüfen, ob die ID das Thema enthält (Format: -1001234567890_123)
|
||||
if (strpos($chat_id, '_') !== false) {
|
||||
// Kanal-ID und Themen-ID trennen
|
||||
list($channel_id, $topic_id) = explode('_', $chat_id);
|
||||
$chat_id = $channel_id;
|
||||
|
||||
// Telegram API-Anfrage senden
|
||||
$url = "https://api.telegram.org/bot$bot_token/sendMessage";
|
||||
$args = [
|
||||
'body' => json_encode([
|
||||
'chat_id' => $chat_id,
|
||||
'text' => $message,
|
||||
'parse_mode' => 'HTML',
|
||||
'reply_to_message_id' => $topic_id
|
||||
]),
|
||||
'headers' => ['Content-Type' => 'application/json'],
|
||||
'method' => 'POST',
|
||||
];
|
||||
|
||||
// API-Request senden und Fehlerprotokollierung
|
||||
$response = wp_remote_post($url, $args);
|
||||
if (is_wp_error($response)) {
|
||||
$error_message = $response->get_error_message();
|
||||
error_log("Telegram Fehler: $error_message");
|
||||
} else {
|
||||
// Erhöhe den Telegram-Nachrichtenzähler
|
||||
tg_notify_increment_telegram_message_count();
|
||||
}
|
||||
} else {
|
||||
// Normaler Kanal ohne Thema
|
||||
$url = "https://api.telegram.org/bot$bot_token/sendMessage";
|
||||
$args = [
|
||||
'body' => json_encode([
|
||||
'chat_id' => $chat_id,
|
||||
'text' => $message,
|
||||
'parse_mode' => 'HTML'
|
||||
]),
|
||||
'headers' => ['Content-Type' => 'application/json'],
|
||||
'method' => 'POST',
|
||||
];
|
||||
|
||||
// API-Request senden und Fehlerprotokollierung
|
||||
$response = wp_remote_post($url, $args);
|
||||
if (is_wp_error($response)) {
|
||||
$error_message = $response->get_error_message();
|
||||
error_log("Telegram Fehler: $error_message");
|
||||
} else {
|
||||
// Erhöhe den Telegram-Nachrichtenzähler
|
||||
tg_notify_increment_telegram_message_count();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tg_notify_increment_telegram_message_count() {
|
||||
$current_count = get_option('wp_multi_telegram_message_count', 0);
|
||||
update_option('wp_multi_telegram_message_count', $current_count + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Notify-Übersichtsseite
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Notify Seite Discord & Telegram
|
||||
*/
|
||||
|
||||
|
||||
// Die Notify-Menüpunkte werden zentral in wp_multi_register_admin_menus() registriert
|
||||
// (DC-Notify-Slug wurde von 'wp-multi' zu 'wp-multi-dc-notify' umbenannt, da 'wp-multi'
|
||||
// jetzt das gemeinsame Top-Level-Menü ist).
|
||||
|
||||
// Callback-Funktion für die Hauptseite Notify
|
||||
function wp_multi_notify_page() {
|
||||
wpmt_admin_page_open(
|
||||
__('Notify', 'wp-multi'),
|
||||
__('Discord- und Telegram-Benachrichtigungen für neue Beiträge', 'wp-multi')
|
||||
);
|
||||
|
||||
wpmt_admin_notice('info', __('Um Benachrichtigungen zu senden, müssen zuerst die entsprechenden Webhooks und Bots eingerichtet werden. Diese Seite erklärt die Einrichtung - die eigentlichen Einstellungen findest du unter DC-Notify bzw. TG-Notify.', 'wp-multi'));
|
||||
|
||||
echo '<div class="wpm-grid wpm-grid--2">';
|
||||
|
||||
wpmt_admin_card_open(__('Discord', 'wp-multi'));
|
||||
?>
|
||||
<p><?php _e('Erstellen Sie einen Webhook in einem Discord-Kanal und fügen Sie die Webhook-URL in die entsprechenden Felder ein.', 'wp-multi'); ?></p>
|
||||
<ol>
|
||||
<li><?php _e('Gehen Sie zu Ihrem Discord-Server und öffnen Sie die Server-Einstellungen.', 'wp-multi'); ?></li>
|
||||
<li><?php _e('Wählen Sie "Integrationen" und dann "Webhook erstellen".', 'wp-multi'); ?></li>
|
||||
<li><?php _e('Kopieren Sie die Webhook-URL und fügen Sie diese in das entsprechende Feld ein.', 'wp-multi'); ?></li>
|
||||
</ol>
|
||||
<p><a href="<?php echo esc_url(admin_url('admin.php?page=wp-multi-dc-notify')); ?>" class="wpm-btn wpm-btn--primary"><?php _e('DC-Notify einrichten', 'wp-multi'); ?></a></p>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Telegram', 'wp-multi'));
|
||||
?>
|
||||
<p><?php _e('Erstellen Sie einen Bot über BotFather und fügen Sie den Token und die Kanal-ID in die entsprechenden Felder ein.', 'wp-multi'); ?></p>
|
||||
<ol>
|
||||
<li><?php _e('Öffnen Sie Telegram und suchen Sie nach "BotFather".', 'wp-multi'); ?></li>
|
||||
<li><?php _e('Geben Sie /newbot ein, um einen neuen Bot zu erstellen.', 'wp-multi'); ?></li>
|
||||
<li><?php _e('Speichern Sie den Bot-Token und die Kanal-ID und tragen Sie diese in die Felder ein.', 'wp-multi'); ?></li>
|
||||
</ol>
|
||||
<p><a href="<?php echo esc_url(admin_url('admin.php?page=tg-notify')); ?>" class="wpm-btn wpm-btn--primary"><?php _e('TG-Notify einrichten', 'wp-multi'); ?></a></p>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
echo '</div>';
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Beitrags-Report
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Beitrags Report
|
||||
*/
|
||||
|
||||
|
||||
// Funktion zum Erstellen und Aktualisieren der Datenbanktabelle für gemeldete Beiträge
|
||||
function wp_stat_notice_create_reported_posts_table() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'reported_posts';
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
// SQL für die Tabelle
|
||||
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
post_id BIGINT(20) NOT NULL,
|
||||
report_date DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
reason TEXT NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(20) DEFAULT 'reported',
|
||||
user_id BIGINT(20) UNSIGNED DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY post_id (post_id),
|
||||
KEY user_id (user_id)
|
||||
) $charset_collate;";
|
||||
|
||||
// Tabelle zuerst erstellen bzw. aktualisieren - erst danach kann die
|
||||
// Spaltenprüfung laufen (vorher schlug SHOW COLUMNS bei der Erstaktivierung fehl).
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
|
||||
// Migration für Alt-Installationen: Spalte `name` ergänzen, falls sie fehlt
|
||||
$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name");
|
||||
|
||||
$column_names = array_map(function($column) {
|
||||
return $column->Field;
|
||||
}, $columns);
|
||||
|
||||
if (!in_array('name', $column_names, true)) {
|
||||
$wpdb->query("ALTER TABLE $table_name ADD COLUMN `name` VARCHAR(255) NOT NULL");
|
||||
}
|
||||
}
|
||||
|
||||
register_activation_hook(WP_MULTI_FILE, 'wp_stat_notice_create_reported_posts_table');
|
||||
|
||||
|
||||
// Shortcode für den "Beitrag melden"-Button
|
||||
function wp_stat_notice_report_button($atts) {
|
||||
global $post;
|
||||
if (!is_user_logged_in()) return '';
|
||||
|
||||
$atts = shortcode_atts(array('post_id' => $post->ID), $atts, 'report_button');
|
||||
$nonce = wp_create_nonce('report_post_nonce');
|
||||
|
||||
// Report-Button & Eingabefelder für Name und Grund
|
||||
ob_start();
|
||||
?>
|
||||
<button class="report-post" data-post-id="<?php echo esc_attr($atts['post_id']); ?>" data-nonce="<?php echo esc_attr($nonce); ?>">
|
||||
Beitrag melden
|
||||
</button>
|
||||
<div class="report-reason" style="display:none;">
|
||||
<input type="text" class="report-name" placeholder="Geben Sie Ihren Namen an" required />
|
||||
<textarea class="report-reason-text" placeholder="Geben Sie den Grund an" required></textarea>
|
||||
<button class="submit-report">Bericht absenden</button>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
add_shortcode('report_button', 'wp_stat_notice_report_button');
|
||||
|
||||
// Stil für das Meldeformular
|
||||
function wp_stat_notice_report_button_styles() {
|
||||
?>
|
||||
<style>
|
||||
.report-reason {
|
||||
display: none;
|
||||
margin-top: 10px;
|
||||
background-color: #f9f9f9;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
width: 300px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.report-reason input, .report-reason textarea {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin: 5px 0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.report-reason button {
|
||||
background-color: #0073aa;
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.report-reason button:hover {
|
||||
background-color: #005177;
|
||||
}
|
||||
.report-post {
|
||||
background-color: #ff7f00;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.report-post:hover {
|
||||
background-color: #e07b00;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
add_action('wp_head', 'wp_stat_notice_report_button_styles');
|
||||
|
||||
// Dashboard-Widget hinzufügen
|
||||
function wp_stat_notice_add_dashboard_widget() {
|
||||
wp_add_dashboard_widget(
|
||||
'wp_stat_notice_dashboard_widget',
|
||||
'Letzte 10 gemeldete Beiträge',
|
||||
'wp_stat_notice_dashboard_widget_display'
|
||||
);
|
||||
}
|
||||
add_action('wp_dashboard_setup', 'wp_stat_notice_add_dashboard_widget');
|
||||
|
||||
// Funktion, die das Dashboard-Widget anzeigt
|
||||
function wp_stat_notice_dashboard_widget_display() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'reported_posts';
|
||||
|
||||
// Abfrage, um die letzten 10 gemeldeten Beiträge zu holen
|
||||
$reports = $wpdb->get_results(
|
||||
"SELECT * FROM $table_name ORDER BY report_date DESC LIMIT 10"
|
||||
);
|
||||
|
||||
if (empty($reports)) {
|
||||
echo '<p>Es gibt keine gemeldeten Beiträge.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Tabelle mit den letzten 10 gemeldeten Beiträgen anzeigen
|
||||
echo '<table class="wp-list-table widefat fixed striped">';
|
||||
echo '<thead><tr><th>Beitrag</th><th>Datum</th><th>Grund</th></tr></thead><tbody>';
|
||||
|
||||
foreach ($reports as $report) {
|
||||
$post = get_post($report->post_id);
|
||||
echo '<tr>';
|
||||
echo '<td>' . esc_html($post->post_title) . '</td>';
|
||||
echo '<td>' . esc_html($report->report_date) . '</td>';
|
||||
echo '<td>' . esc_html($report->reason) . '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
|
||||
// AJAX-Handler zum Senden eines Reports
|
||||
function wp_stat_notice_handle_report() {
|
||||
check_ajax_referer('report_post_nonce', 'nonce');
|
||||
|
||||
if (!isset($_POST['post_id'], $_POST['reason'], $_POST['name']) || !is_user_logged_in()) {
|
||||
wp_send_json_error(array('message' => 'Ungültige Anfrage.'));
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'reported_posts';
|
||||
|
||||
$post_id = intval($_POST['post_id']);
|
||||
$reason = sanitize_textarea_field($_POST['reason']);
|
||||
$name = sanitize_text_field($_POST['name']);
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
// Versuche den Eintrag in die Datenbank zu schreiben
|
||||
$result = $wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'post_id' => $post_id,
|
||||
'reason' => $reason,
|
||||
'name' => $name,
|
||||
'status' => 'reported',
|
||||
'user_id' => $user_id
|
||||
),
|
||||
array('%d', '%s', '%s', '%s', '%d')
|
||||
);
|
||||
|
||||
if ($result === false) {
|
||||
error_log("Datenbankfehler: " . $wpdb->last_error); // WP Debug Log
|
||||
wp_send_json_error(array('message' => 'Datenbankfehler: ' . $wpdb->last_error));
|
||||
} else {
|
||||
wp_send_json_success(array('message' => 'Bericht erfolgreich gesendet.'));
|
||||
}
|
||||
}
|
||||
add_action('wp_ajax_report_post', 'wp_stat_notice_handle_report');
|
||||
|
||||
|
||||
// JavaScript in den Footer einfügen
|
||||
function wp_stat_notice_inline_js() {
|
||||
?>
|
||||
<script>
|
||||
jQuery(document).ready(function ($) {
|
||||
$(document).on("click", ".report-post", function () {
|
||||
let reasonBox = $(this).next(".report-reason");
|
||||
reasonBox.toggle();
|
||||
});
|
||||
|
||||
$(document).on("click", ".submit-report", function () {
|
||||
let button = $(this);
|
||||
let container = button.closest(".report-reason");
|
||||
let reason = container.find(".report-reason-text").val();
|
||||
let name = container.find(".report-name").val();
|
||||
let postId = button.closest(".report-reason").prev(".report-post").data("post-id");
|
||||
let nonce = button.closest(".report-reason").prev(".report-post").data("nonce");
|
||||
|
||||
if (!reason || !name) {
|
||||
alert("Bitte geben Sie sowohl Ihren Namen als auch einen Grund an.");
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "<?php echo admin_url('admin-ajax.php'); ?>",
|
||||
type: "POST",
|
||||
data: {
|
||||
action: "report_post",
|
||||
post_id: postId,
|
||||
reason: reason,
|
||||
name: name,
|
||||
nonce: nonce
|
||||
},
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
alert("Der Bericht wurde erfolgreich gesendet.");
|
||||
container.hide();
|
||||
} else {
|
||||
alert("Fehler: " + response.data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
}
|
||||
add_action('wp_footer', 'wp_stat_notice_inline_js');
|
||||
|
||||
// Admin-Seite für gemeldete Beiträge
|
||||
function wp_stat_notice_reported_posts_page() {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'reported_posts';
|
||||
$reports = $wpdb->get_results("SELECT * FROM $table_name ORDER BY report_date DESC");
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Gemeldete Beiträge', 'wp-stat-notice'),
|
||||
__('Von Besuchern gemeldete Inhalte prüfen und bearbeiten', 'wp-stat-notice')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open();
|
||||
if (empty($reports)) {
|
||||
wpmt_admin_notice('info', __('Es liegen keine Meldungen vor.', 'wp-stat-notice'));
|
||||
} else {
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php _e('Beitrag', 'wp-stat-notice'); ?></th>
|
||||
<th><?php _e('Datum', 'wp-stat-notice'); ?></th>
|
||||
<th><?php _e('Name', 'wp-stat-notice'); ?></th>
|
||||
<th><?php _e('Grund', 'wp-stat-notice'); ?></th>
|
||||
<th><?php _e('Status', 'wp-stat-notice'); ?></th>
|
||||
<th><?php _e('Aktionen', 'wp-stat-notice'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($reports as $report):
|
||||
$post = get_post($report->post_id); ?>
|
||||
<tr>
|
||||
<td><?php echo $post ? esc_html($post->post_title) : '—'; ?></td>
|
||||
<td><?php echo esc_html($report->report_date); ?></td>
|
||||
<td><?php echo esc_html($report->name); ?></td>
|
||||
<td><?php echo esc_html($report->reason); ?></td>
|
||||
<td><span class="wpm-badge <?php echo $report->status === 'reported' ? 'wpm-badge--warning' : ''; ?>"><?php echo esc_html($report->status); ?></span></td>
|
||||
<td>
|
||||
<a href="<?php echo esc_url(wp_nonce_url('?page=reported-posts&delete_report=' . $report->id, 'wp_stat_notice_delete_report_' . $report->id)); ?>" class="wpm-btn" onclick="return confirm('<?php esc_attr_e('Report wirklich löschen?', 'wp-stat-notice'); ?>');"><?php _e('Report löschen', 'wp-stat-notice'); ?></a>
|
||||
<a href="<?php echo esc_url(wp_nonce_url('?page=reported-posts&unpublish_report=' . $report->id, 'wp_stat_notice_unpublish_report_' . $report->id)); ?>" class="wpm-btn"><?php _e('Unpublish', 'wp-stat-notice'); ?></a>
|
||||
<a href="<?php echo esc_url(wp_nonce_url('?page=reported-posts&delete_post=' . $report->post_id, 'wp_stat_notice_delete_post_' . $report->post_id)); ?>" class="wpm-btn wpm-btn--danger" onclick="return confirm('<?php esc_attr_e('Beitrag wirklich unwiderruflich löschen?', 'wp-stat-notice'); ?>');"><?php _e('Beitrag löschen', 'wp-stat-notice'); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Aktionen für Report-Handling
|
||||
function wp_stat_notice_handle_report_actions() {
|
||||
if (!isset($_GET['page']) || $_GET['page'] !== 'reported-posts') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
if (isset($_GET['delete_report'])) {
|
||||
check_admin_referer('wp_stat_notice_delete_report_' . intval($_GET['delete_report']));
|
||||
$wpdb->delete($wpdb->prefix . 'reported_posts', array('id' => intval($_GET['delete_report'])), array('%d'));
|
||||
} elseif (isset($_GET['unpublish_report'])) {
|
||||
check_admin_referer('wp_stat_notice_unpublish_report_' . intval($_GET['unpublish_report']));
|
||||
$wpdb->update($wpdb->prefix . 'reported_posts', array('status' => 'unpublished'), array('id' => intval($_GET['unpublish_report'])), array('%s'), array('%d'));
|
||||
} elseif (isset($_GET['delete_post'])) {
|
||||
check_admin_referer('wp_stat_notice_delete_post_' . intval($_GET['delete_post']));
|
||||
wp_delete_post(intval($_GET['delete_post']), true);
|
||||
}
|
||||
}
|
||||
add_action('admin_init', 'wp_stat_notice_handle_report_actions');
|
||||
|
||||
// Der Menüpunkt "Gemeldete Beiträge" wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Custom Shortcodes
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* custom shortcodes
|
||||
*/
|
||||
|
||||
|
||||
// Funktion, um die Datenbanktabelle für Shortcodes zu erstellen
|
||||
function wp_multi_create_shortcodes_table() {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'wp_multi_shortcodes'; // Name der Tabelle mit Präfix
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
// SQL-Abfrage zum Erstellen der Tabelle
|
||||
$sql = "CREATE TABLE $table_name (
|
||||
id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
shortcode_name varchar(255) NOT NULL,
|
||||
shortcode_content text NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY shortcode_name (shortcode_name)
|
||||
) $charset_collate;";
|
||||
|
||||
// Datenbank abfragen und ausführen
|
||||
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
||||
dbDelta( $sql );
|
||||
}
|
||||
register_activation_hook( WP_MULTI_FILE, 'wp_multi_create_shortcodes_table' );
|
||||
|
||||
// Der Shortcodes-Menüpunkt wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Callback-Funktion für das Shortcode-Verwaltungs-Interface
|
||||
function wp_multi_shortcode_page() {
|
||||
global $wpdb;
|
||||
|
||||
$message = ''; // Variable für benutzerdefinierte Nachrichten
|
||||
|
||||
// Verarbeite das Speichern von Shortcodes
|
||||
if (isset($_POST['wp_multi_shortcode_name']) && isset($_POST['wp_multi_shortcode_content'])) {
|
||||
check_admin_referer('wp_multi_save_shortcode', 'wp_multi_shortcode_nonce');
|
||||
|
||||
// Hole die übermittelten Shortcodes
|
||||
$name = sanitize_key($_POST['wp_multi_shortcode_name']);
|
||||
$content = wp_kses_post(wp_unslash($_POST['wp_multi_shortcode_content']));
|
||||
|
||||
// Prüfen, ob der Shortcode bereits existiert
|
||||
$existing_shortcode = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}wp_multi_shortcodes WHERE shortcode_name = %s", $name));
|
||||
|
||||
if ($existing_shortcode) {
|
||||
// Aktualisiere den Shortcode, falls er bereits existiert
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wp_multi_shortcodes',
|
||||
['shortcode_content' => $content],
|
||||
['shortcode_name' => $name]
|
||||
);
|
||||
$message = 'Shortcode wurde aktualisiert!';
|
||||
} else {
|
||||
// Andernfalls einen neuen Shortcode einfügen
|
||||
$wpdb->insert(
|
||||
$wpdb->prefix . 'wp_multi_shortcodes',
|
||||
[
|
||||
'shortcode_name' => $name,
|
||||
'shortcode_content' => $content
|
||||
]
|
||||
);
|
||||
$message = 'Shortcode wurde hinzugefügt!';
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcode löschen
|
||||
if (isset($_GET['delete_shortcode']) && !empty($_GET['delete_shortcode'])) {
|
||||
check_admin_referer('wp_multi_delete_shortcode_' . intval($_GET['delete_shortcode']));
|
||||
$delete_id = intval($_GET['delete_shortcode']);
|
||||
$wpdb->delete(
|
||||
$wpdb->prefix . 'wp_multi_shortcodes',
|
||||
['id' => $delete_id]
|
||||
);
|
||||
$message = 'Shortcode wurde gelöscht!';
|
||||
}
|
||||
|
||||
// Holen der gespeicherten Shortcodes aus der Datenbank
|
||||
$custom_shortcodes = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wp_multi_shortcodes");
|
||||
|
||||
wpmt_admin_page_open(
|
||||
__('Shortcodes', 'wp-multi'),
|
||||
__('Eigene Shortcodes erstellen, die im Editor eingefügt werden können', 'wp-multi')
|
||||
);
|
||||
|
||||
if (!empty($message)) {
|
||||
wpmt_admin_notice('success', $message);
|
||||
}
|
||||
|
||||
wpmt_admin_card_open(__('Shortcode anlegen / aktualisieren', 'wp-multi'));
|
||||
?>
|
||||
<form method="post">
|
||||
<?php wp_nonce_field('wp_multi_save_shortcode', 'wp_multi_shortcode_nonce'); ?>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label" for="wp_multi_shortcode_name"><?php _e('Name des Shortcodes', 'wp-multi'); ?>
|
||||
<small class="wpm-field__hint"><?php _e('Nur Kleinbuchstaben, Zahlen und Unterstriche.', 'wp-multi'); ?></small>
|
||||
</label>
|
||||
<input type="text" name="wp_multi_shortcode_name" id="wp_multi_shortcode_name" required />
|
||||
</div>
|
||||
<div class="wpm-field">
|
||||
<label class="wpm-field__label" for="wp_multi_shortcode_content"><?php _e('Inhalt des Shortcodes', 'wp-multi'); ?></label>
|
||||
<textarea name="wp_multi_shortcode_content" id="wp_multi_shortcode_content" rows="5" required></textarea>
|
||||
</div>
|
||||
<?php submit_button(__('Shortcode speichern', 'wp-multi')); ?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Verfügbare Shortcodes', 'wp-multi'));
|
||||
if (!empty($custom_shortcodes)) {
|
||||
?>
|
||||
<div class="wpm-table-wrap">
|
||||
<table class="wpm-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php _e('Shortcode', 'wp-multi'); ?></th>
|
||||
<th><?php _e('Inhalt', 'wp-multi'); ?></th>
|
||||
<th><?php _e('Aktionen', 'wp-multi'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($custom_shortcodes as $shortcode) :
|
||||
$delete_url = wp_nonce_url(
|
||||
admin_url('admin.php?page=wp_multi_shortcodes&delete_shortcode=' . $shortcode->id),
|
||||
'wp_multi_delete_shortcode_' . $shortcode->id
|
||||
);
|
||||
?>
|
||||
<tr>
|
||||
<td><code>[<?php echo esc_html($shortcode->shortcode_name); ?>]</code></td>
|
||||
<td><?php echo esc_html(wp_trim_words($shortcode->shortcode_content, 15)); ?></td>
|
||||
<td><a href="<?php echo esc_url($delete_url); ?>" class="wpm-btn wpm-btn--danger" onclick="return confirm('<?php esc_attr_e('Möchten Sie diesen Shortcode wirklich löschen?', 'wp-multi'); ?>');"><?php _e('Löschen', 'wp-multi'); ?></a></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
wpmt_admin_notice('info', __('Keine benutzerdefinierten Shortcodes gefunden.', 'wp-multi'));
|
||||
}
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Shortcode-Verwaltung: Ermöglicht Benutzern das Erstellen eigener Shortcodes
|
||||
function wp_multi_register_custom_shortcodes() {
|
||||
global $wpdb;
|
||||
|
||||
// Holen der gespeicherten Shortcodes aus der Datenbank
|
||||
$custom_shortcodes = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wp_multi_shortcodes");
|
||||
|
||||
// Wenn keine benutzerdefinierten Shortcodes vorhanden sind, abbrechen
|
||||
if (empty($custom_shortcodes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Definiere die Shortcodes in WordPress
|
||||
foreach ($custom_shortcodes as $shortcode) {
|
||||
add_shortcode($shortcode->shortcode_name, function() use ($shortcode) {
|
||||
return wp_kses_post($shortcode->shortcode_content);
|
||||
});
|
||||
}
|
||||
}
|
||||
add_action('init', 'wp_multi_register_custom_shortcodes');
|
||||
|
||||
// Inhalt der Meta-Box anzeigen
|
||||
function wp_multi_render_shortcode_meta_box($post) {
|
||||
global $wpdb;
|
||||
|
||||
// Alle gespeicherten Shortcodes aus der Datenbank holen
|
||||
$shortcodes = $wpdb->get_results("SELECT shortcode_name FROM {$wpdb->prefix}wp_multi_shortcodes");
|
||||
|
||||
if (!empty($shortcodes)) {
|
||||
echo '<select id="wp_multi_shortcode_dropdown">';
|
||||
echo '<option value="">-- Shortcode auswählen --</option>';
|
||||
|
||||
foreach ($shortcodes as $shortcode) {
|
||||
echo '<option value="' . esc_attr($shortcode->shortcode_name) . '">' . esc_html($shortcode->shortcode_name) . '</option>';
|
||||
}
|
||||
|
||||
echo '</select>';
|
||||
echo '<button type="button" class="button button-primary" id="wp_multi_insert_shortcode">Einfügen</button>';
|
||||
} else {
|
||||
echo '<p>Keine Shortcodes vorhanden.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
// JavaScript für Meta-Box einbinden (Classic Editor: fügt den gewählten Shortcode ein)
|
||||
function wp_multi_enqueue_admin_scripts($hook) {
|
||||
if ('post.php' === $hook || 'post-new.php' === $hook) {
|
||||
wp_enqueue_script('wp-multi-shortcode', plugin_dir_url(WP_MULTI_FILE) . 'js/classic-editor-shortcodes.js', array('jquery'), '1.0', true);
|
||||
}
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'wp_multi_enqueue_admin_scripts');
|
||||
|
||||
// Funktion zum Registrieren des TinyMCE Plugins
|
||||
function wp_multi_add_shortcode_button() {
|
||||
add_filter('mce_external_plugins', 'wp_multi_register_tinymce_plugin');
|
||||
add_filter('mce_buttons', 'wp_multi_add_tinymce_button');
|
||||
}
|
||||
add_action('admin_head', 'wp_multi_add_shortcode_button');
|
||||
|
||||
// Plugin für TinyMCE registrieren (angepasster Pfad zum JS-File)
|
||||
function wp_multi_register_tinymce_plugin($plugins) {
|
||||
$plugins['wp_multi_shortcodes'] = plugin_dir_url(WP_MULTI_FILE) . 'js/tinymce-shortcodes.js';
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
// Button zur TinyMCE Toolbar hinzufügen
|
||||
function wp_multi_add_tinymce_button($buttons) {
|
||||
array_push($buttons, 'wp_multi_shortcodes');
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
// Shortcodes aus der Datenbank für das JavaScript bereitstellen
|
||||
function wp_multi_localize_shortcodes() {
|
||||
global $wpdb;
|
||||
$shortcodes = $wpdb->get_results("SELECT shortcode_name FROM {$wpdb->prefix}wp_multi_shortcodes", ARRAY_A);
|
||||
|
||||
// Shortcodes als JSON an das JS-File übergeben
|
||||
wp_enqueue_script('wp-multi-tinymce', plugin_dir_url(WP_MULTI_FILE) . 'js/tinymce-shortcodes.js', array('jquery'), null, true);
|
||||
wp_localize_script('wp-multi-tinymce', 'wpMultiShortcodes', $shortcodes);
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'wp_multi_localize_shortcodes');
|
||||
|
||||
|
||||
@@ -0,0 +1,510 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Statistik & Banner
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Statistik & Banner
|
||||
*/
|
||||
|
||||
|
||||
// Funktion zum Einbinden von CSS direkt im Plugin-Code
|
||||
function statistik_manager_inline_styles() {
|
||||
?>
|
||||
<style>
|
||||
/* CSS für das Statistik Manager Plugin */
|
||||
.statistik-manager-bookmarks {
|
||||
font-family: Arial, sans-serif;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.statistik-manager-bookmarks ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
.statistik-manager-bookmarks li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.statistik-manager-bookmarks a {
|
||||
text-decoration: none;
|
||||
color: #0073aa;
|
||||
font-size: 1.6em; /* Größerer Text für den Titel */
|
||||
}
|
||||
.statistik-manager-bookmarks a:hover {
|
||||
color: #005177;
|
||||
}
|
||||
.delete-bookmark-btn {
|
||||
background-color: #f44336;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
margin-right: 10px; /* Abstand zwischen Button und Titel */
|
||||
margin-bottom: 10px; /* Mehr Abstand nach unten */
|
||||
}
|
||||
.delete-bookmark-btn:hover {
|
||||
background-color: #d32f2f;
|
||||
}
|
||||
.form-field {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.form-field label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.form-field input {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.form-field button {
|
||||
background-color: #0073aa;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.form-field button:hover {
|
||||
background-color: #005177;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
add_action('wp_head', 'statistik_manager_inline_styles');
|
||||
|
||||
// Font Awesome einbinden
|
||||
function statistik_manager_enqueue_fontawesome() {
|
||||
wp_enqueue_style('fontawesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css', [], null);
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'statistik_manager_enqueue_fontawesome');
|
||||
|
||||
// Sprachdateien laden
|
||||
function statistik_manager_load_textdomain() {
|
||||
load_plugin_textdomain('statistik-manager', false, dirname(plugin_basename(WP_MULTI_FILE)) . '/languages');
|
||||
}
|
||||
add_action('plugins_loaded', 'statistik_manager_load_textdomain');
|
||||
|
||||
// Funktion zum Abrufen der Statistiken
|
||||
function statistik_manager_get_statistics() {
|
||||
global $wpdb;
|
||||
|
||||
// Beiträge
|
||||
$posts_count = wp_count_posts()->publish;
|
||||
|
||||
// Kommentare
|
||||
$comments_count = wp_count_comments()->total_comments;
|
||||
|
||||
// Kategorien
|
||||
$selected_categories = get_option('statistik_manager_selected_categories', []);
|
||||
$categories_count = 0;
|
||||
|
||||
if (!empty($selected_categories)) {
|
||||
$categories_count = count($selected_categories);
|
||||
} else {
|
||||
// Alle Kategorien zählen, wenn keine ausgewählt wurden
|
||||
$categories_count = wp_count_terms('category');
|
||||
}
|
||||
|
||||
// Serien (angenommen, Serien sind benutzerdefinierte Taxonomie)
|
||||
$series_count = 0;
|
||||
if (taxonomy_exists('series')) {
|
||||
$count = wp_count_terms('series');
|
||||
$series_count = is_wp_error($count) ? 0 : (int) $count;
|
||||
}
|
||||
|
||||
// Eröffnungsdatum
|
||||
$opening_date = get_option('statistik_manager_opening_date', '');
|
||||
|
||||
return [
|
||||
'posts_count' => $posts_count,
|
||||
'comments_count' => $comments_count,
|
||||
'categories_count' => $categories_count,
|
||||
'series_count' => $series_count,
|
||||
'opening_date' => $opening_date
|
||||
];
|
||||
}
|
||||
|
||||
// Banner-Funktion
|
||||
function statistik_manager_display_banner($position) {
|
||||
if (!get_option('statistik_manager_banner_enabled', 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$banner_text = get_option('statistik_manager_banner_text', 'Willkommen auf unserer Webseite!');
|
||||
$banner_color = get_option('statistik_manager_banner_color', '#0073aa');
|
||||
$banner_position = get_option('statistik_manager_banner_position', 'top');
|
||||
$font_size = get_option('statistik_manager_banner_font_size', 'medium');
|
||||
$banner_icon = get_option('statistik_manager_banner_icon', 'fas fa-info-circle'); // Standard-Icon
|
||||
$show_icon = get_option('statistik_manager_show_icon', 1); // Option zur Aktivierung des Icons
|
||||
|
||||
// Schriftgröße je nach Auswahl setzen
|
||||
switch ($font_size) {
|
||||
case 'small':
|
||||
$font_size_css = '14px';
|
||||
break;
|
||||
case 'medium':
|
||||
$font_size_css = '18px';
|
||||
break;
|
||||
case 'large':
|
||||
$font_size_css = '24px';
|
||||
break;
|
||||
default:
|
||||
$font_size_css = '18px';
|
||||
}
|
||||
|
||||
if ($banner_position !== $position) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Standard-Styles für das Banner
|
||||
$style = "background-color: " . esc_attr($banner_color) . ";
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
height: 50px; /* Feste Höhe */
|
||||
line-height: 30px; /* Zentrierte Schrift */
|
||||
z-index: 9999;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;";
|
||||
|
||||
$text_style = "font-size: " . esc_attr($font_size_css) . ";";
|
||||
$icon_style = "font-size: 24px; margin-right: 8px;"; // Feste Größe für Icon
|
||||
|
||||
echo '<div class="statistik-manager-banner" id="statistik-manager-banner" style="' . esc_attr($style) . '">';
|
||||
|
||||
// Icon nur anzeigen, wenn gewünscht
|
||||
if ($show_icon && !empty($banner_icon)) {
|
||||
echo '<i class="' . esc_attr($banner_icon) . '" style="' . esc_attr($icon_style) . '"></i>';
|
||||
}
|
||||
|
||||
echo '<span style="' . esc_attr($text_style) . '">' . esc_html($banner_text) . '</span>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
// Funktion für das Banner im Header (nach <body>)
|
||||
function statistik_manager_display_banner_header() {
|
||||
add_action('wp_body_open', function() {
|
||||
statistik_manager_display_banner('top');
|
||||
});
|
||||
}
|
||||
|
||||
// Falls `wp_body_open` nicht unterstützt wird, als Fallback `wp_footer` nutzen
|
||||
function statistik_manager_display_banner_header_fallback() {
|
||||
add_action('wp_footer', function() {
|
||||
statistik_manager_display_banner('top');
|
||||
}, 5);
|
||||
}
|
||||
|
||||
// Funktion für das Banner im Footer
|
||||
function statistik_manager_display_banner_footer() {
|
||||
add_action('wp_footer', function() {
|
||||
statistik_manager_display_banner('bottom');
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// Banner laden (Header mit Fallback)
|
||||
if (function_exists('wp_body_open')) {
|
||||
statistik_manager_display_banner_header();
|
||||
} else {
|
||||
statistik_manager_display_banner_header_fallback();
|
||||
}
|
||||
|
||||
// Fix: Admin-Leiste (Wenn Admin angemeldet ist, Banner nach unten verschieben)
|
||||
function statistik_manager_admin_bar_fix() {
|
||||
if (is_admin_bar_showing()) {
|
||||
echo '<style>
|
||||
#statistik-manager-banner {
|
||||
top: 32px !important; /* Admin-Leiste ausgleichen */
|
||||
}
|
||||
body {
|
||||
padding-top: 82px !important; /* Extra Platz für Admin-Leiste */
|
||||
}
|
||||
</style>';
|
||||
} else {
|
||||
echo '<style>
|
||||
body {
|
||||
padding-top: 70px !important; /* Standard Abstand */
|
||||
}
|
||||
</style>';
|
||||
}
|
||||
}
|
||||
add_action('wp_head', 'statistik_manager_admin_bar_fix');
|
||||
|
||||
// Shortcode für die Anzeige der Statistiken
|
||||
function statistik_manager_shortcode() {
|
||||
$statistics = statistik_manager_get_statistics();
|
||||
$webseitenname = get_bloginfo('name');
|
||||
|
||||
$output = '<div class="statistik-manager">';
|
||||
$output .= '<h3>Statistikübersicht</h3>';
|
||||
$output .= '<div class="statistik-items">';
|
||||
|
||||
if (get_option('statistik_manager_show_posts')) {
|
||||
$output .= '<div class="stat-item"><i class="fas fa-file-alt"></i>';
|
||||
$output .= '<p><strong>Beiträge:</strong></br> ' . esc_html($statistics['posts_count']) . '</p></div>';
|
||||
}
|
||||
if (get_option('statistik_manager_show_comments')) {
|
||||
$output .= '<div class="stat-item"><i class="fas fa-comments"></i>';
|
||||
$output .= '<p><strong>Kommentare:</strong></br> ' . esc_html($statistics['comments_count']) . '</p></div>';
|
||||
}
|
||||
if (get_option('statistik_manager_show_categories')) {
|
||||
$output .= '<div class="stat-item"><i class="fas fa-th-list"></i>';
|
||||
$output .= '<p><strong>Kategorien:</strong></br> ' . esc_html($statistics['categories_count']) . '</p></div>';
|
||||
}
|
||||
if (get_option('statistik_manager_show_series')) {
|
||||
$output .= '<div class="stat-item"><i class="fas fa-tv"></i>';
|
||||
$output .= '<p><strong>Serien:</strong></br> ' . esc_html($statistics['series_count']) . '</p></div>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
|
||||
// Eröffnungsdatum anzeigen, wenn gesetzt
|
||||
if (!empty($statistics['opening_date'])) {
|
||||
$formatted_date = date('d.m.Y', strtotime($statistics['opening_date']));
|
||||
$output .= '<div class="stat-opening-date">';
|
||||
$output .= '<i class="fas fa-calendar-alt"></i>';
|
||||
$output .= '<p><strong>' . sprintf(__('%s wurde am %s eröffnet.', 'statistik-manager'), esc_html($webseitenname), esc_html($formatted_date)) . '</strong></p>';
|
||||
$output .= '</div>';
|
||||
}
|
||||
|
||||
$output .= '</div>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
add_shortcode('statistik_manager', 'statistik_manager_shortcode');
|
||||
|
||||
// Admin-Panel CSS einbinden, nur auf der Plugin-Seite
|
||||
// Das frühere seitenspezifische admin-style.css wurde durch das gemeinsame
|
||||
// Design-System (wp-multi-toolkit/assets/admin.css) ersetzt.
|
||||
|
||||
// Frontend CSS nur einbinden, wenn der Shortcode verwendet wird
|
||||
function statistik_manager_enqueue_frontend_styles() {
|
||||
if (has_shortcode(get_post()->post_content, 'statistik_manager')) {
|
||||
wp_enqueue_style('statistik-manager-frontend-style', plugins_url('css/style.css', WP_MULTI_FILE));
|
||||
}
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'statistik_manager_enqueue_frontend_styles');
|
||||
|
||||
// Der Menüpunkt "Statistik & Notice" wird zentral in wp_multi_register_admin_menus() registriert.
|
||||
|
||||
// Funktion für die Plugin-Optionen-Seite
|
||||
function statistik_manager_options_page() {
|
||||
wpmt_admin_page_open(
|
||||
__('Statistik & Notice', 'statistik-manager'),
|
||||
__('Statistik-Shortcode, Lesezeichen und Frontend-Banner konfigurieren', 'statistik-manager')
|
||||
);
|
||||
|
||||
wpmt_admin_card_open(__('Einstellungen', 'statistik-manager'));
|
||||
?>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('statistik_manager_settings_group');
|
||||
do_settings_sections('statistik_manager');
|
||||
?>
|
||||
<h2><?php _e('Statistiken anzeigen', 'statistik-manager'); ?></h2>
|
||||
<table class="form-table">
|
||||
<tr valign="top">
|
||||
<th scope="row"><?php _e('Anzeigen', 'statistik-manager'); ?></th>
|
||||
<td>
|
||||
<input type="checkbox" name="statistik_manager_show_posts" value="1" <?php checked(get_option('statistik_manager_show_posts'), 1); ?> />
|
||||
<label for="statistik_manager_show_posts"><?php _e('Beiträge anzeigen', 'statistik-manager'); ?></label><br>
|
||||
<input type="checkbox" name="statistik_manager_show_comments" value="1" <?php checked(get_option('statistik_manager_show_comments'), 1); ?> />
|
||||
<label for="statistik_manager_show_comments"><?php _e('Kommentare anzeigen', 'statistik-manager'); ?></label><br>
|
||||
<input type="checkbox" name="statistik_manager_show_categories" value="1" <?php checked(get_option('statistik_manager_show_categories'), 1); ?> />
|
||||
<label for="statistik_manager_show_categories"><?php _e('Kategorien anzeigen', 'statistik-manager'); ?></label><br>
|
||||
<input type="checkbox" name="statistik_manager_show_series" value="1" <?php checked(get_option('statistik_manager_show_series'), 1); ?> />
|
||||
<label for="statistik_manager_show_series"><?php _e('Serien anzeigen', 'statistik-manager'); ?></label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><?php _e('Kategorien auswählen', 'statistik-manager'); ?></h2>
|
||||
<table class="form-table">
|
||||
<tr valign="top">
|
||||
<th scope="row"><?php _e('Angezeigte Kategorien', 'statistik-manager'); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
$categories = get_terms(array(
|
||||
'taxonomy' => 'category',
|
||||
'orderby' => 'name',
|
||||
'order' => 'ASC',
|
||||
'hide_empty' => false,
|
||||
));
|
||||
|
||||
if (!empty($categories) && !is_wp_error($categories)) :
|
||||
$selected_categories = get_option('statistik_manager_selected_categories', []);
|
||||
?>
|
||||
<select name="statistik_manager_selected_categories[]" multiple="multiple" style="width: 300px; height: 150px;">
|
||||
<?php foreach ($categories as $category) : ?>
|
||||
<option value="<?php echo esc_attr($category->term_id); ?>"
|
||||
<?php echo in_array($category->term_id, $selected_categories) ? 'selected' : ''; ?>>
|
||||
<?php echo esc_html($category->name); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><?php _e('Eröffnungsdatum der Webseite', 'statistik-manager'); ?></h2>
|
||||
<table class="form-table">
|
||||
<tr valign="top">
|
||||
<th scope="row"><?php _e('Eröffnungsdatum', 'statistik-manager'); ?></th>
|
||||
<td>
|
||||
<input type="date" name="statistik_manager_opening_date" value="<?php echo esc_attr(get_option('statistik_manager_opening_date')); ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Banner-Einstellungen</h2>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>Banner anzeigen</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statistik_manager_banner_enabled" value="1" <?php checked(get_option('statistik_manager_banner_enabled', 1)); ?> />
|
||||
<label for="statistik_manager_banner_enabled">Banner aktivieren</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Banner Text</th>
|
||||
<td><input type="text" name="statistik_manager_banner_text" value="<?php echo esc_attr(get_option('statistik_manager_banner_text', 'Willkommen auf unserer Webseite!')); ?>" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Banner Farbe</th>
|
||||
<td><input type="color" name="statistik_manager_banner_color" value="<?php echo esc_attr(get_option('statistik_manager_banner_color', '#0073aa')); ?>" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Banner Position</th>
|
||||
<td>
|
||||
<select name="statistik_manager_banner_position">
|
||||
<option value="top" <?php selected(get_option('statistik_manager_banner_position'), 'top'); ?>>Oben</option>
|
||||
<option value="bottom" <?php selected(get_option('statistik_manager_banner_position'), 'bottom'); ?>>Unten</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Icon auswählen</th>
|
||||
<td>
|
||||
<select name="statistik_manager_banner_icon">
|
||||
<option value="fas fa-info-circle" <?php selected(get_option('statistik_manager_banner_icon'), 'fas fa-info-circle'); ?>>ℹ️ Info</option>
|
||||
<option value="fas fa-exclamation-triangle" <?php selected(get_option('statistik_manager_banner_icon'), 'fas fa-exclamation-triangle'); ?>>⚠️ Warnung</option>
|
||||
<option value="fas fa-bell" <?php selected(get_option('statistik_manager_banner_icon'), 'fas fa-bell'); ?>>🔔 Benachrichtigung</option>
|
||||
<option value="fas fa-thumbs-up" <?php selected(get_option('statistik_manager_banner_icon'), 'fas fa-thumbs-up'); ?>>👍 Daumen hoch</option>
|
||||
<option value="">Kein Icon</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Icon anzeigen</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statistik_manager_show_icon" value="1" <?php checked(get_option('statistik_manager_show_icon', 1)); ?> />
|
||||
<label for="statistik_manager_show_icon">Icon anzeigen</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Schriftgröße</th>
|
||||
<td>
|
||||
<select name="statistik_manager_banner_font_size">
|
||||
<option value="small" <?php selected(get_option('statistik_manager_banner_font_size'), 'small'); ?>>Klein</option>
|
||||
<option value="medium" <?php selected(get_option('statistik_manager_banner_font_size'), 'medium'); ?>>Mittel</option>
|
||||
<option value="large" <?php selected(get_option('statistik_manager_banner_font_size'), 'large'); ?>>Groß</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
echo '<div class="wpm-grid wpm-grid--2">';
|
||||
|
||||
wpmt_admin_card_open(__('Kurzanleitung: Statistik-Box', 'statistik-manager'));
|
||||
?>
|
||||
<ol>
|
||||
<li><strong>Shortcode einfügen:</strong> Füge <code>[statistik_manager]</code> an der gewünschten Stelle in einem Beitrag oder einer Seite ein.</li>
|
||||
<li><strong>Statistiken wählen:</strong> Beiträge, Kommentare, Kategorien und Serien lassen sich einzeln ein- und ausblenden.</li>
|
||||
<li><strong>Kategorien:</strong> Wähle aus, welche Kategorien in die Zählung einbezogen werden.</li>
|
||||
<li><strong>Eröffnungsdatum:</strong> Wird automatisch in der Statistik-Box angezeigt.</li>
|
||||
<li><strong>Banner:</strong> Ein konfigurierbares Hinweis-Banner kann im Header oder Footer der Website eingeblendet werden.</li>
|
||||
</ol>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
wpmt_admin_card_open(__('Kurzanleitung: Lesezeichen', 'statistik-manager'));
|
||||
?>
|
||||
<ol>
|
||||
<li><strong>Anzeigen:</strong> Der Shortcode <code>[display_bookmarks]</code> listet die gespeicherten Lesezeichen der Besucher auf.</li>
|
||||
<li><strong>Hinzufügen:</strong> Über <code>[add_bookmark]</code> erhalten Besucher ein Formular zum Speichern eines Lesezeichens.</li>
|
||||
<li><strong>Löschen:</strong> Nur der Besitzer eines Lesezeichens kann es über den Löschen-Button entfernen.</li>
|
||||
</ol>
|
||||
<p><?php printf(__('Weitere Plugins der WP-Multi-Familie findest du auf %s.', 'statistik-manager'), '<a href="https://git.viper.ipv64.net/M_Viper" target="_blank">git.viper.ipv64.net</a>'); ?></p>
|
||||
<?php
|
||||
wpmt_admin_card_close();
|
||||
|
||||
echo '</div>';
|
||||
|
||||
wpmt_admin_page_close();
|
||||
}
|
||||
|
||||
// Optionen registrieren
|
||||
function statistik_manager_register_settings() {
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_show_posts');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_show_comments');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_show_categories');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_show_series');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_selected_categories');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_opening_date');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_banner_text');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_banner_color', [
|
||||
'sanitize_callback' => 'sanitize_hex_color',
|
||||
]);
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_banner_position');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_banner_enabled');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_banner_icon', [
|
||||
'sanitize_callback' => function($value) {
|
||||
// Icon-Wert besteht aus mehreren space-getrennten CSS-Klassen (z. B. "fas fa-bell")
|
||||
$classes = array_map('sanitize_html_class', explode(' ', (string) $value));
|
||||
return implode(' ', array_filter($classes));
|
||||
},
|
||||
]);
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_show_icon');
|
||||
register_setting('statistik_manager_settings_group', 'statistik_manager_banner_font_size');
|
||||
|
||||
}
|
||||
add_action('admin_init', 'statistik_manager_register_settings');
|
||||
|
||||
// Standardwerte setzen
|
||||
function statistik_manager_set_default_options() {
|
||||
if (get_option('statistik_manager_show_posts') === false) {
|
||||
update_option('statistik_manager_show_posts', 1);
|
||||
}
|
||||
if (get_option('statistik_manager_show_comments') === false) {
|
||||
update_option('statistik_manager_show_comments', 1);
|
||||
}
|
||||
if (get_option('statistik_manager_show_categories') === false) {
|
||||
update_option('statistik_manager_show_categories', 1);
|
||||
}
|
||||
if (get_option('statistik_manager_show_series') === false) {
|
||||
update_option('statistik_manager_show_series', 1);
|
||||
}
|
||||
if (get_option('statistik_manager_selected_categories') === false) {
|
||||
update_option('statistik_manager_selected_categories', []);
|
||||
}
|
||||
if (get_option('statistik_manager_banner_enabled') === false) {
|
||||
update_option('statistik_manager_banner_enabled', 1);
|
||||
}
|
||||
if (get_option('statistik_manager_banner_font_size') === false) {
|
||||
update_option('statistik_manager_banner_font_size', 'medium');
|
||||
}
|
||||
|
||||
}
|
||||
add_action('admin_init', 'statistik_manager_set_default_options');
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* WP Multi – Modul: Admin-Dashboard Update-Anzeige
|
||||
*
|
||||
* Automatisch aus wp-multi.php ausgelagert. Wird über den Loader in
|
||||
* wp-multi.php eingebunden (nur wenn das WP Multi Toolkit aktiv ist).
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
/*
|
||||
* Admin Dashboard Update-Anzeige
|
||||
*/
|
||||
|
||||
define('WP_MULTI_UPDATE_REPO', 'wp-multi');
|
||||
define('WP_MULTI_UPDATE_CACHE_KEY', 'wp_multi_latest_release');
|
||||
define('WP_MULTI_UPDATE_HOST', 'git.viper.ipv64.net');
|
||||
|
||||
// Fragt den Gitea-Server nach dem neuesten Release ab (gecached via Transient)
|
||||
function wp_multi_get_latest_release() {
|
||||
$cached = get_transient(WP_MULTI_UPDATE_CACHE_KEY);
|
||||
if ($cached !== false) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$api_url = 'https://' . WP_MULTI_UPDATE_HOST . '/api/v1/repos/M_Viper/' . WP_MULTI_UPDATE_REPO . '/releases';
|
||||
$response = wp_remote_get($api_url, array(
|
||||
'timeout' => 10,
|
||||
'headers' => array('Accept' => 'application/json'),
|
||||
));
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
// Kurz erneut versuchen statt für 12 Stunden zu sperren
|
||||
set_transient(WP_MULTI_UPDATE_CACHE_KEY, false, HOUR_IN_SECONDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$releases = json_decode($body, true);
|
||||
|
||||
if (empty($releases) || !is_array($releases)) {
|
||||
set_transient(WP_MULTI_UPDATE_CACHE_KEY, false, HOUR_IN_SECONDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
usort($releases, function ($a, $b) {
|
||||
$a_date = !empty($a['created_at']) ? $a['created_at'] : '';
|
||||
$b_date = !empty($b['created_at']) ? $b['created_at'] : '';
|
||||
return strtotime($b_date) - strtotime($a_date);
|
||||
});
|
||||
|
||||
$latest = false;
|
||||
foreach ($releases as $release) {
|
||||
if (!empty($release['prerelease'])) {
|
||||
continue;
|
||||
}
|
||||
if (!empty($release['tag_name'])) {
|
||||
// Nur Download-URLs auf dem erwarteten Host akzeptieren
|
||||
$html_url = !empty($release['html_url']) ? $release['html_url'] : '';
|
||||
$release_host = $html_url ? wp_parse_url($html_url, PHP_URL_HOST) : '';
|
||||
$latest = array(
|
||||
'version' => ltrim($release['tag_name'], 'v'),
|
||||
'url' => ($release_host === WP_MULTI_UPDATE_HOST)
|
||||
? esc_url_raw($html_url)
|
||||
: 'https://' . WP_MULTI_UPDATE_HOST . '/M_Viper/' . WP_MULTI_UPDATE_REPO . '/releases',
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_transient(WP_MULTI_UPDATE_CACHE_KEY, $latest, 12 * HOUR_IN_SECONDS);
|
||||
return $latest;
|
||||
}
|
||||
|
||||
// Liest die installierte Version aus dem Plugin-Header
|
||||
function wp_multi_get_installed_version() {
|
||||
if (!function_exists('get_plugin_data')) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
$data = get_plugin_data(WP_MULTI_FILE, false, false);
|
||||
return !empty($data['Version']) ? $data['Version'] : '0';
|
||||
}
|
||||
|
||||
// Dashboard-Widget registrieren
|
||||
function wp_multi_add_update_dashboard_widget() {
|
||||
wp_add_dashboard_widget(
|
||||
'wp_multi_update_widget',
|
||||
__('WP Multi - Update-Status', 'wp-multi'),
|
||||
'wp_multi_update_dashboard_widget_content'
|
||||
);
|
||||
}
|
||||
add_action('wp_dashboard_setup', 'wp_multi_add_update_dashboard_widget');
|
||||
|
||||
// Zeigt im Dashboard-Widget an, ob WP Multi aktuell ist oder ein Update verfügbar ist
|
||||
function wp_multi_update_dashboard_widget_content() {
|
||||
$installed_version = wp_multi_get_installed_version();
|
||||
$latest = wp_multi_get_latest_release();
|
||||
|
||||
echo '<p><strong>' . esc_html__('Installierte Version:', 'wp-multi') . '</strong> ' . esc_html($installed_version) . '</p>';
|
||||
|
||||
if (!$latest || empty($latest['version'])) {
|
||||
echo '<p>' . esc_html__('Der Update-Server konnte nicht erreicht werden.', 'wp-multi') . '</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
if (version_compare($latest['version'], $installed_version, '>')) {
|
||||
echo '<p style="color:#dc3545;"><strong>' . esc_html__('Update verfügbar:', 'wp-multi') . '</strong> ' . esc_html($latest['version']) . '</p>';
|
||||
echo '<p><a href="' . esc_url($latest['url']) . '" target="_blank" class="button button-primary">' . esc_html__('Update herunterladen', 'wp-multi') . '</a></p>';
|
||||
} else {
|
||||
echo '<p style="color:#28a745;"><strong>' . esc_html__('WP Multi ist aktuell.', 'wp-multi') . '</strong></p>';
|
||||
}
|
||||
}
|
||||
|
||||
// Admin-Hinweis anzeigen, wenn ein Update verfügbar ist
|
||||
function wp_multi_update_admin_notice() {
|
||||
if (!current_user_can('manage_options') || !is_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$installed_version = wp_multi_get_installed_version();
|
||||
$latest = wp_multi_get_latest_release();
|
||||
|
||||
if (!$latest || empty($latest['version'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (version_compare($latest['version'], $installed_version, '>')) {
|
||||
printf(
|
||||
'<div class="notice notice-warning is-dismissible"><p>%1$s <a href="%2$s" target="_blank">%3$s</a></p></div>',
|
||||
sprintf(
|
||||
esc_html__('Für "WP Multi" ist ein Update verfügbar: Version %1$s (installiert: %2$s).', 'wp-multi'),
|
||||
esc_html($latest['version']),
|
||||
esc_html($installed_version)
|
||||
),
|
||||
esc_url($latest['url']),
|
||||
esc_html__('Jetzt herunterladen', 'wp-multi')
|
||||
);
|
||||
}
|
||||
}
|
||||
add_action('admin_notices', 'wp_multi_update_admin_notice');
|
||||
|
||||
|
||||
+51
-5316
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user