Update from Git Manager GUI
This commit is contained in:
@@ -367,6 +367,11 @@ function wbf_admin_page() {
|
||||
$existing = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}forum_%'");
|
||||
$missing = array_filter($exp_tables, fn($t) => !in_array($wpdb->prefix.$t, $existing));
|
||||
|
||||
// ── MC Bridge StatusAPI ───────────────────────────────────────────────────
|
||||
$mc_s = wbf_get_settings();
|
||||
$mc_enabled = ! empty( $mc_s['mc_bridge_enabled'] );
|
||||
$mc_api_url = trim( $mc_s['mc_bridge_api_url'] ?? '' );
|
||||
|
||||
// ── Trends ────────────────────────────────────────────────────────────────
|
||||
$pt = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}forum_posts WHERE deleted_at IS NULL AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
||||
$pl = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}forum_posts WHERE deleted_at IS NULL AND created_at BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY) AND DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
||||
@@ -482,6 +487,11 @@ function wbf_admin_page() {
|
||||
</div>
|
||||
|
||||
<!-- ═══════════ SYSTEM BAR ════════════════════════════════════════════════ -->
|
||||
<?php
|
||||
// Plugin-Status prüfen
|
||||
$gallery_active = class_exists('MC_Gallery_Core');
|
||||
$shop_active = class_exists('WIS_DB');
|
||||
?>
|
||||
<div class="wbf-sysbar">
|
||||
<span class="wbf-sysbar__label">System</span>
|
||||
<span class="wbf-sbadge <?php echo $php_rec?'wbf-sbadge--ok':($php_ok?'wbf-sbadge--warn':'wbf-sbadge--err'); ?>">
|
||||
@@ -494,11 +504,57 @@ function wbf_admin_page() {
|
||||
<i class="fas fa-<?php echo $mail_ok?'envelope-circle-check':'xmark'; ?>"></i> wp_mail
|
||||
</span>
|
||||
<div class="wbf-sdivider"></div>
|
||||
<span class="wbf-sbadge <?php echo $gallery_active?'wbf-sbadge--ok':'wbf-sbadge--err'; ?>">
|
||||
<i class="fas fa-images"></i> Galerie: <?php echo $gallery_active?'Aktiv':'Nicht aktiv'; ?>
|
||||
</span>
|
||||
<span class="wbf-sbadge <?php echo $shop_active?'wbf-sbadge--ok':'wbf-sbadge--err'; ?>">
|
||||
<i class="fas fa-shopping-cart"></i> Shop: <?php echo $shop_active?'Aktiv':'Nicht aktiv'; ?>
|
||||
</span>
|
||||
<div class="wbf-sdivider"></div>
|
||||
<?php if (empty($missing)): ?>
|
||||
<span class="wbf-sbadge wbf-sbadge--ok"><i class="fas fa-table-columns"></i> <?php echo count($exp_tables); ?> Tabellen OK</span>
|
||||
<?php else: ?>
|
||||
<span class="wbf-sbadge wbf-sbadge--err"><i class="fas fa-triangle-exclamation"></i> Fehlende Tabellen: <?php echo esc_html(implode(', ',$missing)); ?></span>
|
||||
<?php endif; ?>
|
||||
<div class="wbf-sdivider"></div>
|
||||
<?php if ( ! $mc_enabled ) : ?>
|
||||
<span class="wbf-sbadge" style="color:#94a3b8;border-color:#e2e8f0;background:#f8fafc" title="MC Bridge in den Einstellungen aktivieren">
|
||||
<i class="fas fa-cubes"></i> MC Bridge: Aus
|
||||
</span>
|
||||
<?php elseif ( empty( $mc_api_url ) ) : ?>
|
||||
<span class="wbf-sbadge wbf-sbadge--warn" title="Keine API-URL konfiguriert">
|
||||
<i class="fas fa-cubes"></i> StatusAPI: Nicht konfiguriert
|
||||
</span>
|
||||
<?php else : ?>
|
||||
<span id="wbf-mc-status-badge" class="wbf-sbadge wbf-sbadge--err" title="Verbindung wird geprüft...">
|
||||
<i class="fas fa-spinner fa-spin"></i> StatusAPI: Prüfe...
|
||||
</span>
|
||||
<script>
|
||||
(function() {
|
||||
var badge = document.getElementById('wbf-mc-status-badge');
|
||||
if (!badge) return;
|
||||
var url = <?php echo json_encode( rest_url( 'mc-bridge/v1/status' ) ); ?>;
|
||||
fetch(url, { cache: 'no-store' })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(d) {
|
||||
if (d && d.success && d.enabled) {
|
||||
badge.className = 'wbf-sbadge wbf-sbadge--ok';
|
||||
badge.title = 'MC Bridge aktiv — Verbindung hergestellt';
|
||||
badge.innerHTML = '<i class="fas fa-cubes"></i> StatusAPI: Verbunden';
|
||||
} else {
|
||||
badge.className = 'wbf-sbadge wbf-sbadge--err';
|
||||
badge.title = 'MC Bridge deaktiviert oder Fehler';
|
||||
badge.innerHTML = '<i class="fas fa-cubes"></i> StatusAPI: Nicht verbunden';
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
badge.className = 'wbf-sbadge wbf-sbadge--err';
|
||||
badge.title = 'WordPress REST-Endpoint nicht erreichbar';
|
||||
badge.innerHTML = '<i class="fas fa-cubes"></i> StatusAPI: Nicht verbunden';
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
<span style="margin-left:auto;font-size:.7rem;color:#94a3b8"><?php echo $online_count; ?> gerade online</span>
|
||||
</div>
|
||||
|
||||
@@ -1346,6 +1402,20 @@ function wbf_admin_members() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// ── Admin: 2FA eines Users zurücksetzen ──────────────────────────────────
|
||||
if ( isset( $_POST['wbf_admin_reset_2fa'] ) && check_admin_referer( 'wbf_admin_2fa_nonce' ) ) {
|
||||
if ( current_user_can('manage_options') && class_exists('WBF_TOTP') ) {
|
||||
$uid = (int) ( $_POST['user_id'] ?? 0 );
|
||||
if ( $uid ) {
|
||||
$target = WBF_DB::get_user( $uid );
|
||||
if ( $target && $target->role !== WBF_Roles::SUPERADMIN ) {
|
||||
WBF_TOTP::disable_for( $uid );
|
||||
echo '<div class="notice notice-success is-dismissible"><p>2FA für <strong>'
|
||||
. esc_html($target->display_name) . '</strong> zurückgesetzt.</p></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$members = WBF_DB::get_all_users( 200 );
|
||||
$s_discord = wbf_get_settings();
|
||||
@@ -1546,6 +1616,30 @@ function wbf_admin_members() {
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- 2FA Admin-Panel -->
|
||||
<?php if ( class_exists('WBF_TOTP') && ! $is_sa ) : ?>
|
||||
<div id="wbf-2fa-admin-<?php echo (int)$m->id; ?>"
|
||||
style="margin-top:6px;padding:8px 10px;background:#fefce8;border:1px solid #fde68a;border-radius:4px;font-size:12px">
|
||||
<strong style="color:#92400e"><i class="fas fa-shield-halved"></i> 2FA-Status:</strong>
|
||||
<?php if ( WBF_TOTP::is_enabled_for($m->id) ) : ?>
|
||||
<span style="color:#16a34a;font-weight:600"> ✔ Aktiv</span>
|
||||
<form method="post" style="display:inline;margin-left:10px">
|
||||
<?php wp_nonce_field( 'wbf_admin_2fa_nonce' ); ?>
|
||||
<input type="hidden" name="user_id" value="<?php echo (int)$m->id; ?>">
|
||||
<button type="submit" name="wbf_admin_reset_2fa"
|
||||
class="button button-small"
|
||||
style="color:#dc2626;border-color:rgba(220,38,38,.4);font-size:11px"
|
||||
onclick="return confirm('2FA für <?php echo esc_js($m->display_name); ?> zurücksetzen?')">
|
||||
<span class="dashicons dashicons-unlock" style="font-size:13px;width:13px;height:13px;vertical-align:-2px"></span>
|
||||
2FA zurücksetzen
|
||||
</button>
|
||||
</form>
|
||||
<?php else : ?>
|
||||
<span style="color:#9ca3af"> — Nicht aktiv</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Inline Profil-Editor -->
|
||||
<div id="wbf-edit-user-<?php echo (int)$m->id; ?>" style="display:none;margin-top:8px;padding:12px;background:#f9f9f9;border:1px solid #ddd;border-radius:4px;max-width:480px">
|
||||
<strong style="font-size:13px">Profil bearbeiten: <?php echo esc_html($m->display_name); ?></strong>
|
||||
|
||||
89
admin/forum-settings-mc-section.php
Normal file
89
admin/forum-settings-mc-section.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* MC Bridge — Einstellungs-Sektion für den Forum-Admin
|
||||
*
|
||||
* Diesen Block in forum-settings.php im Admin-Formular einfügen,
|
||||
* z.B. nach der Discord-Sektion.
|
||||
*/
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
?>
|
||||
|
||||
<!-- ═══ Minecraft Bridge ═══ -->
|
||||
<div class="wbf-settings-section">
|
||||
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
|
||||
<span style="font-size:1.3em">⛏️</span> Minecraft Bridge
|
||||
</h3>
|
||||
<p class="description" style="margin-bottom:16px;color:#9ca3af">
|
||||
Verbindet das Forum mit deinem Minecraft-Server (BungeeCord StatusAPI Plugin).
|
||||
Spieler können ihren Forum-Account verknüpfen und erhalten Ingame-Benachrichtigungen
|
||||
bei neuen Antworten, Erwähnungen und Privatnachrichten.
|
||||
</p>
|
||||
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>Aktiviert</th>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" name="wbf_settings[mc_bridge_enabled]" value="1"
|
||||
<?php checked( ! empty( $s['mc_bridge_enabled'] ) ); ?>>
|
||||
MC Bridge aktivieren
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>StatusAPI URL</th>
|
||||
<td>
|
||||
<input type="url" name="wbf_settings[mc_bridge_api_url]"
|
||||
value="<?php echo esc_attr( $s['mc_bridge_api_url'] ?? '' ); ?>"
|
||||
class="regular-text"
|
||||
placeholder="http://192.168.1.100:9191">
|
||||
<p class="description">
|
||||
Die URL deines BungeeCord StatusAPI Servers (IP + Port).
|
||||
Beispiel: <code>http://dein-server:9191</code>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>API Secret</th>
|
||||
<td>
|
||||
<input type="password" name="wbf_settings[mc_bridge_api_secret]"
|
||||
value="<?php echo esc_attr( $s['mc_bridge_api_secret'] ?? '' ); ?>"
|
||||
class="regular-text"
|
||||
autocomplete="new-password">
|
||||
<p class="description">
|
||||
Gemeinsames Passwort für die API-Kommunikation.
|
||||
Muss identisch sein mit <code>forum.api_secret</code> in der
|
||||
<code>verify.properties</code> des StatusAPI Plugins.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Verbindungstest</th>
|
||||
<td>
|
||||
<button type="button" id="wbf-mc-test-btn" class="button"
|
||||
onclick="wbfTestMcConnection()">
|
||||
🔌 Verbindung testen
|
||||
</button>
|
||||
<span id="wbf-mc-test-result" style="margin-left:10px"></span>
|
||||
<script>
|
||||
function wbfTestMcConnection() {
|
||||
var btn = document.getElementById('wbf-mc-test-btn');
|
||||
var result = document.getElementById('wbf-mc-test-result');
|
||||
var url = document.querySelector('input[name="wbf_settings[mc_bridge_api_url]"]').value;
|
||||
if (!url) { result.textContent = '❌ Bitte erst eine URL eingeben.'; return; }
|
||||
btn.disabled = true;
|
||||
result.textContent = '⏳ Teste...';
|
||||
fetch(url.replace(/\/$/, '') + '/forum/status')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(d) {
|
||||
if (d.success) result.innerHTML = '✅ <strong>Verbunden!</strong> StatusAPI v' + (d.version || '?');
|
||||
else result.textContent = '⚠️ Erreichbar aber Fehler: ' + JSON.stringify(d);
|
||||
})
|
||||
.catch(function(e) { result.textContent = '❌ Nicht erreichbar: ' + e.message; })
|
||||
.finally(function() { btn.disabled = false; });
|
||||
}
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -61,12 +61,17 @@ if ( ! function_exists('wbf_get_settings') ) {
|
||||
'discord_client_secret' => '',
|
||||
'discord_role_sync' => '0', // Rollen-Sync aktiviert?
|
||||
'discord_role_map' => '', // JSON: {"discord_role_id":"forum_role_key"}
|
||||
// Minecraft Bridge
|
||||
'mc_bridge_enabled' => '0',
|
||||
'mc_bridge_api_url' => '',
|
||||
'mc_bridge_api_secret' => '',
|
||||
];
|
||||
|
||||
$saved = get_option( 'wbf_settings', [] );
|
||||
|
||||
// Fehlende Keys mit Defaults auffüllen, leere Strings ignorieren
|
||||
return array_merge( $defaults, array_filter( (array) $saved, 'strlen' ) );
|
||||
// Keine Filterung mehr, damit auch bewusst geleerte Felder gespeichert werden
|
||||
return array_merge( $defaults, (array) $saved );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,9 +163,13 @@ function wbf_admin_settings() {
|
||||
}
|
||||
$settings['discord_role_map'] = json_encode($role_map);
|
||||
|
||||
// ── Minecraft Bridge ──────────────────────────────────────────────────
|
||||
$settings['mc_bridge_api_url'] = esc_url_raw( trim( $_POST['mc_bridge_api_url'] ?? '' ) );
|
||||
$settings['mc_bridge_api_secret'] = sanitize_text_field( $_POST['mc_bridge_api_secret'] ?? '' );
|
||||
|
||||
// Checkbox-Felder explizit als '0' speichern wenn nicht angehakt,
|
||||
// damit array_filter(...,'strlen') sie nicht wegwirft und der Default '1' greift.
|
||||
$checkbox_fields = ['maintenance_mode', 'rules_enabled', 'rules_accept_required'];
|
||||
$checkbox_fields = ['maintenance_mode', 'rules_enabled', 'rules_accept_required', 'mc_bridge_enabled'];
|
||||
foreach ( $checkbox_fields as $cb ) {
|
||||
$settings[$cb] = isset($_POST[$cb]) && $_POST[$cb] === '1' ? '1' : '0';
|
||||
}
|
||||
@@ -731,6 +740,116 @@ function wbf_admin_settings() {
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
Minecraft Bridge
|
||||
════════════════════════════════════════════════════════════ -->
|
||||
<div class="wbf-settings-box" style="margin-top:2rem;padding:1.5rem;border:1px solid #e5e7eb;border-radius:8px;background:#f9fafb">
|
||||
<h2 style="margin-top:0;display:flex;align-items:center;gap:8px">
|
||||
<span style="font-size:1.3em">⛏️</span> Minecraft Bridge
|
||||
</h2>
|
||||
<p class="description" style="margin-bottom:1.2rem;color:#6b7280">
|
||||
Verbindet das Forum mit deinem BungeeCord-Server (StatusAPI Plugin).
|
||||
Spieler können ihren Forum-Account mit <code>/forumlink <token></code> verknüpfen
|
||||
und erhalten dann Ingame-Benachrichtigungen bei neuen Antworten, Erwähnungen und PNs.
|
||||
</p>
|
||||
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope="row">Aktiviert</th>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" name="mc_bridge_enabled" value="1"
|
||||
<?php checked( '1', $s['mc_bridge_enabled'] ?? '0' ); ?>>
|
||||
Minecraft Bridge aktivieren
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="wbf_mc_api_url">StatusAPI URL</label></th>
|
||||
<td>
|
||||
<input type="url" id="wbf_mc_api_url" name="mc_bridge_api_url"
|
||||
value="<?php echo esc_attr( $s['mc_bridge_api_url'] ?? '' ); ?>"
|
||||
class="regular-text"
|
||||
placeholder="http://dein-server:9191">
|
||||
<p class="description">
|
||||
IP + Port deines BungeeCord StatusAPI Servers.
|
||||
Beispiel: <code>http://192.168.1.100:9191</code>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="wbf_mc_api_secret">API Secret</label></th>
|
||||
<td>
|
||||
<input type="password" id="wbf_mc_api_secret" name="mc_bridge_api_secret"
|
||||
value="<?php echo esc_attr( $s['mc_bridge_api_secret'] ?? '' ); ?>"
|
||||
class="regular-text"
|
||||
autocomplete="new-password"
|
||||
placeholder="Gemeinsames Passwort">
|
||||
<p class="description">
|
||||
Muss identisch sein mit <code>forum.api_secret</code> in der
|
||||
<code>verify.properties</code> des StatusAPI Plugins.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Verbindungstest</th>
|
||||
<td>
|
||||
<button type="button" id="wbf-mc-test-btn" class="button"
|
||||
onclick="wbfTestMcConnection()">
|
||||
🔌 Verbindung testen
|
||||
</button>
|
||||
<span id="wbf-mc-test-result" style="margin-left:10px;font-weight:600"></span>
|
||||
<script>
|
||||
function wbfTestMcConnection() {
|
||||
var btn = document.getElementById('wbf-mc-test-btn');
|
||||
var result = document.getElementById('wbf-mc-test-result');
|
||||
var url = document.getElementById('wbf_mc_api_url').value.replace(/\/$/, '');
|
||||
if (!url) { result.style.color='#dc2626'; result.textContent = '❌ Bitte erst eine URL eingeben.'; return; }
|
||||
btn.disabled = true;
|
||||
result.style.color = '#6b7280';
|
||||
result.textContent = '⏳ Teste Verbindung...';
|
||||
// Test gegen WordPress REST-Endpoint (sicherer als direkter BungeeCord-Aufruf vom Browser)
|
||||
fetch('<?php echo esc_url( rest_url("mc-bridge/v1/status") ); ?>')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(d) {
|
||||
if (d.success) {
|
||||
result.style.color = '#16a34a';
|
||||
result.innerHTML = '✅ <strong>WordPress-Endpoint aktiv!</strong> Plugin v' + (d.version || '?');
|
||||
} else {
|
||||
result.style.color = '#dc2626';
|
||||
result.textContent = '⚠️ Endpoint antwortet, aber Fehler: ' + JSON.stringify(d);
|
||||
}
|
||||
})
|
||||
.catch(function(e) {
|
||||
result.style.color = '#dc2626';
|
||||
result.textContent = '❌ Nicht erreichbar: ' + e.message;
|
||||
})
|
||||
.finally(function() { btn.disabled = false; });
|
||||
}
|
||||
</script>
|
||||
<p class="description" style="margin-top:.5rem">
|
||||
Testet ob der WordPress REST-Endpoint <code>/wp-json/mc-bridge/v1/status</code> erreichbar ist.
|
||||
Danach in <code>verify.properties</code>: <code>forum.wp_url</code> und <code>forum.api_secret</code> eintragen.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="background:#fffbeb;border:1px solid #fcd34d;border-radius:6px;padding:1rem;margin-top:1rem;font-size:.875rem">
|
||||
<strong>⚙️ Einrichtung in 3 Schritten:</strong>
|
||||
<ol style="margin:.5rem 0 0 1.2rem;padding:0;line-height:1.8">
|
||||
<li>API Secret hier festlegen und Einstellungen speichern.</li>
|
||||
<li>In <code>verify.properties</code> des BungeeCord-Plugins setzen:
|
||||
<br><code>forum.enabled=true</code>
|
||||
<br><code>forum.wp_url=<?php echo esc_html( get_site_url() ); ?></code>
|
||||
<br><code>forum.api_secret=DEIN_SECRET</code>
|
||||
</li>
|
||||
<li>Spieler können sich nun mit <strong><code>/forumlink <token></code></strong> ingame verknüpfen.
|
||||
Den Token generieren sie in ihrem Forum-Profil unter dem Tab <em>Verbindungen</em>.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php submit_button(
|
||||
'💾 Einstellungen speichern',
|
||||
'primary',
|
||||
|
||||
@@ -125,8 +125,12 @@ class WBF_Setup {
|
||||
$page_title = sanitize_text_field($_POST['page_title'] ?? 'Forum');
|
||||
|
||||
if ($create_page) {
|
||||
$existing = get_posts(['post_type'=>'page','s'=>$page_title,'posts_per_page'=>1]);
|
||||
if (empty($existing)) {
|
||||
global $wpdb;
|
||||
$existing_id = $wpdb->get_var( $wpdb->prepare(
|
||||
"SELECT ID FROM {$wpdb->posts} WHERE post_type = 'page' AND post_status = 'publish' AND post_content LIKE %s LIMIT 1",
|
||||
'%[business_forum]%'
|
||||
) );
|
||||
if (empty($existing_id)) {
|
||||
$page_id = wp_insert_post([
|
||||
'post_title' => $page_title,
|
||||
'post_content' => '[business_forum]',
|
||||
|
||||
Reference in New Issue
Block a user