Update from Git Manager GUI

This commit is contained in:
2026-03-29 13:35:46 +02:00
parent 7ef72641f6
commit b0bec83593
3 changed files with 1454 additions and 83 deletions

View File

@@ -0,0 +1,691 @@
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* MC_Gallery_Forum_Bridge
*
* Optionale Integration zwischen MC MultiServer Gallery PRO und WP Business Forum.
* Wird nur initialisiert wenn beide Plugins aktiv sind (class_exists-Check).
*
* Features:
* - Forum-User können ihren Minecraft-Account im Profil verknüpfen
* - Verknüpfte + verifizierte User können in der Galerie ohne Ingame-Token hochladen
* - Admin kann Verknüpfungen in der Forum-Benutzerverwaltung einsehen & bestätigen
* - Automatische Verifikation wenn ein gültiger Ingame-Token für diesen MC-Namen vorliegt
*
* Datenspeicherung: forum_user_meta (bereits vorhanden im Forum-Schema)
*/
class MC_Gallery_Forum_Bridge {
// Meta-Keys (gespeichert in forum_user_meta)
const META_MC_USER = 'mc_linked_username';
const META_MC_SERVER = 'mc_linked_server';
const META_VERIFIED = 'mc_link_verified';
const NONCE_ACTION = 'mc_gallery_forum_bridge';
// ── Bootstrap ─────────────────────────────────────────────────────────────
public static function init() {
// Nur laden wenn beide Plugins aktiv sind
if ( ! class_exists( 'WBF_Auth' ) || ! class_exists( 'MC_Gallery_Helpers' ) ) {
return;
}
// AJAX-Handler
add_action( 'wp_ajax_mc_forum_link_account', [ __CLASS__, 'ajax_link_account' ] );
add_action( 'wp_ajax_mc_forum_unlink_account', [ __CLASS__, 'ajax_unlink_account' ] );
add_action( 'wp_ajax_mc_forum_verify_upload', [ __CLASS__, 'ajax_verify_upload' ] );
add_action( 'wp_ajax_nopriv_mc_forum_verify_upload', [ __CLASS__, 'ajax_verify_upload' ] );
add_action( 'wp_ajax_mc_forum_admin_approve', [ __CLASS__, 'ajax_admin_approve' ] );
// Hooks in die Gallery-Ausgabe (sofern vorhanden)
add_filter( 'mc_gallery_verify_ui_extra', [ __CLASS__, 'render_verify_panel' ], 10, 2 );
add_filter( 'mc_gallery_can_upload', [ __CLASS__, 'filter_upload_permission' ], 10, 3 );
// Hooks ins Forum
add_filter( 'wbf_profile_tabs', [ __CLASS__, 'add_profile_tab' ], 10, 2 );
add_filter( 'wbf_profile_tab_content', [ __CLASS__, 'render_profile_tab' ], 10, 3 );
add_action( 'wbf_admin_user_row_extra',[ __CLASS__, 'render_admin_user_col' ] );
// CSS laden
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_assets' ] );
add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_assets' ] );
}
public static function enqueue_assets() {
wp_enqueue_style(
'mc-gallery-forum-bridge',
MCGALLERY_PRO_URL . 'assets/css/mc-gallery-forum-bridge.css',
[],
MCGALLERY_PRO_VERSION
);
}
// ── Forum-Profil: Minecraft-Tab ───────────────────────────────────────────
/**
* Neuen Tab "Minecraft" zum Forum-Profil hinzufügen.
* Erwartet dass WBF einen `wbf_profile_tabs`-Filter anbietet.
* Falls nicht: Tab wird ignoriert, kein Fehler.
*/
public static function add_profile_tab( $tabs, $profile_user ) {
$tabs['minecraft'] = [
'label' => '<i class="fas fa-cubes"></i> Minecraft',
'order' => 50,
];
return $tabs;
}
public static function render_profile_tab( $content, $tab, $profile_user ) {
if ( $tab !== 'minecraft' ) return $content;
$current = WBF_Auth::get_current_user();
$is_own = $current && (int) $current->id === (int) $profile_user->id;
$is_mod = $current && WBF_Roles::can( $current, 'manage_users' );
$mc_user = self::get_mc_username( $profile_user->id );
$verified = self::is_verified( $profile_user->id );
$servers = self::get_server_list();
ob_start();
?>
<div class="mc-bridge-profile-tab">
<?php if ( $mc_user ) : ?>
<div class="mc-bridge-linked-card <?php echo $verified ? 'is-verified' : 'is-pending'; ?>">
<img class="mc-bridge-head"
src="https://mc-heads.net/avatar/<?php echo esc_attr( $mc_user ); ?>/48"
alt="" loading="lazy">
<div class="mc-bridge-linked-info">
<span class="mc-bridge-mc-name"><?php echo esc_html( $mc_user ); ?></span>
<?php if ( $verified ) : ?>
<span class="mc-bridge-badge mc-bridge-badge--ok">
<i class="fas fa-check-circle"></i> Verifiziert
</span>
<?php else : ?>
<span class="mc-bridge-badge mc-bridge-badge--wait">
<i class="fas fa-clock"></i> Ausstehend
</span>
<?php endif; ?>
<?php
$sv = self::get_mc_server( $profile_user->id );
if ( $sv ) echo '<span class="mc-bridge-server-hint"><i class="fas fa-server"></i> ' . esc_html( $sv ) . '</span>';
?>
</div>
<?php if ( $is_own || $is_mod ) : ?>
<div class="mc-bridge-actions">
<?php if ( ! $verified && $is_mod ) : ?>
<button type="button" class="mc-bridge-btn mc-bridge-btn--approve"
data-uid="<?php echo (int) $profile_user->id; ?>"
data-nonce="<?php echo wp_create_nonce( self::NONCE_ACTION ); ?>">
<i class="fas fa-check"></i> Bestätigen
</button>
<?php endif; ?>
<?php if ( $is_own ) : ?>
<button type="button" class="mc-bridge-btn mc-bridge-btn--unlink"
data-nonce="<?php echo wp_create_nonce( self::NONCE_ACTION ); ?>">
<i class="fas fa-unlink"></i> Trennen
</button>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php if ( $is_own && ! $verified ) : ?>
<div class="mc-bridge-pending-hint">
<i class="fas fa-info-circle"></i>
Noch nicht verifiziert. Du kannst entweder auf Admin-Bestätigung warten
oder deinen Ingame-Token normal in der Galerie eingeben — dann wird
die Verknüpfung automatisch bestätigt.
</div>
<?php endif; ?>
<?php elseif ( $is_own ) : ?>
<p class="mc-bridge-intro">
Verknüpfe deinen Minecraft-Account mit deinem Forum-Profil.
Danach kannst du Bilder in der Galerie ohne Ingame-Token hochladen.
</p>
<div class="mc-bridge-link-form">
<label>
<span>Minecraft-Benutzername</span>
<input type="text" id="mc-bridge-username"
placeholder="z. B. MvViper123" maxlength="32" autocomplete="off">
</label>
<?php if ( count( $servers ) > 1 ) : ?>
<label>
<span>Server</span>
<select id="mc-bridge-server">
<?php foreach ( $servers as $sid => $sname ) : ?>
<option value="<?php echo esc_attr( $sid ); ?>">
<?php echo esc_html( $sname ); ?>
</option>
<?php endforeach; ?>
</select>
</label>
<?php else :
$first_key = array_key_first( $servers );
echo '<input type="hidden" id="mc-bridge-server" value="' . esc_attr( $first_key ) . '">';
endif; ?>
<button type="button" class="mc-bridge-btn mc-bridge-btn--link"
data-nonce="<?php echo wp_create_nonce( self::NONCE_ACTION ); ?>">
<i class="fas fa-link"></i> Verknüpfen
</button>
</div>
<?php else : ?>
<p class="mc-bridge-intro">Kein Minecraft-Account verknüpft.</p>
<?php endif; ?>
</div>
<script>
(function($){
// Account verknüpfen
$('.mc-bridge-btn--link').on('click', function(){
var mc = $('#mc-bridge-username').val().trim();
var sv = $('#mc-bridge-server').val() || '';
if ( ! mc ) { alert('Bitte einen Minecraft-Namen eingeben.'); return; }
var $btn = $(this).prop('disabled', true).text('Bitte warten…');
$.post(<?php echo json_encode( admin_url('admin-ajax.php') ); ?>, {
action: 'mc_forum_link_account',
mc_username: mc,
server_id: sv,
nonce: $btn.data('nonce')
})
.done(function(r){
if ( r.success ) location.reload();
else { alert(r.data || 'Fehler beim Verknüpfen.'); $btn.prop('disabled', false).html('<i class="fas fa-link"></i> Verknüpfen'); }
})
.fail(function(){ alert('Netzwerkfehler.'); $btn.prop('disabled', false).html('<i class="fas fa-link"></i> Verknüpfen'); });
});
// Trennen
$('.mc-bridge-btn--unlink').on('click', function(){
if ( ! confirm('Minecraft-Konto wirklich trennen?') ) return;
$.post(<?php echo json_encode( admin_url('admin-ajax.php') ); ?>, {
action: 'mc_forum_unlink_account',
nonce: $(this).data('nonce')
})
.done(function(r){
if ( r.success ) location.reload();
else alert(r.data || 'Fehler.');
});
});
// Admin: Bestätigen
$('.mc-bridge-btn--approve').on('click', function(){
var uid = $(this).data('uid');
var nonce = $(this).data('nonce');
var $btn = $(this).prop('disabled', true);
$.post(<?php echo json_encode( admin_url('admin-ajax.php') ); ?>, {
action: 'mc_forum_admin_approve',
user_id: uid,
nonce: nonce
})
.done(function(r){
if ( r.success ) location.reload();
else { alert(r.data || 'Fehler.'); $btn.prop('disabled', false); }
});
});
})(jQuery);
</script>
<?php
return ob_get_clean();
}
// ── AJAX-Handler ──────────────────────────────────────────────────────────
/** Account verknüpfen (eigenes Profil) */
public static function ajax_link_account() {
check_ajax_referer( self::NONCE_ACTION, 'nonce' );
$user = WBF_Auth::get_current_user();
if ( ! $user ) wp_send_json_error( 'Nicht eingeloggt.' );
$mc_user = sanitize_text_field( $_POST['mc_username'] ?? '' );
$server = sanitize_text_field( $_POST['server_id'] ?? '' );
// Validierung
if ( strlen( $mc_user ) < 2 || strlen( $mc_user ) > 32 ) {
wp_send_json_error( 'Ungültiger Minecraft-Name (232 Zeichen).' );
}
if ( ! preg_match( '/^[a-zA-Z0-9_]+$/', $mc_user ) ) {
wp_send_json_error( 'Nur Buchstaben, Zahlen und _ erlaubt.' );
}
// Doppelte Verknüpfung verhindern
if ( self::mc_user_taken( $mc_user, $user->id ) ) {
wp_send_json_error( 'Dieser Minecraft-Name ist bereits mit einem anderen Forum-Konto verknüpft.' );
}
self::set_mc_username( $user->id, $mc_user );
self::set_mc_server( $user->id, $server );
// Verifizierung: automatisch wenn gültiger Ingame-Token vorliegt
$auto_verified = self::check_active_token_for( $mc_user );
self::set_verified( $user->id, $auto_verified );
wp_send_json_success( [
'mc_username' => $mc_user,
'verified' => $auto_verified,
] );
}
/** Account-Verknüpfung trennen */
public static function ajax_unlink_account() {
check_ajax_referer( self::NONCE_ACTION, 'nonce' );
$user = WBF_Auth::get_current_user();
if ( ! $user ) wp_send_json_error( 'Nicht eingeloggt.' );
self::delete_mc_link( $user->id );
wp_send_json_success();
}
/** Admin bestätigt eine ausstehende Verknüpfung */
public static function ajax_admin_approve() {
check_ajax_referer( self::NONCE_ACTION, 'nonce' );
$current = WBF_Auth::get_current_user();
if ( ! $current || ! WBF_Roles::can( $current, 'manage_users' ) ) {
wp_send_json_error( 'Keine Berechtigung.' );
}
$target_id = (int) ( $_POST['user_id'] ?? 0 );
if ( ! $target_id ) wp_send_json_error( 'Ungültige Benutzer-ID.' );
self::set_verified( $target_id, true );
wp_send_json_success();
}
/**
* Galerie-Verify via Forum-Login.
* Wird vom Frontend aufgerufen wenn der User auf "Mit Forum-Login verifizieren" klickt.
* Gibt bei Erfolg MC-Username + Server zurück, die das Gallery-JS dann als würden
* sie aus einem Token-Verify stammen weiterverarbeiten kann.
*/
public static function ajax_verify_upload() {
check_ajax_referer( self::NONCE_ACTION, 'nonce' );
$forum_user = WBF_Auth::get_current_user();
if ( ! $forum_user ) {
wp_send_json_error( [
'code' => 'not_logged_in',
'message' => 'Du musst im Forum eingeloggt sein.',
] );
}
$mc_user = self::get_mc_username( $forum_user->id );
$verified = self::is_verified( $forum_user->id );
if ( ! $mc_user ) {
wp_send_json_error( [
'code' => 'no_mc_link',
'message' => 'Kein Minecraft-Konto verknüpft. Bitte zuerst im Profil verknüpfen.',
] );
}
// Noch nicht verifiziert → Ingame-Token als letzten Ausweg prüfen
if ( ! $verified ) {
if ( self::check_active_token_for( $mc_user ) ) {
self::set_verified( $forum_user->id, true );
$verified = true;
}
}
if ( ! $verified ) {
wp_send_json_error( [
'code' => 'not_verified',
'message' => 'Dein Account ist noch nicht verifiziert. Bitte einen Admin um Bestätigung oder nutze einmalig das Ingame-Token.',
] );
}
$server_id = self::get_mc_server( $forum_user->id )
?: sanitize_text_field( $_POST['server_id'] ?? '' );
wp_send_json_success( [
'mc_username' => $mc_user,
'server_id' => $server_id,
'display_name' => $forum_user->display_name,
'verify_type' => 'forum_login',
] );
}
// ── Filter: Gallery-Upload-Berechtigung ───────────────────────────────────
/**
* Gibt true zurück wenn ein eingeloggter Forum-User einen verifizierten
* Link zu $mc_username hat — ersetzt dann die normale Token-Prüfung.
* Wird nur aufgerufen wenn die Gallery `apply_filters('mc_gallery_can_upload', …)` nutzt.
*/
public static function filter_upload_permission( $allowed, $mc_username, $server_id ) {
if ( $allowed ) return true; // schon erlaubt, nicht überschreiben
$forum_user = WBF_Auth::get_current_user();
if ( ! $forum_user ) return false;
$linked = self::get_mc_username( $forum_user->id );
if ( ! $linked ) return false;
if ( strtolower( $linked ) !== strtolower( $mc_username ) ) return false;
return self::is_verified( $forum_user->id );
}
// ── Filter: Zusätzliche Verify-UI in der Gallery ──────────────────────────
/**
* Hängt unter das normale Verify-Formular einen "Mit Forum-Login"-Bereich.
* Funktioniert wenn die Gallery `apply_filters('mc_gallery_verify_ui_extra', '', $server_id)` aufruft.
*
* Falls der Hook nicht existiert: eigenen Shortcode [mc_gallery_forum_login] nutzen.
*/
public static function render_verify_panel( $html, $server_id ) {
return $html . self::build_verify_panel( $server_id );
}
/**
* Shortcode [mc_gallery_forum_login server_id="survival"]
* Kann manuell auf der Upload-Seite eingebettet werden falls der Hook-Ansatz
* nicht greift.
*/
public static function shortcode_verify_panel( $atts ) {
$atts = shortcode_atts( [ 'server_id' => '' ], $atts );
return self::build_verify_panel( sanitize_text_field( $atts['server_id'] ) );
}
/** Eigentliches HTML für das Verify-Panel */
public static function build_verify_panel( $server_id ) {
$forum_user = WBF_Auth::get_current_user();
$nonce = wp_create_nonce( self::NONCE_ACTION );
$ajax_url = admin_url( 'admin-ajax.php' );
ob_start();
?>
<div class="mc-bridge-verify-wrap" data-server="<?php echo esc_attr( $server_id ); ?>">
<div class="mc-bridge-divider"><span>oder</span></div>
<?php if ( ! $forum_user ) :
$forum_url = function_exists('wbf_get_forum_url') ? wbf_get_forum_url() : '#';
$register_url = function_exists('wbf_get_forum_url') ? wbf_get_forum_url() . '?register=1' : '#';
?>
<div class="mc-bridge-card">
<div class="mc-bridge-card-inner">
<div class="mc-bridge-card-icon">
<i class="fas fa-comments"></i>
</div>
<div class="mc-bridge-card-text">
<div class="mc-bridge-card-label">Forum-Login</div>
<div class="mc-bridge-card-desc">
Direkt hochladen ohne Ingame-Token wenn dein <strong>Minecraft-Account</strong> mit dem Forum verknüpft ist.
</div>
</div>
<div class="mc-bridge-card-actions">
<a href="<?php echo esc_url( $forum_url ); ?>" class="mc-bridge-action-btn">
<i class="fas fa-sign-in-alt"></i> Einloggen
</a>
<a href="<?php echo esc_url( $register_url ); ?>" class="mc-bridge-action-btn-ghost">
<i class="fas fa-external-link-alt"></i> Konto erstellen
</a>
</div>
</div>
</div>
<?php else :
$mc_user = self::get_mc_username( $forum_user->id );
$verified = self::is_verified( $forum_user->id );
$forum_url = function_exists('wbf_get_forum_url')
? wbf_get_forum_url() . '?forum_profile=' . (int) $forum_user->id . '#tab-minecraft'
: '#';
?>
<?php if ( $mc_user && $verified ) : ?>
<div class="mc-bridge-success">
<i class="fas fa-check-circle"></i>
Verifiziert als <strong><?php echo esc_html( $mc_user ); ?></strong>
</div>
<?php elseif ( $mc_user ) : ?>
<div class="mc-bridge-card mc-bridge-card--warn">
<div class="mc-bridge-card-inner">
<img class="mc-bridge-head-sm"
src="https://mc-heads.net/avatar/<?php echo esc_attr( $mc_user ); ?>/44"
alt="" loading="lazy">
<div class="mc-bridge-card-text">
<div class="mc-bridge-card-label">Verknüpft · ausstehend</div>
<div class="mc-bridge-card-desc">
<strong><?php echo esc_html( $mc_user ); ?></strong>
· Noch nicht bestätigt
</div>
</div>
<button type="button"
class="mc-bridge-verify-trigger"
data-ajax="<?php echo esc_attr( $ajax_url ); ?>"
data-nonce="<?php echo esc_attr( $nonce ); ?>"
data-server="<?php echo esc_attr( $server_id ); ?>">
<i class="fas fa-sign-in-alt"></i> Mit Forum verifizieren
</button>
</div>
</div>
<?php else : ?>
<div class="mc-bridge-card">
<div class="mc-bridge-card-inner">
<div class="mc-bridge-card-icon">
<i class="fas fa-user-circle"></i>
</div>
<div class="mc-bridge-card-text">
<div class="mc-bridge-card-label">Eingeloggt als <?php echo esc_html( $forum_user->display_name ); ?></div>
<div class="mc-bridge-card-desc">
Noch kein Minecraft-Konto verknüpft.
</div>
</div>
<div class="mc-bridge-card-actions">
<a href="<?php echo esc_url( $forum_url ); ?>" class="mc-bridge-action-btn">
<i class="fas fa-link"></i> Konto verknüpfen
</a>
</div>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<script>
(function($){
$(document).on('click', '.mc-bridge-verify-trigger', function(){
console.log('[MC-Gallery] Forum-Login Button geklickt!');
if (typeof $ === 'undefined') { alert('jQuery nicht geladen!'); return; }
var $btn = $(this).prop('disabled', true);
var ajax = $btn.data('ajax');
var nonce = $btn.data('nonce');
var server = $btn.data('server') || $btn.closest('[data-server]').data('server') || '';
$btn.html('<i class="fas fa-spinner fa-spin"></i> Prüfe…');
$.post(ajax, {
action: 'mc_forum_verify_upload',
nonce: nonce,
server_id: server
})
.done(function(r){
if ( r.success ) {
// Galerie-JS über erfolgreiche Verify informieren
// Standard-Event — Gallery-JS kann darauf lauschen
$(document).trigger('mc_gallery_forum_verified', [ r.data ]);
// Falls Gallery eigenes globales Callback hat
if ( typeof window.mcGalleryOnVerified === 'function' ) {
window.mcGalleryOnVerified( r.data );
}
// Statusanzeige aktualisieren
$btn.closest('.mc-bridge-verify-wrap')
.html('<div class="mc-bridge-success">'
+ '<i class="fas fa-check-circle"></i> Verifiziert als <strong>'
+ $('<span>').text(r.data.mc_username).html()
+ '</strong></div>');
} else {
var msg = (r.data && r.data.message) ? r.data.message : 'Fehler bei der Verifikation.';
$btn.closest('.mc-bridge-verify-wrap').find('.mc-bridge-error').remove();
$btn.closest('.mc-bridge-forum-linked, .mc-bridge-not-linked')
.after('<p class="mc-bridge-error"><i class="fas fa-times-circle"></i> ' + msg + '</p>');
$btn.prop('disabled', false).html('<i class="fas fa-sign-in-alt"></i> Mit Forum-Login verifizieren');
}
})
.fail(function(){
$btn.prop('disabled', false).html('<i class="fas fa-sign-in-alt"></i> Mit Forum-Login verifizieren');
alert('Netzwerkfehler. Bitte erneut versuchen.');
});
});
})(jQuery);
</script>
<?php
return ob_get_clean();
}
// ── Admin: Spalte in Forum-Benutzertabelle ────────────────────────────────
/**
* Zeigt verknüpfte MC-Accounts in der Forum-Admin-Usertabelle.
* Voraussetzung: Forum rendert `do_action('wbf_admin_user_row_extra', $user)`.
*/
public static function render_admin_user_col( $user ) {
$mc_user = self::get_mc_username( $user->id );
if ( ! $mc_user ) return;
$verified = self::is_verified( $user->id );
$nonce = wp_create_nonce( self::NONCE_ACTION );
?>
<span class="mc-bridge-admin-mc-badge"
title="Verknüpfter Minecraft-Account<?php echo $verified ? ' (verifiziert)' : ' (ausstehend)'; ?>">
<img src="https://mc-heads.net/avatar/<?php echo esc_attr( $mc_user ); ?>/20" alt="">
<?php echo esc_html( $mc_user ); ?>
<?php if ( $verified ) : ?>
<i class="fas fa-check" style="color:#22c55e"></i>
<?php else : ?>
<a href="#"
class="mc-bridge-btn--approve"
style="color:#f59e0b;margin-left:4px"
data-uid="<?php echo (int) $user->id; ?>"
data-nonce="<?php echo esc_attr( $nonce ); ?>"
title="Verknüpfung bestätigen">
<i class="fas fa-check-circle"></i>
</a>
<script>
(function($){
$(document).on('click', '.mc-bridge-btn--approve[data-uid]', function(e){
e.preventDefault();
var $a = $(this);
var uid = $a.data('uid');
var nonce = $a.data('nonce');
$.post(<?php echo json_encode( admin_url('admin-ajax.php') ); ?>, {
action: 'mc_forum_admin_approve',
user_id: uid,
nonce: nonce
}).done(function(r){
if ( r.success ) location.reload();
else alert(r.data || 'Fehler.');
});
});
})(jQuery);
</script>
<?php endif; ?>
</span>
<?php
}
// ── Hilfsmethoden: forum_user_meta Zugriff ────────────────────────────────
private static function get_meta( $user_id, $key ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare(
"SELECT meta_value FROM {$wpdb->prefix}forum_user_meta
WHERE user_id = %d AND meta_key = %s
LIMIT 1",
(int) $user_id, $key
) );
}
private static function set_meta( $user_id, $key, $value ) {
global $wpdb;
$table = $wpdb->prefix . 'forum_user_meta';
$exists = $wpdb->get_var( $wpdb->prepare(
"SELECT id FROM {$table} WHERE user_id = %d AND meta_key = %s",
(int) $user_id, $key
) );
if ( $exists ) {
$wpdb->update( $table,
[ 'meta_value' => $value ],
[ 'user_id' => (int) $user_id, 'meta_key' => $key ]
);
} else {
$wpdb->insert( $table, [
'user_id' => (int) $user_id,
'meta_key' => $key,
'meta_value' => $value,
] );
}
}
private static function delete_meta( $user_id, $key ) {
global $wpdb;
$wpdb->delete( $wpdb->prefix . 'forum_user_meta',
[ 'user_id' => (int) $user_id, 'meta_key' => $key ]
);
}
// Öffentliche Getter/Setter
public static function get_mc_username( $user_id ) { return self::get_meta( $user_id, self::META_MC_USER ); }
public static function get_mc_server ( $user_id ) { return self::get_meta( $user_id, self::META_MC_SERVER ); }
public static function is_verified ( $user_id ) { return '1' === self::get_meta( $user_id, self::META_VERIFIED ); }
public static function set_mc_username( $user_id, $val ) { self::set_meta( $user_id, self::META_MC_USER, $val ); }
public static function set_mc_server ( $user_id, $val ) { self::set_meta( $user_id, self::META_MC_SERVER, $val ); }
public static function set_verified ( $user_id, $bool ) { self::set_meta( $user_id, self::META_VERIFIED, $bool ? '1' : '0' ); }
public static function delete_mc_link( $user_id ) {
self::delete_meta( $user_id, self::META_MC_USER );
self::delete_meta( $user_id, self::META_MC_SERVER );
self::delete_meta( $user_id, self::META_VERIFIED );
}
// Prüft ob ein MC-Name schon einem anderen Forum-User gehört
private static function mc_user_taken( $mc_user, $exclude_user_id ) {
global $wpdb;
return (bool) $wpdb->get_var( $wpdb->prepare(
"SELECT m.id FROM {$wpdb->prefix}forum_user_meta m
WHERE m.meta_key = %s
AND m.meta_value = %s
AND m.user_id != %d
LIMIT 1",
self::META_MC_USER, $mc_user, (int) $exclude_user_id
) );
}
// Gibt true zurück wenn gerade ein gültiger Ingame-Token für diesen MC-Namen existiert
private static function check_active_token_for( $mc_username ) {
if ( ! class_exists( 'MC_Gallery_Helpers' ) ) return false;
$tokens = MC_Gallery_Helpers::get_tokens();
$now = time();
foreach ( $tokens as $token => $data ) {
if ( ! is_array( $data ) ) continue;
if ( ( $data['expires'] ?? 0 ) < $now ) continue;
if ( strtolower( $data['player'] ?? '' ) === strtolower( $mc_username ) ) {
return true;
}
}
return false;
}
// Server-Liste aus Gallery-Config laden
private static function get_server_list() {
$servers = get_option( 'mc_gallery_servers', [] );
if ( ! empty( $servers ) && is_array( $servers ) ) return $servers;
return [ 'default' => 'Standard-Server' ];
}
}