Update from Git Manager GUI
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
<?php
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
class MC_Gallery_Core {
|
||||
|
||||
const OPTION_FORUM_LOGIN = 'mc_gallery_forum_login';
|
||||
const OPTION_VOTING = 'mc_gallery_voting_enabled';
|
||||
private static $forum_plugin_active = false;
|
||||
|
||||
const OPTION_THUMB_H = 'mc_gallery_thumb_h';
|
||||
const OPTION_RESIZE_PCT = 'mc_gallery_resize_pct';
|
||||
const OPTION_SHOW_DATE = 'mc_gallery_show_date';
|
||||
@@ -10,6 +15,8 @@ class MC_Gallery_Core {
|
||||
const SESSION_TTL = 3600; // 1 Stunde Session
|
||||
|
||||
public static function init() {
|
||||
// Prüfen, ob das Forum-Plugin aktiv ist
|
||||
self::$forum_plugin_active = class_exists('WBF_Auth');
|
||||
add_action('init', [__CLASS__, 'register_post_types']);
|
||||
add_action('rest_api_init', [__CLASS__, 'register_rest_routes']);
|
||||
|
||||
@@ -22,6 +29,9 @@ class MC_Gallery_Core {
|
||||
add_action('wp_ajax_mc_gallery_create_album', [__CLASS__, 'handle_create_album']);
|
||||
add_action('wp_ajax_nopriv_mc_gallery_create_album', [__CLASS__, 'handle_create_album']);
|
||||
|
||||
add_action('wp_ajax_mc_gallery_vote', [__CLASS__, 'handle_vote']);
|
||||
add_action('wp_ajax_nopriv_mc_gallery_vote', [__CLASS__, 'handle_vote']);
|
||||
|
||||
add_action('wp_enqueue_scripts', [__CLASS__, 'enqueue_assets']);
|
||||
|
||||
// Meta Boxen & UI
|
||||
@@ -202,7 +212,7 @@ class MC_Gallery_Core {
|
||||
register_setting('mc_gallery_pro_group', self::OPTION_RESIZE_PCT, ['type' => 'integer', 'sanitize_callback' => 'absint', 'default' => 100]);
|
||||
register_setting('mc_gallery_pro_group', self::OPTION_SHOW_DATE, [
|
||||
'type' => 'boolean',
|
||||
'sanitize_callback' => function($input) { return $input === '1'; },
|
||||
'sanitize_callback' => function($input) { return $input == '1' || $input === true || $input === 'on'; },
|
||||
'default' => true
|
||||
]);
|
||||
register_setting('mc_gallery_pro_group', self::OPTION_MAX_UPLOADS, [
|
||||
@@ -210,6 +220,16 @@ class MC_Gallery_Core {
|
||||
'sanitize_callback' => 'absint',
|
||||
'default' => 5
|
||||
]);
|
||||
register_setting('mc_gallery_pro_group', self::OPTION_FORUM_LOGIN, [
|
||||
'type' => 'boolean',
|
||||
'sanitize_callback' => function($input) { return !empty($input) && $input !== '0'; },
|
||||
'default' => false
|
||||
]);
|
||||
register_setting('mc_gallery_pro_group', self::OPTION_VOTING, [
|
||||
'type' => 'boolean',
|
||||
'sanitize_callback' => function($input) { return !empty($input) && $input !== '0'; },
|
||||
'default' => true
|
||||
]);
|
||||
}
|
||||
|
||||
public static function settings_page() {
|
||||
@@ -217,6 +237,22 @@ class MC_Gallery_Core {
|
||||
$resize_pct = get_option(self::OPTION_RESIZE_PCT, 100);
|
||||
$show_date = get_option(self::OPTION_SHOW_DATE, true);
|
||||
$max_uploads = get_option(self::OPTION_MAX_UPLOADS, 5);
|
||||
$forum_login = get_option(self::OPTION_FORUM_LOGIN, false);
|
||||
$forum_plugin_active = class_exists('WBF_Auth');
|
||||
|
||||
// Prüfen ob das Forum-Plugin zwar existiert (Datei vorhanden) aber nicht aktiv ist
|
||||
$forum_plugin_installed = false;
|
||||
if ( ! $forum_plugin_active ) {
|
||||
$all_plugins = get_plugins();
|
||||
foreach ( $all_plugins as $plugin_file => $plugin_data ) {
|
||||
if ( stripos( $plugin_data['Name'], 'WP Business Forum' ) !== false
|
||||
|| stripos( $plugin_data['TextDomain'], 'wp-business-forum' ) !== false
|
||||
|| stripos( $plugin_file, 'wp-business-forum' ) !== false ) {
|
||||
$forum_plugin_installed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>MC Gallery PRO Settings</h1>
|
||||
@@ -250,8 +286,84 @@ class MC_Gallery_Core {
|
||||
<p class="description">How many images can a user upload at once? (Default: 5)</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
Forum-Login für Upload-Verifizierung
|
||||
<br><span style="font-weight:400;color:#646970;font-size:12px;">Benötigt: WP Business Forum</span>
|
||||
</th>
|
||||
<td>
|
||||
<?php if ( $forum_plugin_active ) : ?>
|
||||
|
||||
<?php /* ── Plugin aktiv & bereit ── */ ?>
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px;">
|
||||
<span style="display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:20px;background:#edfaef;border:1px solid #c3e6cb;color:#1a7431;font-size:12px;font-weight:600;">
|
||||
<span style="width:7px;height:7px;border-radius:50%;background:#22c55e;display:inline-block;"></span>
|
||||
WP Business Forum aktiv
|
||||
</span>
|
||||
</div>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr(self::OPTION_FORUM_LOGIN); ?>" value="1" <?php checked($forum_login, '1'); ?> />
|
||||
Forum-Login für Upload-Verifizierung erlauben
|
||||
</label>
|
||||
<p class="description" style="margin-top:6px;">
|
||||
Wenn aktiviert, können sich Nutzer die ihren Minecraft-Account im Forum-Profil verknüpft haben, direkt ohne Ingame-Token hochladen.<br>
|
||||
<strong>Der Shortcode:</strong> <code>[mc_gallery_combined]</code> <strong>ermöglicht eine kombinierte Verifizierung für Token und Forum.</strong>
|
||||
</p>
|
||||
|
||||
<?php elseif ( $forum_plugin_installed ) : ?>
|
||||
|
||||
<?php /* ── Plugin installiert aber nicht aktiviert ── */ ?>
|
||||
<div style="padding:12px 14px;background:#fff8e6;border:1px solid #f0c040;border-left:4px solid #f0c040;border-radius:0 6px 6px 0;margin-bottom:12px;">
|
||||
<strong style="color:#7a5400;">⚠ WP Business Forum ist installiert, aber nicht aktiviert.</strong><br>
|
||||
<span style="color:#7a5400;font-size:13px;">Aktiviere das Plugin unter <a href="<?php echo esc_url(admin_url('plugins.php')); ?>" style="color:#7a5400;text-decoration:underline;">Plugins → Installierte Plugins</a>, um diese Funktion zu nutzen.</span>
|
||||
</div>
|
||||
<label style="opacity:.5;pointer-events:none;">
|
||||
<input type="checkbox" disabled />
|
||||
Forum-Login für Upload-Verifizierung erlauben
|
||||
</label>
|
||||
|
||||
<?php else : ?>
|
||||
|
||||
<?php /* ── Plugin nicht vorhanden ── */ ?>
|
||||
<div style="padding:12px 14px;background:#fef2f2;border:1px solid #fca5a5;border-left:4px solid #ef4444;border-radius:0 6px 6px 0;margin-bottom:12px;">
|
||||
<strong style="color:#991b1b;">✗ WP Business Forum ist nicht installiert.</strong><br>
|
||||
<span style="color:#991b1b;font-size:13px;">
|
||||
Dieses Feature benötigt das Plugin <em>WP Business Forum</em> von M_Viper.<br>
|
||||
<a href="https://git.viper.ipv64.net/M_Viper/WP-Business-Forum/releases" target="_blank" rel="noopener" style="color:#b91c1c;font-weight:600;text-decoration:underline;">
|
||||
↓ Jetzt herunterladen (Gitea)
|
||||
</a>
|
||||
·
|
||||
<a href="<?php echo esc_url(admin_url('plugin-install.php')); ?>" style="color:#b91c1c;text-decoration:underline;">
|
||||
Plugins → Neu hinzufügen
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<label style="opacity:.5;pointer-events:none;">
|
||||
<input type="checkbox" disabled />
|
||||
Forum-Login für Upload-Verifizierung erlauben
|
||||
</label>
|
||||
<p class="description" style="margin-top:6px;color:#888;">
|
||||
Nach der Installation und Aktivierung von WP Business Forum wird diese Option freigeschaltet.
|
||||
</p>
|
||||
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Abstimmung (Daumen hoch/runter)</th>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" name="<?php echo esc_attr(self::OPTION_VOTING); ?>" value="1" <?php checked(get_option(self::OPTION_VOTING, true), true); ?> />
|
||||
Abstimmung auf Bilder aktivieren
|
||||
</label>
|
||||
<p class="description" style="margin-top:6px;">
|
||||
Besucher können Bilder mit 👍 oder 👎 bewerten. Jeder kann abstimmen (kein Login nötig).<br>
|
||||
Shortcode für die Bestenliste: <code>[mc_gallery_vote]</code>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button(); ?>
|
||||
<?php submit_button('Änderungen speichern'); ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
@@ -268,16 +380,43 @@ class MC_Gallery_Core {
|
||||
}
|
||||
|
||||
public static function enqueue_assets() {
|
||||
$js_version = time(); // Zeitstempel für Cache-Busting
|
||||
wp_register_style('mc-gallery-pro-css', MCGALLERY_PRO_URL . 'assets/css/gallery-pro.css', [], MCGALLERY_PRO_VERSION);
|
||||
wp_register_script('mc-gallery-pro-js', MCGALLERY_PRO_URL . 'assets/js/gallery-pro.js', ['jquery'], MCGALLERY_PRO_VERSION, true);
|
||||
wp_register_script('mc-gallery-pro-js', MCGALLERY_PRO_URL . 'assets/js/gallery-pro.js?v=' . $js_version, ['jquery'], null, true);
|
||||
wp_enqueue_style('mc-gallery-pro-css');
|
||||
wp_enqueue_script('mc-gallery-pro-js');
|
||||
// Forum-Verified-Status für JS ermitteln
|
||||
$forum_verified_data = false;
|
||||
if ( class_exists('WBF_Auth') && class_exists('MC_Gallery_Forum_Bridge') ) {
|
||||
$forum_user = WBF_Auth::get_current_user();
|
||||
if ( $forum_user ) {
|
||||
$mc_user = MC_Gallery_Forum_Bridge::get_mc_username( $forum_user->id );
|
||||
$verified = MC_Gallery_Forum_Bridge::is_verified( $forum_user->id );
|
||||
if ( $mc_user && $verified ) {
|
||||
$forum_verified_data = [
|
||||
'mc_username' => $mc_user,
|
||||
'server_id' => MC_Gallery_Forum_Bridge::get_mc_server( $forum_user->id ),
|
||||
'display_name' => $forum_user->display_name,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wp_localize_script('mc-gallery-pro-js', 'mcGalleryPro', [
|
||||
'restBase' => esc_url_raw(rest_url('mc-gallery/v1')),
|
||||
'uploadUrl' => esc_url_raw(admin_url('admin-ajax.php')),
|
||||
'nonce' => wp_create_nonce('mc_gallery_upload_action'),
|
||||
'maxUploads' => intval(get_option(self::OPTION_MAX_UPLOADS, 5))
|
||||
'forumNonce' => wp_create_nonce('mc_gallery_forum_bridge'),
|
||||
'maxUploads' => intval(get_option(self::OPTION_MAX_UPLOADS, 5)),
|
||||
'forumVerified' => $forum_verified_data,
|
||||
'votingEnabled' => get_option(self::OPTION_VOTING, true) ? true : false,
|
||||
]);
|
||||
|
||||
// Forum-Bridge-JS nur laden, wenn Option aktiv und Forum-Plugin vorhanden
|
||||
$forum_login = get_option(self::OPTION_FORUM_LOGIN, false);
|
||||
if ($forum_login && class_exists('WBF_Auth')) {
|
||||
wp_enqueue_script('mc-gallery-forum-bridge', MCGALLERY_PRO_URL . 'assets/js/forum-bridge.js?v=' . $js_version, ['jquery'], null, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static function register_rest_routes() {
|
||||
@@ -438,18 +577,40 @@ class MC_Gallery_Core {
|
||||
$params = $req->get_json_params();
|
||||
$token = sanitize_text_field($params['token'] ?? '');
|
||||
$username = sanitize_text_field($params['username'] ?? '');
|
||||
$server_id = intval($params['server_id'] ?? 0);
|
||||
$server_id = sanitize_text_field($params['server_id'] ?? '');
|
||||
|
||||
if (!$token || !$username || !$server_id) {
|
||||
return new WP_REST_Response(['success'=>false,'message'=>'Missing data'],400);
|
||||
if (!$username) {
|
||||
return new WP_REST_Response(['success'=>false,'message'=>'Missing username'],400);
|
||||
}
|
||||
|
||||
// ── Autorisierung: Token-Session ODER Forum-Login ─────────────────────
|
||||
$authorized = false;
|
||||
|
||||
if ($token) {
|
||||
$tokens = MC_Gallery_Helpers::get_tokens();
|
||||
if (!isset($tokens[$token]) || !$tokens[$token]['claimed'] || $tokens[$token]['claimed_by'] !== $username) {
|
||||
if (isset($tokens[$token]) && $tokens[$token]['claimed'] && $tokens[$token]['claimed_by'] === $username) {
|
||||
if (!$server_id) $server_id = $tokens[$token]['server_id'] ?? '';
|
||||
$authorized = true;
|
||||
}
|
||||
} elseif (class_exists('WBF_Auth') && class_exists('MC_Gallery_Forum_Bridge')) {
|
||||
$forum_user = WBF_Auth::get_current_user();
|
||||
if ($forum_user) {
|
||||
$linked = MC_Gallery_Forum_Bridge::get_mc_username($forum_user->id);
|
||||
if ($linked && MC_Gallery_Forum_Bridge::is_verified($forum_user->id)
|
||||
&& strtolower($linked) === strtolower($username)) {
|
||||
if (!$server_id) $server_id = MC_Gallery_Forum_Bridge::get_mc_server($forum_user->id);
|
||||
$authorized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$authorized) {
|
||||
return new WP_REST_Response(['success'=>false,'message'=>'Invalid session'],401);
|
||||
}
|
||||
|
||||
$gallery = MC_Gallery_Helpers::find_or_create_gallery_post($username, $server_id);
|
||||
$server_id_val = is_numeric($server_id) ? intval($server_id) : $server_id;
|
||||
|
||||
$gallery = MC_Gallery_Helpers::find_or_create_gallery_post($username, $server_id_val);
|
||||
if (!$gallery) {
|
||||
return MC_Gallery_Helpers::rest_response_success(['albums' => []]);
|
||||
}
|
||||
@@ -495,6 +656,43 @@ class MC_Gallery_Core {
|
||||
wp_send_json_success(['views' => $count]);
|
||||
}
|
||||
|
||||
// NEU: Vote/Like Handler
|
||||
public static function handle_vote() {
|
||||
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'mc_gallery_upload_action')) {
|
||||
wp_send_json_error(['message' => 'Security check failed.']);
|
||||
}
|
||||
|
||||
if (!isset($_POST['attach_id']) || !is_numeric($_POST['attach_id'])) {
|
||||
wp_send_json_error(['message' => 'Invalid ID.']);
|
||||
}
|
||||
|
||||
// Voting deaktiviert?
|
||||
if (!get_option(self::OPTION_VOTING, true)) {
|
||||
wp_send_json_error(['message' => 'Voting ist deaktiviert.']);
|
||||
}
|
||||
|
||||
$attach_id = intval($_POST['attach_id']);
|
||||
$vote_type = sanitize_text_field($_POST['vote_type'] ?? 'up'); // 'up' oder 'down'
|
||||
$vote_action = sanitize_text_field($_POST['vote_action'] ?? 'add'); // 'add' oder 'remove'
|
||||
|
||||
$post = get_post($attach_id);
|
||||
if (!$post || $post->post_type !== 'attachment' || strpos($post->post_mime_type, 'image/') !== 0) {
|
||||
wp_send_json_error(['message' => 'Not a valid image.']);
|
||||
}
|
||||
|
||||
$meta_key = ($vote_type === 'down') ? 'mc_votes_down' : 'mc_votes_up';
|
||||
$count = (int) get_post_meta($attach_id, $meta_key, true);
|
||||
$count = ($vote_action === 'remove') ? max(0, $count - 1) : $count + 1;
|
||||
update_post_meta($attach_id, $meta_key, $count);
|
||||
|
||||
wp_send_json_success([
|
||||
'votes_up' => (int) get_post_meta($attach_id, 'mc_votes_up', true),
|
||||
'votes_down' => (int) get_post_meta($attach_id, 'mc_votes_down', true),
|
||||
'vote_type' => $vote_type,
|
||||
'vote_action'=> $vote_action,
|
||||
]);
|
||||
}
|
||||
|
||||
public static function handle_create_album() {
|
||||
if (!isset($_POST['mc_upload_nonce']) || !wp_verify_nonce($_POST['mc_upload_nonce'], 'mc_gallery_upload_action')) {
|
||||
wp_send_json_error(['message' => 'Security check failed.']);
|
||||
@@ -502,23 +700,43 @@ class MC_Gallery_Core {
|
||||
|
||||
$token = sanitize_text_field($_POST['mc_token'] ?? '');
|
||||
$username = sanitize_text_field($_POST['mc_username'] ?? '');
|
||||
$server_id = intval($_POST['mc_server_id'] ?? 0);
|
||||
$server_id = sanitize_text_field($_POST['mc_server_id'] ?? '');
|
||||
$album_name = sanitize_text_field($_POST['album_name'] ?? '');
|
||||
|
||||
if (!$token || !$username || !$server_id || !$album_name) {
|
||||
if (!$username || !$album_name) {
|
||||
wp_send_json_error(['message' => 'Missing data']);
|
||||
}
|
||||
|
||||
// ── Autorisierung: Token-Session ODER Forum-Login ─────────────────────
|
||||
$authorized = false;
|
||||
|
||||
if ($token) {
|
||||
$tokens = MC_Gallery_Helpers::get_tokens();
|
||||
if (!isset($tokens[$token]) || !$tokens[$token]['claimed'] || $tokens[$token]['claimed_by'] !== $username) {
|
||||
wp_send_json_error(['message' => 'Invalid session']);
|
||||
if (isset($tokens[$token]) && $tokens[$token]['claimed'] && $tokens[$token]['claimed_by'] === $username && $tokens[$token]['expires'] >= time()) {
|
||||
if (!$server_id) $server_id = $tokens[$token]['server_id'] ?? '';
|
||||
$authorized = true;
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Invalid or expired session']);
|
||||
}
|
||||
} elseif (class_exists('WBF_Auth') && class_exists('MC_Gallery_Forum_Bridge')) {
|
||||
$forum_user = WBF_Auth::get_current_user();
|
||||
if ($forum_user) {
|
||||
$linked_mc = MC_Gallery_Forum_Bridge::get_mc_username($forum_user->id);
|
||||
$verified = MC_Gallery_Forum_Bridge::is_verified($forum_user->id);
|
||||
if ($linked_mc && $verified && strtolower($linked_mc) === strtolower($username)) {
|
||||
if (!$server_id) $server_id = MC_Gallery_Forum_Bridge::get_mc_server($forum_user->id);
|
||||
$authorized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($tokens[$token]['expires'] < time()) {
|
||||
wp_send_json_error(['message' => 'Session expired']);
|
||||
if (!$authorized) {
|
||||
wp_send_json_error(['message' => 'Nicht autorisiert.']);
|
||||
}
|
||||
|
||||
$gallery = MC_Gallery_Helpers::find_or_create_gallery_post($username, $server_id);
|
||||
$server_id_val = is_numeric($server_id) ? intval($server_id) : $server_id;
|
||||
|
||||
$gallery = MC_Gallery_Helpers::find_or_create_gallery_post($username, $server_id_val);
|
||||
if (!$gallery) {
|
||||
wp_send_json_error(['message' => 'Gallery not found']);
|
||||
}
|
||||
@@ -553,26 +771,59 @@ class MC_Gallery_Core {
|
||||
|
||||
$token = sanitize_text_field($_POST['mc_token'] ?? '');
|
||||
$username = sanitize_text_field($_POST['mc_username'] ?? '');
|
||||
$server_id = intval($_POST['mc_server_id'] ?? 0);
|
||||
$server_id = sanitize_text_field($_POST['mc_server_id'] ?? '');
|
||||
$album_id = intval($_POST['mc_album_id'] ?? 0);
|
||||
|
||||
if (!$token || !$username || !$server_id) {
|
||||
wp_send_json_error(['message' => 'Token or data missing.']);
|
||||
if (!$username) {
|
||||
wp_send_json_error(['message' => 'Benutzername fehlt.']);
|
||||
}
|
||||
|
||||
// ── Autorisierung: Token-Session ODER Forum-Login ─────────────────────
|
||||
$authorized = false;
|
||||
|
||||
if ($token) {
|
||||
// Standard-Weg: Ingame-Token verifizieren
|
||||
$tokens = MC_Gallery_Helpers::get_tokens();
|
||||
if (!isset($tokens[$token])) {
|
||||
wp_send_json_error(['message' => 'Invalid token.']);
|
||||
}
|
||||
|
||||
$t = $tokens[$token];
|
||||
if ($t['expires'] < time()) {
|
||||
wp_send_json_error(['message' => 'Session expired.']);
|
||||
}
|
||||
|
||||
if (!$t['claimed'] || $t['claimed_by'] !== $username) {
|
||||
wp_send_json_error(['message' => 'Verification failed. Please go back to step 2 and use /verify']);
|
||||
}
|
||||
// server_id aus Token übernehmen falls nicht per POST übergeben
|
||||
if (!$server_id) {
|
||||
$server_id = $t['server_id'] ?? '';
|
||||
}
|
||||
$authorized = true;
|
||||
} elseif (class_exists('WBF_Auth') && class_exists('MC_Gallery_Forum_Bridge')) {
|
||||
// Forum-Login-Weg: eingeloggten Forum-User prüfen
|
||||
$forum_user = WBF_Auth::get_current_user();
|
||||
if ($forum_user) {
|
||||
$linked_mc = MC_Gallery_Forum_Bridge::get_mc_username($forum_user->id);
|
||||
$verified = MC_Gallery_Forum_Bridge::is_verified($forum_user->id);
|
||||
if ($linked_mc && $verified && strtolower($linked_mc) === strtolower($username)) {
|
||||
// server_id aus Profil holen falls nicht übergeben
|
||||
if (!$server_id) {
|
||||
$server_id = MC_Gallery_Forum_Bridge::get_mc_server($forum_user->id);
|
||||
}
|
||||
$authorized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$authorized) {
|
||||
wp_send_json_error(['message' => 'Nicht autorisiert. Bitte zuerst verifizieren.']);
|
||||
}
|
||||
|
||||
// server_id als Integer für wp_query (falls numeric), sonst als String belassen
|
||||
$server_id_val = is_numeric($server_id) ? intval($server_id) : $server_id;
|
||||
if (!$server_id_val) {
|
||||
wp_send_json_error(['message' => 'Server-ID fehlt.']);
|
||||
}
|
||||
|
||||
if (empty($_FILES['mc_images']) || !is_array($_FILES['mc_images']['name'])) {
|
||||
wp_send_json_error(['message' => 'No files uploaded.']);
|
||||
@@ -596,7 +847,7 @@ class MC_Gallery_Core {
|
||||
$errors = [];
|
||||
|
||||
try {
|
||||
$gallery_post = MC_Gallery_Helpers::find_or_create_gallery_post($username, $server_id);
|
||||
$gallery_post = MC_Gallery_Helpers::find_or_create_gallery_post($username, $server_id_val);
|
||||
if (!$gallery_post) throw new Exception('Gallery not found.');
|
||||
|
||||
if (empty($_FILES['mc_images']) || !is_array($_FILES['mc_images']['name'])) {
|
||||
|
||||
691
includes/class-mc-gallery-forum-bridge.php
Normal file
691
includes/class-mc-gallery-forum-bridge.php
Normal 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 (2–32 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' ];
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,15 @@ if (!defined('ABSPATH')) exit;
|
||||
|
||||
class MC_Gallery_Shortcodes {
|
||||
|
||||
private static $modal_rendered = false;
|
||||
|
||||
public static function init() {
|
||||
add_shortcode('mc_gallery_overview', [__CLASS__, 'shortcode_overview']);
|
||||
add_shortcode('mc_gallery_player', [__CLASS__, 'shortcode_player']);
|
||||
add_shortcode('mc_gallery_upload', [__CLASS__, 'shortcode_upload']);
|
||||
add_shortcode('mc_gallery_combined', [__CLASS__, 'shortcode_combined']);
|
||||
add_shortcode('mc_gallery_all_albums', [__CLASS__, 'shortcode_all_albums_overview']);
|
||||
add_shortcode('mc_gallery_vote', [__CLASS__, 'shortcode_vote_board']);
|
||||
|
||||
add_shortcode('mc_gallery', [__CLASS__, 'shortcode_overview']);
|
||||
}
|
||||
@@ -112,9 +116,11 @@ class MC_Gallery_Shortcodes {
|
||||
$albums = get_posts([
|
||||
'post_type' => 'mc_album',
|
||||
'posts_per_page' => -1,
|
||||
'meta_key' => 'mc_gallery_id',
|
||||
'meta_query' => [[
|
||||
'key' => 'mc_gallery_id',
|
||||
'value' => $player_gallery_ids,
|
||||
'compare' => 'IN',
|
||||
]],
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
@@ -129,6 +135,7 @@ class MC_Gallery_Shortcodes {
|
||||
foreach ($albums as $album) {
|
||||
$album_images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
'posts_per_page' => 1,
|
||||
'post_mime_type' => 'image',
|
||||
'post_parent' => get_post_meta($album->ID, 'mc_gallery_id', true),
|
||||
@@ -226,6 +233,7 @@ class MC_Gallery_Shortcodes {
|
||||
$out .= '<div class="mc-date-badge">'.$upload_date.'</div>';
|
||||
}
|
||||
$out .= '<img src="'.esc_url($thumb).'" alt="'.esc_attr($q_player).'" loading="lazy" style="aspect-ratio: '.$aspect_ratio.';">';
|
||||
$out .= self::render_like_btn($img->ID);
|
||||
$out .= '<div class="mc-gallery-overlay">';
|
||||
$out .= '<div class="mc-gallery-info">';
|
||||
$out .= '<div class="mc-watermark">'.esc_html($q_player).'</div>';
|
||||
@@ -382,6 +390,7 @@ class MC_Gallery_Shortcodes {
|
||||
$out .= '<div class="mc-date-badge">'.$upload_date.'</div>';
|
||||
}
|
||||
$out .= '<img src="'.esc_url($thumb).'" alt="'.esc_attr($player_name).'" loading="lazy" style="aspect-ratio: '.$aspect_ratio.';">';
|
||||
$out .= self::render_like_btn($img->ID);
|
||||
$out .= '<div class="mc-gallery-overlay">';
|
||||
$out .= '<div class="mc-gallery-info">';
|
||||
$out .= '<div class="mc-watermark">'.$player_name.'</div>';
|
||||
@@ -539,6 +548,7 @@ class MC_Gallery_Shortcodes {
|
||||
$out .= '<div class="mc-date-badge">'.$upload_date.'</div>';
|
||||
}
|
||||
$out .= '<img src="'.esc_url($thumb).'" alt="'.esc_attr($player).'" loading="lazy" style="aspect-ratio: '.$aspect_ratio.';">';
|
||||
$out .= self::render_like_btn($img->ID);
|
||||
$out .= '<div class="mc-gallery-overlay">';
|
||||
$out .= '<div class="mc-gallery-info">';
|
||||
$out .= '<div class="mc-watermark">'.esc_html($player).'</div>';
|
||||
@@ -561,6 +571,12 @@ class MC_Gallery_Shortcodes {
|
||||
$show_date = get_option(MC_Gallery_Core::OPTION_SHOW_DATE, true);
|
||||
$current_url = remove_query_arg(['player', 'server', 'album']);
|
||||
|
||||
// Album-Ansicht: wenn ?album=ID in der URL steht, direkt anzeigen
|
||||
$q_album = isset($_GET['album']) ? intval($_GET['album']) : 0;
|
||||
if ($q_album) {
|
||||
return self::shortcode_album_view(['album_id' => $q_album]);
|
||||
}
|
||||
|
||||
$albums = get_posts([
|
||||
'post_type' => 'mc_album',
|
||||
'posts_per_page' => -1,
|
||||
@@ -587,6 +603,7 @@ class MC_Gallery_Shortcodes {
|
||||
|
||||
$cover_images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
'posts_per_page' => 1,
|
||||
'post_mime_type' => 'image',
|
||||
'meta_key' => 'mc_album_id',
|
||||
@@ -646,6 +663,7 @@ class MC_Gallery_Shortcodes {
|
||||
|
||||
$images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
'posts_per_page' => -1,
|
||||
'post_mime_type' => 'image',
|
||||
'meta_key' => 'mc_album_id',
|
||||
@@ -700,6 +718,7 @@ class MC_Gallery_Shortcodes {
|
||||
$out .= '<div class="mc-date-badge">'.$upload_date.'</div>';
|
||||
}
|
||||
$out .= '<img src="'.esc_url($thumb).'" alt="" loading="lazy" style="aspect-ratio: '.$aspect_ratio.';">';
|
||||
$out .= self::render_like_btn($img->ID);
|
||||
$out .= '</div>';
|
||||
$out .= '</a>';
|
||||
}
|
||||
@@ -716,9 +735,12 @@ class MC_Gallery_Shortcodes {
|
||||
public static function shortcode_upload($atts) {
|
||||
$atts = shortcode_atts(['show' => '0'], $atts);
|
||||
$show_default = ($atts['show'] === '1');
|
||||
|
||||
// Option als String vergleichen, damit auch '1' als String erkannt wird
|
||||
$forum_login_enabled = get_option(MC_Gallery_Core::OPTION_FORUM_LOGIN, false) == '1';
|
||||
$forum_plugin = class_exists('WBF_Auth');
|
||||
ob_start();
|
||||
?>
|
||||
<!-- DEBUG: Forum-Login Option: <?php echo $forum_login_enabled ? 'aktiv' : 'inaktiv'; ?>, Forum-Plugin: <?php echo $forum_plugin ? 'geladen' : 'NICHT geladen'; ?> -->
|
||||
<div class="mc-upload-wrapper">
|
||||
<button id="mc-open-upload-modal" class="mc-btn mc-btn-primary">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -728,6 +750,7 @@ class MC_Gallery_Shortcodes {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php if (!self::$modal_rendered): self::$modal_rendered = true; ?>
|
||||
<div id="mc-upload-modal" class="mc-modal" aria-hidden="true" role="dialog">
|
||||
<div class="mc-modal-backdrop"></div>
|
||||
<div class="mc-modal-content">
|
||||
@@ -757,6 +780,18 @@ class MC_Gallery_Shortcodes {
|
||||
</svg>
|
||||
Session starten
|
||||
</button>
|
||||
<?php if ($forum_login_enabled && $forum_plugin): ?>
|
||||
<div style="margin-top:16px; text-align:center;">
|
||||
<button id="mc-btn-forum-login" class="mc-btn mc-btn-secondary mc-full-width" type="button">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<circle cx="12" cy="12" r="10" stroke-width="2"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 14a4 4 0 100-8 4 4 0 000 8zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
||||
</svg>
|
||||
Mit Forum-Login verifizieren
|
||||
</button>
|
||||
<p class="mc-small" style="margin-top:8px;">Optional: Wenn du im Forum eingeloggt bist und dein Minecraft-Account verknüpft ist, kannst du dich direkt verifizieren.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -866,6 +901,7 @@ class MC_Gallery_Shortcodes {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; // modal_rendered ?>
|
||||
|
||||
<?php if ($show_default): ?>
|
||||
<script>
|
||||
@@ -889,4 +925,397 @@ class MC_Gallery_Shortcodes {
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// === KOMBINIERTER SHORTCODE: Upload-Button + Forum-Panel ================
|
||||
// =========================================================================
|
||||
// Verwendung: [mc_gallery_combined] oder [mc_gallery_combined show="1"]
|
||||
// Ersetzt [mc_gallery_upload] + [mc_gallery_forum_login] auf einer Seite.
|
||||
|
||||
public static function shortcode_combined($atts) {
|
||||
$atts = shortcode_atts(['show' => '0', 'server_id' => ''], $atts);
|
||||
$show_default = ($atts['show'] === '1');
|
||||
$forum_login_enabled = get_option(MC_Gallery_Core::OPTION_FORUM_LOGIN, false) == '1';
|
||||
$forum_plugin = class_exists('WBF_Auth');
|
||||
$server_id = sanitize_text_field($atts['server_id']);
|
||||
|
||||
// Prüfen ob Forum-User bereits verifiziert ist (für Button-Zustand)
|
||||
$forum_verified = false;
|
||||
$forum_mc_name = '';
|
||||
if ($forum_plugin && class_exists('MC_Gallery_Forum_Bridge')) {
|
||||
$fu = WBF_Auth::get_current_user();
|
||||
if ($fu) {
|
||||
$mc = MC_Gallery_Forum_Bridge::get_mc_username($fu->id);
|
||||
$ver = MC_Gallery_Forum_Bridge::is_verified($fu->id);
|
||||
if ($mc && $ver) {
|
||||
$forum_verified = true;
|
||||
$forum_mc_name = $mc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="mc-combined-wrapper">
|
||||
|
||||
<?php if ($forum_verified): ?>
|
||||
<!-- Bereits verifiziert: Upload-Button + grüner Badge -->
|
||||
<button id="mc-open-upload-modal" class="mc-btn mc-btn-primary mc-combined-upload-btn">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
|
||||
</svg>
|
||||
Bilder hochladen
|
||||
</button>
|
||||
<div class="mc-combined-verified-row">
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
Verifiziert als <strong><?php echo esc_html($forum_mc_name); ?></strong>
|
||||
</div>
|
||||
|
||||
<?php elseif ($forum_login_enabled && $forum_plugin): ?>
|
||||
<!-- Zwei-Wege: Token-Upload + Forum-Login -->
|
||||
|
||||
<!-- Upload-Button (Token-Weg) -->
|
||||
<button id="mc-open-upload-modal" class="mc-btn mc-btn-primary mc-combined-upload-btn">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
|
||||
</svg>
|
||||
Bilder hochladen
|
||||
<span class="mc-combined-method-tag">Ingame-Token</span>
|
||||
</button>
|
||||
|
||||
<div class="mc-combined-divider"><span>oder</span></div>
|
||||
|
||||
<!-- Forum-Card direkt inline (ohne extra Divider aus build_verify_panel) -->
|
||||
<?php
|
||||
if (class_exists('MC_Gallery_Forum_Bridge')) {
|
||||
$fu = WBF_Auth::get_current_user();
|
||||
$nonce = wp_create_nonce('mc_gallery_forum_bridge');
|
||||
$ajax_url = admin_url('admin-ajax.php');
|
||||
|
||||
if (!$fu) :
|
||||
$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' : '#';
|
||||
?>
|
||||
<a href="<?php echo esc_url($forum_url); ?>" class="mc-btn mc-combined-upload-btn mc-combined-forum-btn" style="text-decoration:none;display:flex;align-items:center;justify-content:center;gap:8px;">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"/>
|
||||
</svg>
|
||||
Mit Forum-Login verifizieren
|
||||
<span class="mc-combined-method-tag" style="background:rgba(0,0,0,.2);">Forum</span>
|
||||
</a>
|
||||
<a href="<?php echo esc_url($register_url); ?>" class="mc-btn mc-btn-secondary mc-combined-upload-btn" style="">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z"/>
|
||||
</svg>
|
||||
Noch kein Konto? Jetzt registrieren
|
||||
</a>
|
||||
<?php
|
||||
else:
|
||||
$mc_user = MC_Gallery_Forum_Bridge::get_mc_username($fu->id);
|
||||
$verified = MC_Gallery_Forum_Bridge::is_verified($fu->id);
|
||||
$prof_url = function_exists('wbf_get_forum_url') ? wbf_get_forum_url() . '?forum_profile=' . (int)$fu->id . '#tab-minecraft' : '#';
|
||||
|
||||
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):
|
||||
?>
|
||||
<button type="button" class="mc-bridge-verify-trigger mc-btn mc-combined-upload-btn"
|
||||
style="width:100%;justify-content:center;gap:8px;background:#f59e0b;border:none;color:#1c1008;padding:12px 20px;font-size:15px;font-weight:600;cursor:pointer;"
|
||||
data-ajax="<?php echo esc_attr($ajax_url); ?>"
|
||||
data-nonce="<?php echo esc_attr($nonce); ?>"
|
||||
data-server="<?php echo esc_attr($server_id); ?>">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
Mit Forum verifizieren – <?php echo esc_html($mc_user); ?>
|
||||
<span class="mc-combined-method-tag" style="background:rgba(0,0,0,.2);">Ausstehend</span>
|
||||
</button>
|
||||
<?php
|
||||
else:
|
||||
?>
|
||||
<a href="<?php echo esc_url($prof_url); ?>" class="mc-btn mc-combined-upload-btn mc-combined-forum-btn" style="text-decoration:none;display:flex;align-items:center;justify-content:center;gap:8px;">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>
|
||||
</svg>
|
||||
Minecraft-Konto verknüpfen
|
||||
<span class="mc-combined-method-tag">Forum-Profil</span>
|
||||
</a>
|
||||
<?php
|
||||
endif;
|
||||
endif; // $fu
|
||||
} // class_exists
|
||||
?>
|
||||
|
||||
<?php else: ?>
|
||||
<!-- Nur Upload-Button -->
|
||||
<button id="mc-open-upload-modal" class="mc-btn mc-btn-primary mc-combined-upload-btn">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
|
||||
</svg>
|
||||
Bilder hochladen
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Modal HTML — nur einmal pro Seite ausgeben
|
||||
$forum_login_for_modal = $forum_login_enabled && $forum_plugin;
|
||||
if (!self::$modal_rendered): self::$modal_rendered = true;
|
||||
?>
|
||||
<div id="mc-upload-modal" class="mc-modal" aria-hidden="true" role="dialog">
|
||||
<div class="mc-modal-backdrop"></div>
|
||||
<div class="mc-modal-content">
|
||||
<button class="mc-modal-close" aria-label="Schließen">×</button>
|
||||
<div class="mc-upload-wizard">
|
||||
<div class="mc-step active" data-step="1">
|
||||
<div class="mc-step-header"><span class="mc-step-num">1</span><h3>Identifikation</h3></div>
|
||||
<div class="mc-step-body">
|
||||
<label for="mc-upload-username">Dein Minecraft Name</label>
|
||||
<input type="text" id="mc-upload-username" placeholder="z.B. Steve" autocomplete="off">
|
||||
<label for="mc-upload-server">Server wählen</label>
|
||||
<select id="mc-upload-server"><option>Lade Server...</option></select>
|
||||
<button id="mc-btn-generate" class="mc-btn mc-btn-primary mc-full-width">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>
|
||||
</svg>
|
||||
Session starten
|
||||
</button>
|
||||
<?php if ($forum_login_for_modal): ?>
|
||||
<div style="margin-top:16px; text-align:center;">
|
||||
<button id="mc-btn-forum-login" class="mc-btn mc-btn-secondary mc-full-width" type="button">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<circle cx="12" cy="12" r="10" stroke-width="2"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 14a4 4 0 100-8 4 4 0 000 8zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
||||
</svg>
|
||||
Mit Forum-Login verifizieren
|
||||
</button>
|
||||
<p class="mc-small" style="margin-top:8px;">Optional: Wenn du im Forum eingeloggt bist und dein Minecraft-Account verknüpft ist, kannst du dich direkt verifizieren.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mc-step" data-step="2">
|
||||
<div class="mc-step-header"><span class="mc-step-num">2</span><h3>Verifizierung</h3></div>
|
||||
<div class="mc-step-body">
|
||||
<div class="mc-info-box">🎮 Gehe auf den Server und führe den folgenden Befehl aus:</div>
|
||||
<div class="mc-token-box">
|
||||
<code id="mc-token-text">Waiting...</code>
|
||||
<button class="mc-copy-btn" title="Kopieren">📋</button>
|
||||
</div>
|
||||
<p class="mc-small">💡 Gib im Chat ein: <strong>/verify [dein-token]</strong></p>
|
||||
<button id="mc-btn-check" class="mc-btn mc-btn-primary mc-full-width">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
Verifizierung prüfen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mc-step" data-step="3">
|
||||
<div class="mc-step-header"><span class="mc-step-num">3</span><h3>Bilder hochladen</h3></div>
|
||||
<div class="mc-step-body">
|
||||
<div class="mc-session-info">
|
||||
<span class="mc-session-badge">✓ Session aktiv</span>
|
||||
<span id="mc-session-user"></span>
|
||||
</div>
|
||||
<label>Album wählen (optional)</label>
|
||||
<div class="mc-album-selector">
|
||||
<select id="mc-upload-album"><option value="">Kein Album</option></select>
|
||||
<button id="mc-btn-new-album" class="mc-btn mc-btn-ghost mc-btn-small" type="button">
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
||||
</svg>
|
||||
Neues Album
|
||||
</button>
|
||||
</div>
|
||||
<div id="mc-new-album-form" style="display:none;">
|
||||
<label>Album-Name</label>
|
||||
<input type="text" id="mc-new-album-name" placeholder="z.B. Meine Bauten">
|
||||
<button id="mc-btn-create-album" class="mc-btn mc-btn-primary mc-btn-small mc-full-width">Album erstellen</button>
|
||||
</div>
|
||||
<label>Bilder auswählen (mehrere möglich)</label>
|
||||
<div class="mc-file-drop">
|
||||
<input type="file" id="mc-upload-file" accept="image/*" multiple>
|
||||
<svg width="48" height="48" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="margin:0 auto 12px;display:block;color:var(--mc-primary);">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
<span id="mc-file-name">Keine Bilder gewählt</span>
|
||||
</div>
|
||||
<div id="mc-file-preview" class="mc-file-preview"></div>
|
||||
<form id="mc-upload-form" style="display:none;">
|
||||
<?php wp_nonce_field('mc_gallery_upload_action', 'mc_upload_nonce'); ?>
|
||||
<input type="hidden" name="mc_token" id="mc_form_token">
|
||||
<input type="hidden" name="mc_username" id="mc_form_username">
|
||||
<input type="hidden" name="mc_server_id" id="mc_form_server">
|
||||
<input type="hidden" name="mc_album_id" id="mc_form_album">
|
||||
</form>
|
||||
<div id="mc-upload-progress" style="display:none;">
|
||||
<div class="mc-progress-bar"><div class="mc-progress-fill" id="mc-progress-fill"></div></div>
|
||||
<p id="mc-progress-text">Uploading...</p>
|
||||
</div>
|
||||
<button id="mc-btn-final-upload" class="mc-btn mc-btn-success mc-full-width">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
|
||||
</svg>
|
||||
<span id="mc-upload-btn-text">Bilder hochladen</span>
|
||||
</button>
|
||||
<button id="mc-btn-upload-more" class="mc-btn mc-btn-ghost mc-full-width" style="display:none;margin-top:12px;">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
||||
</svg>
|
||||
Weitere Bilder hochladen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mc-feedback-msg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; // modal_rendered ?>
|
||||
|
||||
<?php if ($show_default): ?>
|
||||
<script>(function(){ setTimeout(function(){ var b=document.getElementById('mc-open-upload-modal'); if(b) b.click(); }, 500); })();</script>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// === ABSTIMMUNG / VOTE BOARD =============================================
|
||||
// =========================================================================
|
||||
// Verwendung: [mc_gallery_vote] — Zeigt alle Bilder sortiert nach Likes
|
||||
|
||||
public static function shortcode_vote_board($atts) {
|
||||
$atts = shortcode_atts(['limit' => 50, 'server_ids' => ''], $atts);
|
||||
|
||||
$server_ids = [];
|
||||
if (!empty($atts['server_ids'])) {
|
||||
foreach (explode(',', $atts['server_ids']) as $id) {
|
||||
$int = intval(trim($id));
|
||||
if ($int > 0) $server_ids[] = $int;
|
||||
}
|
||||
}
|
||||
|
||||
// Gallery-Posts ermitteln
|
||||
$gallery_args = ['post_type' => 'mc_gallery', 'posts_per_page' => -1, 'fields' => 'ids', 'post_status' => 'publish'];
|
||||
if (!empty($server_ids)) {
|
||||
$gallery_args['meta_query'] = [['key' => 'mc_server', 'value' => $server_ids, 'compare' => 'IN']];
|
||||
}
|
||||
$gallery_ids = get_posts($gallery_args);
|
||||
|
||||
if (empty($gallery_ids)) {
|
||||
return '<div class="mc-gallery-container"><div class="mc-empty-state">📷 Noch keine Bilder vorhanden.</div></div>';
|
||||
}
|
||||
|
||||
// Alle Bilder laden, nach Likes sortiert
|
||||
$images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
'post_mime_type' => 'image',
|
||||
'post_parent__in'=> $gallery_ids,
|
||||
'posts_per_page' => intval($atts['limit']),
|
||||
'meta_key' => 'mc_votes_up',
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'DESC',
|
||||
]);
|
||||
|
||||
// Auch Bilder ohne Votes holen
|
||||
if (count($images) < intval($atts['limit'])) {
|
||||
$voted_ids = array_map(fn($i) => $i->ID, $images);
|
||||
$rest_args = [
|
||||
'post_type' => 'attachment',
|
||||
'post_status' => 'inherit',
|
||||
'post_mime_type' => 'image',
|
||||
'post_parent__in'=> $gallery_ids,
|
||||
'posts_per_page' => intval($atts['limit']) - count($images),
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
if (!empty($voted_ids)) $rest_args['post__not_in'] = $voted_ids;
|
||||
$images = array_merge($images, get_posts($rest_args));
|
||||
}
|
||||
|
||||
if (empty($images)) {
|
||||
return '<div class="mc-gallery-container"><div class="mc-empty-state">📷 Noch keine Bilder vorhanden.</div></div>';
|
||||
}
|
||||
|
||||
$show_date = get_option(MC_Gallery_Core::OPTION_SHOW_DATE, true);
|
||||
|
||||
$out = '<div class="mc-gallery-container mc-vote-board">';
|
||||
$out .= '<div class="mc-player-header">';
|
||||
$out .= '<div class="mc-player-title"><div class="mc-player-avatar">👍</div><h2>Abstimmung</h2></div>';
|
||||
$out .= '</div>';
|
||||
$out .= '<div class="mc-gallery-grid">';
|
||||
|
||||
foreach ($images as $img) {
|
||||
$full = wp_get_attachment_url($img->ID);
|
||||
$thumb_arr = wp_get_attachment_image_src($img->ID, 'medium');
|
||||
$thumb = $thumb_arr ? $thumb_arr[0] : $full;
|
||||
$views = (int) get_post_meta($img->ID, 'mc_views', true);
|
||||
$upload_date = date_i18n('d.m.Y', strtotime($img->post_date));
|
||||
$gallery_post = get_post($img->post_parent);
|
||||
$player_name = $gallery_post ? get_post_meta($gallery_post->ID, 'mc_player', true) : '';
|
||||
$metadata = wp_get_attachment_metadata($img->ID);
|
||||
$ratio = (($metadata['width'] ?? 0) && ($metadata['height'] ?? 0))
|
||||
? ($metadata['width'] / $metadata['height']) : 1;
|
||||
$data_date = $show_date ? 'data-date="'.esc_attr($upload_date).'"' : '';
|
||||
|
||||
$out .= '<a href="'.esc_url($full).'" class="mc-gallery-item" data-player="'.esc_attr($player_name).'" '.$data_date.' data-attach-id="'.$img->ID.'">';
|
||||
$out .= '<div class="mc-gallery-item-inner">';
|
||||
$out .= '<div class="mc-views-badge">👁️ <span class="mc-views-count">'.$views.'</span></div>';
|
||||
if ($show_date) $out .= '<div class="mc-date-badge">'.$upload_date.'</div>';
|
||||
$out .= '<img src="'.esc_url($thumb).'" alt="'.esc_attr($player_name).'" loading="lazy" style="aspect-ratio:'.$ratio.';">';
|
||||
$out .= self::render_vote_btns($img->ID);
|
||||
$out .= '<div class="mc-gallery-overlay"><div class="mc-gallery-info"><div class="mc-watermark">'.esc_html($player_name).'</div></div></div>';
|
||||
$out .= '</div>';
|
||||
$out .= '</a>';
|
||||
}
|
||||
|
||||
$out .= '</div></div>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
// Hilfsfunktion: Like-Button HTML für normale Galerie-Items
|
||||
public static function render_vote_btns($attach_id) {
|
||||
if (!get_option(MC_Gallery_Core::OPTION_VOTING, true)) return '';
|
||||
$up = (int) get_post_meta($attach_id, 'mc_votes_up', true);
|
||||
$down = (int) get_post_meta($attach_id, 'mc_votes_down', true);
|
||||
$nonce = wp_create_nonce('mc_gallery_upload_action');
|
||||
$id = esc_attr($attach_id);
|
||||
$n = esc_attr($nonce);
|
||||
return
|
||||
'<div class="mc-vote-wrap" data-attach-id="'.$id.'" data-nonce="'.$n.'">'
|
||||
// Daumen hoch
|
||||
.'<button class="mc-vote-btn mc-vote-up" data-type="up" title="Daumen hoch">'
|
||||
.'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5"/></svg>'
|
||||
.'<span class="mc-vote-count mc-vote-up-count">'.$up.'</span>'
|
||||
.'</button>'
|
||||
// Daumen runter
|
||||
.'<button class="mc-vote-btn mc-vote-down" data-type="down" title="Daumen runter">'
|
||||
.'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14H5.236a2 2 0 01-1.789-2.894l3.5-7A2 2 0 018.736 3h4.018c.163 0 .326.02.485.06L17 4m-7 10v2a2 2 0 002 2h.095c.5 0 .905-.405.905-.905 0-.714.211-1.412.608-2.006L17 13V4m-7 10h2m5-10h2a2 2 0 012 2v6a2 2 0 01-2 2h-2.5"/></svg>'
|
||||
.'<span class="mc-vote-count mc-vote-down-count">'.$down.'</span>'
|
||||
.'</button>'
|
||||
.'</div>';
|
||||
}
|
||||
|
||||
// Rückwärtskompatibilität
|
||||
public static function render_like_btn($attach_id) {
|
||||
return self::render_vote_btns($attach_id);
|
||||
}
|
||||
|
||||
public static function ajax_vote() {
|
||||
// Delegiert an MC_Gallery_Core::handle_vote()
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
MC_Gallery_Core::handle_vote();
|
||||
} else {
|
||||
wp_send_json_error(['message' => 'Core nicht geladen.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user