Files
Wordpress-MC-Gallery/includes/class-mc-gallery-shortcodes.php
2026-03-29 13:35:46 +02:00

1321 lines
69 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
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']);
}
public static function shortcode_overview($atts) {
$atts = shortcode_atts([
'server_id' => 0,
'server_ids' => '',
'thumb_h' => 0
], $atts);
$thumb_h = intval($atts['thumb_h']) ?: MC_Gallery_Core::get_default_thumb_h();
$show_date = get_option(MC_Gallery_Core::OPTION_SHOW_DATE, true);
$server_ids_to_search = [];
// Server IDs sammeln
if (!empty($atts['server_ids'])) {
$raw_ids = explode(',', $atts['server_ids']);
foreach ($raw_ids as $id) {
$int_id = intval(trim($id));
if ($int_id > 0) $server_ids_to_search[] = $int_id;
}
} else if (!empty($atts['server_id'])) {
$server_ids_to_search[] = intval($atts['server_id']);
} else {
// Alle aktiven Server laden
$all_server_posts = get_posts([
'post_type' => 'mc_server',
'meta_key' => 'mc_server_active',
'meta_value' => 1,
'numberposts' => -1
]);
foreach ($all_server_posts as $s) {
$server_ids_to_search[] = $s->ID;
}
}
if (empty($server_ids_to_search)) {
return '<div class="mc-gallery-container"><div class="mc-empty-state">🚫 Keine aktiven Server gefunden.</div></div>';
}
// Parameter auslesen
$q_player = isset($_GET['player']) ? sanitize_text_field($_GET['player']) : '';
$q_server = isset($_GET['server']) ? intval($_GET['server']) : 0;
$q_album = isset($_GET['album']) ? intval($_GET['album']) : 0;
$current_url = remove_query_arg(['player', 'server', 'album']);
// ==============================
// 1. FALL: Album-Ansicht (wenn ?album=ID)
// ==============================
if ($q_album) {
return self::shortcode_album_view(['album_id' => $q_album]);
}
// ==============================
// 2. FALL: Spieler-Spezifische Ansicht
// ==============================
if ($q_player) {
// Header erstellen
$out = '<div class="mc-gallery-container">';
$out .= '<div class="mc-player-header">';
$out .= '<div class="mc-player-title">';
$out .= '<div class="mc-player-avatar">👤</div>';
$out .= '<h2>Gallery of <span class="mc-highlight">'.esc_html($q_player).'</span></h2>';
$out .= '</div>';
$out .= '<a href="'.esc_url($current_url).'" class="mc-btn mc-btn-ghost mc-btn-small">';
$out .= '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>';
$out .= ' Zurück zur Übersicht';
$out .= '</a>';
$out .= '</div>';
// Alle Galerien für diesen Spieler laden
$all_galleries = get_posts([
'post_type' => 'mc_gallery',
'posts_per_page' => -1,
'meta_query' => [
[
'key' => 'mc_server',
'value' => $server_ids_to_search,
'compare' => 'IN'
]
]
]);
// Filter nach Spielername
$player_galleries = [];
$player_gallery_ids = [];
foreach ($all_galleries as $gal) {
$p = get_post_meta($gal->ID, 'mc_player', true);
if ($p === $q_player) {
$player_galleries[] = $gal;
$player_gallery_ids[] = $gal->ID;
}
}
// ALBEN dieses Spielers laden
$albums = [];
if (!empty($player_gallery_ids)) {
$albums = get_posts([
'post_type' => 'mc_album',
'posts_per_page' => -1,
'meta_query' => [[
'key' => 'mc_gallery_id',
'value' => $player_gallery_ids,
'compare' => 'IN',
]],
'orderby' => 'date',
'order' => 'DESC'
]);
}
// --- HTML Alben ---
if (!empty($albums)) {
$out .= '<div class="mc-albums-section">';
$out .= '<h3 class="mc-section-title">📁 Alben ('.count($albums).')</h3>';
$out .= '<div class="mc-albums-grid">';
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),
'orderby' => 'date',
'order' => 'DESC'
]);
$cover_url = '';
if (!empty($album_images)) {
$cover_array = wp_get_attachment_image_src($album_images[0]->ID, 'medium');
$cover_url = $cover_array ? $cover_array[0] : '';
}
$album_count = get_post_meta($album->ID, 'mc_image_count', true) ?: 0;
$album_link = add_query_arg(['album' => $album->ID], $current_url);
$out .= '<a href="'.esc_url($album_link).'" class="mc-album-card">';
if ($cover_url) {
$out .= '<div class="mc-album-cover" style="background-image: url('.esc_url($cover_url).')"></div>';
} else {
$out .= '<div class="mc-album-cover mc-album-empty">📁</div>';
}
$out .= '<div class="mc-album-info">';
$out .= '<h4>'.esc_html($album->post_title).'</h4>';
$out .= '<span class="mc-album-count">'.$album_count.' Images</span>';
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
$out .= '</div>';
}
// Alle Bilder des Spielers laden
$all_images = get_posts([
'post_type' => 'attachment',
'post_parent' => $player_gallery_ids,
'posts_per_page' => -1,
'post_mime_type' => 'image',
'orderby' => 'date',
'order' => 'DESC'
]);
// BILDER FILTER: Nur Bilder, die in einem Album sind
$images_linked_to_albums = [];
foreach ($all_images as $img) {
$album_id = get_post_meta($img->ID, 'mc_album_id', true);
// Prüfen ob Album ID existiert und nicht 0 ist
if (!empty($album_id) && $album_id > 0) {
$images_linked_to_albums[] = $img;
}
}
// --- HTML Bilder (NUR VERKNÜPFTE) ---
if (!empty($images_linked_to_albums)) {
$out .= '<div class="mc-images-section">';
$out .= '<h3 class="mc-section-title">🖼️ Alle Bilder ('.count($images_linked_to_albums).')</h3>';
$out .= '<div class="mc-gallery-grid">';
foreach ($images_linked_to_albums as $img) {
$full = wp_get_attachment_url($img->ID);
$upload_date = date_i18n('d.m.Y', strtotime($img->post_date));
$album_id = get_post_meta($img->ID, 'mc_album_id', true);
$album_name = '';
if ($album_id) {
$album_post = get_post($album_id);
if ($album_post) {
$album_name = $album_post->post_title;
}
}
$metadata = wp_get_attachment_metadata($img->ID);
$width = isset($metadata['width']) ? $metadata['width'] : 0;
$height = isset($metadata['height']) ? $metadata['height'] : 0;
$aspect_ratio = ($width && $height) ? ($width / $height) : 1;
$resize_pct = intval(get_option(MC_Gallery_Core::OPTION_RESIZE_PCT, 100));
if ($resize_pct < 100 && isset($metadata['sizes']['mc-optimized'])) {
$upload_dir = wp_upload_dir();
$file_path = dirname($metadata['file']) . '/' . $metadata['sizes']['mc-optimized']['file'];
$thumb = $upload_dir['baseurl'] . '/' . $file_path;
} else {
$thumb_array = wp_get_attachment_image_src($img->ID, 'medium');
$thumb = $thumb_array ? $thumb_array[0] : $full;
}
$data_date_attr = $show_date ? 'data-date="'.esc_attr($upload_date).'"' : '';
$views = get_post_meta($img->ID, 'mc_views', true) ?: 0;
$out .= '<a href="'.esc_url($full).'" class="mc-gallery-item" '.$data_date_attr.' 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($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>';
if ($album_name) {
$out .= '<div class="mc-album-badge">📁 '.esc_html($album_name).'</div>';
}
$out .= '</div>';
$out .= '</div>';
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
$out .= '</div>';
}
$out .= '</div>';
return $out;
}
// ==============================
// 3. FALL: Haupt-Übersicht (Kein Spieler gewählt)
// ==============================
// Alle mc_gallery Posts laden
$galleries = get_posts([
'post_type' => 'mc_gallery',
'posts_per_page' => -1,
'meta_query' => [
[
'key' => 'mc_server',
'value' => $server_ids_to_search,
'compare' => 'IN'
]
],
'orderby' => 'date',
'order' => 'DESC'
]);
if (empty($galleries)) {
return '<div class="mc-gallery-container"><div class="mc-empty-state">🎮 No galleries on selected servers yet.</div></div>';
}
$all_images = [];
$players_list = [];
$player_counts = [];
foreach ($galleries as $gallery) {
$player = get_post_meta($gallery->ID, 'mc_player', true);
if (!in_array($player, $players_list)) {
$players_list[] = $player;
$player_counts[$player] = 0;
}
$images = get_posts([
'post_type' => 'attachment',
'post_parent' => $gallery->ID,
'posts_per_page' => -1,
'post_mime_type' => 'image',
'orderby' => 'date',
'order' => 'DESC'
]);
foreach ($images as $img) {
$img->mc_player_name = $player;
$img->mc_upload_date = $img->post_date;
$img->mc_gallery_id = $gallery->ID;
$all_images[] = $img;
$player_counts[$player]++;
}
}
usort($all_images, function($a, $b) {
return strtotime($b->mc_upload_date) - strtotime($a->mc_upload_date);
});
$out = '<div class="mc-gallery-container">';
// Filter Bar
if (!empty($players_list)) {
$active_all = empty($q_player) ? 'mc-tag-active' : '';
$out .= '<div class="mc-filter-bar">';
$out .= '<div class="mc-filter-header">';
$out .= '<svg class="mc-filter-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"/></svg>';
$out .= '<h3 class="mc-filter-title">Filter nach Spieler</h3>';
$out .= '</div>';
$out .= '<div class="mc-filter-tags">';
$total = count($all_images);
$out .= '<a href="'.esc_url($current_url).'" class="mc-tag '.$active_all.'">';
$out .= '🌐 Alle Spieler';
$out .= '<span class="mc-tag-count">'.$total.'</span>';
$out .= '</a>';
foreach ($players_list as $p) {
$link = esc_url(add_query_arg([
'player' => rawurlencode($p)
], $current_url));
$is_active = ($p === $q_player) ? 'mc-tag-active' : '';
$count = isset($player_counts[$p]) ? $player_counts[$p] : 0;
$out .= '<a href="'.$link.'" class="mc-tag '.$is_active.'">';
$out .= '👤 '.esc_html($p);
$out .= '<span class="mc-tag-count">'.$count.'</span>';
$out .= '</a>';
}
$out .= '</div></div>';
}
// Bilder Grid (Gemischt - Alle Bilder, auch unverknüpfte)
if (!empty($all_images)) {
$out .= '<div class="mc-gallery-grid">';
foreach ($all_images as $img) {
$full = wp_get_attachment_url($img->ID);
$player_name = esc_html($img->mc_player_name);
$upload_date = date_i18n('d.m.Y', strtotime($img->mc_upload_date));
$album_id = get_post_meta($img->ID, 'mc_album_id', true);
$album_name = '';
if ($album_id) {
$album_post = get_post($album_id);
if ($album_post) {
$album_name = $album_post->post_title;
}
}
$metadata = wp_get_attachment_metadata($img->ID);
$width = isset($metadata['width']) ? $metadata['width'] : 0;
$height = isset($metadata['height']) ? $metadata['height'] : 0;
$aspect_ratio = ($width && $height) ? ($width / $height) : 1;
$resize_pct = intval(get_option(MC_Gallery_Core::OPTION_RESIZE_PCT, 100));
if ($resize_pct < 100 && isset($metadata['sizes']['mc-optimized'])) {
$upload_dir = wp_upload_dir();
$file_path = dirname($metadata['file']) . '/' . $metadata['sizes']['mc-optimized']['file'];
$thumb = $upload_dir['baseurl'] . '/' . $file_path;
} else {
$thumb_array = wp_get_attachment_image_src($img->ID, 'medium');
$thumb = $thumb_array ? $thumb_array[0] : $full;
}
$data_date_attr = $show_date ? 'data-date="'.esc_attr($upload_date).'"' : '';
$views = get_post_meta($img->ID, 'mc_views', true) ?: 0;
$out .= '<a href="'.esc_url($full).'" class="mc-gallery-item" data-player="'.esc_attr($player_name).'" '.$data_date_attr.' data-album="'.esc_attr($album_name).'" 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: '.$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>';
if ($album_name) {
$out .= '<div class="mc-album-badge">📁 '.esc_html($album_name).'</div>';
}
$out .= '</div>';
$out .= '</div>';
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
} else {
$out .= '<div class="mc-empty-state">🔍 Keine Bilder gefunden für den ausgewählten Filter.</div>';
}
$out .= '</div>';
return $out;
}
public static function shortcode_player($atts) {
$atts = shortcode_atts([
'player' => '',
'server_id' => 0,
'thumb_h' => 0
], $atts);
$player = sanitize_text_field($atts['player']);
$server_id = intval($atts['server_id']);
$thumb_h = intval($atts['thumb_h']) ?: MC_Gallery_Core::get_default_thumb_h();
$show_date = get_option(MC_Gallery_Core::OPTION_SHOW_DATE, true);
if (!$player || !$server_id) {
return '<div class="mc-notice mc-error">❌ Invalid request.</div>';
}
$gallery = MC_Gallery_Helpers::find_or_create_gallery_post($player, $server_id);
if (!$gallery) {
return '<div class="mc-empty-state">📁 Gallery not found.</div>';
}
$images = get_posts([
'post_type' => 'attachment',
'post_parent' => $gallery->ID,
'posts_per_page' => -1,
'post_mime_type' => 'image',
'orderby' => 'date',
'order' => 'DESC'
]);
$albums = get_posts([
'post_type' => 'mc_album',
'posts_per_page' => -1,
'meta_key' => 'mc_gallery_id',
'meta_value' => $gallery->ID,
'orderby' => 'date',
'order' => 'DESC'
]);
if (empty($images) && empty($albums)) {
return '<div class="mc-gallery-container">
<div class="mc-empty-state">
📷 '.esc_html($player).' has not uploaded any images yet.
</div>
</div>';
}
$current_url = remove_query_arg(['player', 'server', 'album']);
$out = '<div class="mc-gallery-container">';
$out .= '<div class="mc-player-header">';
$out .= '<div class="mc-player-title">';
$out .= '<div class="mc-player-avatar">👤</div>';
$out .= '<h2>Gallery of <span class="mc-highlight">'.esc_html($player).'</span></h2>';
$out .= '</div>';
$out .= '<a href="'.esc_url($current_url).'" class="mc-btn mc-btn-ghost mc-btn-small">';
$out .= '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>';
$out .= ' Zurück zur Übersicht';
$out .= '</a>';
$out .= '</div>';
if (!empty($albums)) {
$out .= '<div class="mc-albums-section">';
$out .= '<h3 class="mc-section-title">📁 Albums ('.count($albums).')</h3>';
$out .= '<div class="mc-albums-grid">';
foreach ($albums as $album) {
$album_images = get_posts([
'post_type' => 'attachment',
'posts_per_page' => 1,
'post_mime_type' => 'image',
'post_parent' => get_post_meta($album->ID, 'mc_gallery_id', true),
'orderby' => 'date',
'order' => 'DESC'
]);
$cover_url = '';
if (!empty($album_images)) {
$cover_array = wp_get_attachment_image_src($album_images[0]->ID, 'medium');
$cover_url = $cover_array ? $cover_array[0] : '';
}
$album_count = get_post_meta($album->ID, 'mc_image_count', true) ?: 0;
$album_link = add_query_arg(['album' => $album->ID], $current_url);
$out .= '<a href="'.esc_url($album_link).'" class="mc-album-card">';
if ($cover_url) {
$out .= '<div class="mc-album-cover" style="background-image: url('.esc_url($cover_url).')"></div>';
} else {
$out .= '<div class="mc-album-cover mc-album-empty">📁</div>';
}
$out .= '<div class="mc-album-info">';
$out .= '<h4>'.esc_html($album->post_title).'</h4>';
$out .= '<span class="mc-album-count">'.$album_count.' Images</span>';
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
$out .= '</div>';
}
if (!empty($images)) {
$out .= '<div class="mc-images-section">';
$out .= '<h3 class="mc-section-title">🖼️ Alle Bilder ('.count($images).')</h3>';
$out .= '<div class="mc-gallery-grid">';
foreach ($images as $img) {
$full = wp_get_attachment_url($img->ID);
$upload_date = date_i18n('d.m.Y', strtotime($img->post_date));
$metadata = wp_get_attachment_metadata($img->ID);
$width = isset($metadata['width']) ? $metadata['width'] : 0;
$height = isset($metadata['height']) ? $metadata['height'] : 0;
$aspect_ratio = ($width && $height) ? ($width / $height) : 1;
$resize_pct = intval(get_option(MC_Gallery_Core::OPTION_RESIZE_PCT, 100));
if ($resize_pct < 100 && isset($metadata['sizes']['mc-optimized'])) {
$upload_dir = wp_upload_dir();
$file_path = dirname($metadata['file']) . '/' . $metadata['sizes']['mc-optimized']['file'];
$thumb = $upload_dir['baseurl'] . '/' . $file_path;
} else {
$thumb_array = wp_get_attachment_image_src($img->ID, 'medium');
$thumb = $thumb_array ? $thumb_array[0] : $full;
}
$data_date_attr = $show_date ? 'data-date="'.esc_attr($upload_date).'"' : '';
$views = get_post_meta($img->ID, 'mc_views', true) ?: 0;
$out .= '<a href="'.esc_url($full).'" class="mc-gallery-item" '.$data_date_attr.' 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).'" 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>';
$out .= '</div>';
$out .= '</div>';
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
$out .= '</div>';
}
$out .= '</div>';
return $out;
}
public static function shortcode_all_albums_overview($atts) {
$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,
'orderby' => 'date',
'order' => 'DESC'
]);
if (empty($albums)) {
return '<div class="mc-gallery-container"><div class="mc-empty-state">📁 Es wurden noch keine Alben erstellt.</div></div>';
}
$out = '<div class="mc-gallery-container">';
$out .= '<div class="mc-player-header">';
$out .= '<div class="mc-player-title">';
$out .= '<div class="mc-player-avatar">📁</div>';
$out .= '<h2>📁 Alle Alben (' . count($albums) . ')</h2>';
$out .= '</div>';
$out .= '</div>';
$out .= '<div class="mc-albums-grid">';
foreach ($albums as $album) {
$album_count = get_post_meta($album->ID, 'mc_image_count', true) ?: 0;
$cover_images = get_posts([
'post_type' => 'attachment',
'post_status' => 'inherit',
'posts_per_page' => 1,
'post_mime_type' => 'image',
'meta_key' => 'mc_album_id',
'meta_value' => $album->ID,
'orderby' => 'date',
'order' => 'DESC'
]);
$cover_url = '';
if (!empty($cover_images)) {
$cover_array = wp_get_attachment_image_src($cover_images[0]->ID, 'medium');
$cover_url = $cover_array ? $cover_array[0] : '';
}
$album_link = add_query_arg(['album' => $album->ID], $current_url);
$gallery_id = get_post_meta($album->ID, 'mc_gallery_id', true);
$player_name = '';
if ($gallery_id) {
$player_name = get_post_meta($gallery_id, 'mc_player', true);
}
$out .= '<a href="'.esc_url($album_link).'" class="mc-album-card" title="'.esc_attr($player_name).'">';
if ($cover_url) {
$out .= '<div class="mc-album-cover" style="background-image: url('.esc_url($cover_url).')"></div>';
} else {
$out .= '<div class="mc-album-cover mc-album-empty">📁</div>';
}
$out .= '<div class="mc-album-info">';
$out .= '<h4>'.esc_html($album->post_title).'</h4>';
$out .= '<span class="mc-album-count">'.$album_count.' Images</span>';
if ($player_name) {
$out .= '<span class="mc-album-player">by '.esc_html($player_name).'</span>';
}
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
$out .= '</div>';
return $out;
}
public static function shortcode_album_view($atts) {
$atts = shortcode_atts([
'album_id' => 0,
'server_id' => 0
], $atts);
$album_id = intval($atts['album_id']);
$album = get_post($album_id);
$show_date = get_option(MC_Gallery_Core::OPTION_SHOW_DATE, true);
if (!$album || $album->post_type !== 'mc_album') {
return '<div class="mc-notice mc-error">❌ Album not found.</div>';
}
$images = get_posts([
'post_type' => 'attachment',
'post_status' => 'inherit',
'posts_per_page' => -1,
'post_mime_type' => 'image',
'meta_key' => 'mc_album_id',
'meta_value' => $album_id,
'orderby' => 'date',
'order' => 'DESC'
]);
$gallery_id = get_post_meta($album_id, 'mc_gallery_id', true);
$gallery = get_post($gallery_id);
$player = $gallery ? get_post_meta($gallery_id, 'mc_player', true) : '';
$current_url = remove_query_arg(['album']);
$out = '<div class="mc-gallery-container">';
$out .= '<div class="mc-player-header">';
$out .= '<div class="mc-player-title">';
$out .= '<div class="mc-player-avatar">📁</div>';
$out .= '<h2><span class="mc-highlight">'.esc_html($album->post_title).'</span></h2>';
if ($player) {
$out .= '<p class="mc-album-subtitle">by '.esc_html($player).'</p>';
}
$out .= '</div>';
$out .= '<a href="'.esc_url($current_url).'" class="mc-btn mc-btn-ghost mc-btn-small">';
$out .= '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>';
$out .= ' Zurück';
$out .= '</a>';
$out .= '</div>';
if (!empty($images)) {
$out .= '<div class="mc-gallery-grid">';
foreach ($images as $img) {
$full = wp_get_attachment_url($img->ID);
$upload_date = date_i18n('d.m.Y', strtotime($img->post_date));
$metadata = wp_get_attachment_metadata($img->ID);
$width = isset($metadata['width']) ? $metadata['width'] : 0;
$height = isset($metadata['height']) ? $metadata['height'] : 0;
$aspect_ratio = ($width && $height) ? ($width / $height) : 1;
$thumb_array = wp_get_attachment_image_src($img->ID, 'medium');
$thumb = $thumb_array ? $thumb_array[0] : $full;
$data_date_attr = $show_date ? 'data-date="'.esc_attr($upload_date).'"' : '';
$views = get_post_meta($img->ID, 'mc_views', true) ?: 0;
$out .= '<a href="'.esc_url($full).'" class="mc-gallery-item" '.$data_date_attr.' 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="" loading="lazy" style="aspect-ratio: '.$aspect_ratio.';">';
$out .= self::render_like_btn($img->ID);
$out .= '</div>';
$out .= '</a>';
}
$out .= '</div>';
} else {
$out .= '<div class="mc-empty-state">📷 This album contains no images yet.</div>';
}
$out .= '</div>';
return $out;
}
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">
<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>
<?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">
<button class="mc-modal-close" aria-label="Schließen">&times;</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_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>
<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(){
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function(){
setTimeout(function(){
var btn = document.getElementById('mc-open-upload-modal');
if (btn) btn.click();
}, 500);
});
} else {
setTimeout(function(){
var btn = document.getElementById('mc-open-upload-modal');
if (btn) btn.click();
}, 500);
}
})();
</script>
<?php endif; ?>
<?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">&times;</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.']);
}
}
}