Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0bec83593 | |||
| 7ef72641f6 | |||
| c4c02c1b9d | |||
| 0ab87297ac | |||
| 92ecb0e719 | |||
| d6c23c086e | |||
| 7b7c5e7251 | |||
| afa02ef721 | |||
| d4cfc5cbf3 | |||
| 9ef317e3ac | |||
| 66ca7919a1 | |||
| 80838c3611 | |||
| 5d6e49e0b6 | |||
| c64e277fe6 | |||
| a16bd5e911 | |||
| 824e5a3324 | |||
| 2160c11c66 | |||
| bab8e406a2 | |||
| 2572ce610e | |||
| 7019c7731f | |||
| e55126c266 | |||
| cc6d7577ea |
24
README.md
24
README.md
@@ -20,7 +20,7 @@ Ein Spieler kann nicht einfach auf "Hochladen" klicken und Bilder laden. Er muss
|
||||
3. Er muss diesen Code auf dem Minecraft-Server im Chat eingeben (z.B. `/verify [Code]`).
|
||||
4. Erst dann wird der Upload freigeschaltet.
|
||||
|
||||
Dies stellt sicher, dass niemand unter dem Namen eines anderen Spieler Bilder hochlädt.
|
||||
Dies stellt sicher, dass niemand unter dem Namen eines anderen Spielers Bilder hochlädt.
|
||||
|
||||
---
|
||||
|
||||
@@ -111,7 +111,7 @@ Erstellt eine dedizierte Seite für einen spezifischen Spieler. Dies ist nützli
|
||||
|
||||
**Code:** `[mc_gallery_all_albums]`
|
||||
|
||||
Zeigt eine Übersicht aller ersterten Alben an (unabhängig von den einzelnen Bildern). Jedes Album wird als Karte mit einem Titel und einer Vorschau angezeigt. Ideal, um sich einen schnellen Überblick über die Sammlungen zu verschaffen.
|
||||
Zeigt eine Übersicht aller erstellten Alben an (unabhängig von den einzelnen Bildern). Jedes Album wird als Karte mit einem Titel und einer Vorschau angezeigt. Ideal, um sich einen schnellen Überblick über die Sammlungen zu verschaffen.
|
||||
|
||||
**Beispiel:**
|
||||
```
|
||||
@@ -128,10 +128,26 @@ Zeigt eine Übersicht aller ersterten Alben an (unabhängig von den einzelnen Bi
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Voraussetzungen
|
||||
|
||||
Für die Verifizierungsfunktion wird die **StatusAPI** benötigt:
|
||||
|
||||
**[StatusAPI auf Git](https://git.viper.ipv64.net/M_Viper/StatusAPI)**
|
||||
|
||||
Die StatusAPI muss auf deinem Minecraft-Bungeecord laufen, um die Kommunikation zwischen dem Minecraft-Server und dem WordPress-Plugin zu ermöglichen.
|
||||
|
||||
---
|
||||
|
||||
## Häufige Fragen (FAQ)
|
||||
|
||||
**F: Warum können sich Spieler nicht verifizieren?**
|
||||
A: Du musst sicherstellen, dass auf deinem Minecraft-Server ein Plugin läuft, das mit diesem WordPress-Plugin kommunizieren kann. Der Server muss den Befehl `/verify` entgegennehmen und an deine WordPress-Website melden.
|
||||
A: Du musst sicherstellen, dass auf deinem Minecraft-Bungeecord die [StatusAPI](https://git.viper.ipv64.net/M_Viper/StatusAPI) läuft, die mit diesem WordPress-Plugin kommunizieren kann. Der Server muss den Befehl `/verify` entgegennehmen und an deine WordPress-Website melden.
|
||||
|
||||
**F: Wo finde ich die Server ID?**
|
||||
A: Gehe im WordPress Dashboard auf "MC Gallery PRO" > "MC Server". Die ID ist die Zahl, die in der URL steht, wenn du einen Server bearbeitest (z.B. `post.php?post=15&action=edit` → ID ist 15).
|
||||
A: Gehe im WordPress Dashboard auf "MC Gallery PRO" > "MC Server". Die ID ist die Zahl, die in der URL steht, wenn du einen Server bearbeitest (z.B. `post.php?post=15&action=edit` → ID ist 15).
|
||||
|
||||
---
|
||||
|
||||
**Copyright © 2026 - M_Viper - Alle Rechte vorbehalten**
|
||||
|
||||
Die unbefugte Vervielfältigung, Verbreitung oder Weitergabe dieses Plugins ist strafbar und wird rechtlich verfolgt.
|
||||
@@ -1,54 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.mviper</groupId>
|
||||
<artifactId>Verify</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Verify</name>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<spigot.version>1.20.1-R0.1-SNAPSHOT</spigot.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>${spigot.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>de.mviper.verify.Verify</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,146 +0,0 @@
|
||||
package de.mviper.verify;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class Verify extends JavaPlugin implements CommandExecutor {
|
||||
|
||||
private String wpVerifyUrl;
|
||||
private String sharedSecret;
|
||||
private int serverId;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
saveDefaultConfig();
|
||||
wpVerifyUrl = getConfig().getString("wp_verify_url", "http://deine-wp-domain.tld");
|
||||
sharedSecret = getConfig().getString("shared_secret", "ChangeMe");
|
||||
serverId = getConfig().getInt("server_id", 0);
|
||||
getCommand("verify").setExecutor(this);
|
||||
getLogger().info("Verify enabled for server ID: " + serverId + " | WP URL: " + wpVerifyUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "Nur Spieler können diesen Befehl benutzen.");
|
||||
return true;
|
||||
}
|
||||
Player p = (Player) sender;
|
||||
if (args.length != 1) {
|
||||
p.sendMessage(ChatColor.YELLOW + "Benutzung: /verify <token>");
|
||||
return true;
|
||||
}
|
||||
String token = args[0].trim();
|
||||
String playerName = p.getName();
|
||||
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
// FIX: Explizit UTF-8 für die Signatur
|
||||
Charset utf8 = Charset.forName("UTF-8");
|
||||
String signature = hmacSHA256(playerName + token, sharedSecret, utf8);
|
||||
|
||||
// FIX: Explizit UTF-8 für den Payload
|
||||
String payload = "{\"player\":\"" + escapeJson(playerName) + "\",\"token\":\"" + escapeJson(token) + "\",\"server_id\":" + serverId + ",\"signature\":\"" + signature + "\"}";
|
||||
|
||||
URL url = new URL(wpVerifyUrl + "/wp-json/mc-gallery/v1/verify");
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setReadTimeout(7000);
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(payload.getBytes(utf8));
|
||||
}
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
String resp;
|
||||
|
||||
// FIX: Antwort immer als UTF-8 lesen, egal ob 200 oder 403
|
||||
if (code >= 200 && code < 300) {
|
||||
InputStream is = conn.getInputStream();
|
||||
resp = streamToString(is, utf8);
|
||||
} else {
|
||||
InputStream es = conn.getErrorStream();
|
||||
resp = streamToString(es, utf8);
|
||||
}
|
||||
|
||||
// Antwort parsen
|
||||
if (resp != null && !resp.isEmpty() && resp.trim().startsWith("{")) {
|
||||
// Erfolgreiche Übertragung, nun JSON parsen
|
||||
|
||||
// Checken ob success true ist
|
||||
boolean isSuccess = resp.contains("\"success\":true");
|
||||
|
||||
// Die message auslesen
|
||||
String message = "Ein unbekannter Fehler ist aufgetreten.";
|
||||
int keyIndex = resp.indexOf("\"message\":\"");
|
||||
if (keyIndex != -1) {
|
||||
int startIndex = keyIndex + 11;
|
||||
int endIndex = resp.indexOf("\"", startIndex);
|
||||
if (endIndex != -1) {
|
||||
message = resp.substring(startIndex, endIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Nachricht senden (mit Farbcodes)
|
||||
if (isSuccess) {
|
||||
p.sendMessage(ChatColor.GREEN + "✓ " + message);
|
||||
p.sendMessage(ChatColor.GRAY + "Du kannst nun Bilder hochladen!");
|
||||
} else {
|
||||
// Hier landen Fehler wie "Name stimmt nicht überein" oder 403
|
||||
// Durch die UTF-8 Lesung sollten Umlaute jetzt korrekt sein
|
||||
p.sendMessage(ChatColor.RED + "✗ " + message);
|
||||
}
|
||||
} else {
|
||||
p.sendMessage(ChatColor.RED + "✗ Fehler beim Verbinden mit der Webseite (Code: " + code + ")");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
p.sendMessage(ChatColor.RED + "✗ Ein interner Fehler ist aufgetreten.");
|
||||
getLogger().warning("Verify error: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIX: UTF-8 als Parameter übergeben
|
||||
private static String hmacSHA256(String data, String key, Charset charset) throws Exception {
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(key.getBytes(charset), "HmacSHA256"));
|
||||
byte[] raw = mac.doFinal(data.getBytes(charset));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : raw) sb.append(String.format("%02x", b));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// FIX: UTF-8 als Parameter übergeben
|
||||
private static String streamToString(InputStream in, Charset charset) throws IOException {
|
||||
if (in == null) return "";
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(in, charset))) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) sb.append(line);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static String escapeJson(String s) {
|
||||
return s.replace("\\", "\\\\").replace("\"","\\\"").replace("\n","\\n").replace("\r","\\r");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
# URL deiner WordPress-Seite (ohne Slash am Ende)
|
||||
wp_verify_url: "https://deine-wp-domain.tld"
|
||||
|
||||
# Shared Secret — muss identisch sein mit dem Secret im WordPress Server-CPT
|
||||
shared_secret: "TrageHierDasSecretEin"
|
||||
|
||||
# server_id: die Post-ID des mc_server-Posts in der jeweiligen WordPress-Installation
|
||||
server_id: 1
|
||||
@@ -1,7 +0,0 @@
|
||||
name: Verify
|
||||
main: de.mviper.verify.Verify
|
||||
version: 1.0
|
||||
api-version: 1.20
|
||||
commands:
|
||||
verify:
|
||||
description: Verifiziere ein Website-Token (Usage /verify <token>)
|
||||
@@ -45,6 +45,19 @@
|
||||
background-color: var(--mc-primary-hover);
|
||||
}
|
||||
|
||||
.mc-upload-wrapper .mc-btn-secondary,
|
||||
.mc-combined-wrapper .mc-btn-secondary {
|
||||
background-color: rgba(255,255,255,.07);
|
||||
color: #94a3b8;
|
||||
border: 1px solid rgba(100,116,139,.3);
|
||||
}
|
||||
.mc-upload-wrapper .mc-btn-secondary:hover,
|
||||
.mc-combined-wrapper .mc-btn-secondary:hover {
|
||||
background-color: rgba(255,255,255,.12);
|
||||
color: #cbd5e1;
|
||||
border-color: rgba(100,116,139,.5);
|
||||
}
|
||||
|
||||
|
||||
/* =================================================================== */
|
||||
/* === 2. MODAL SPECIFIC CSS (Fix für das Popup) ================== */
|
||||
@@ -739,6 +752,37 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Like-Button in Lightbox */
|
||||
.mc-lightbox-like-wrap {
|
||||
margin-top: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.mc-like-btn--lightbox {
|
||||
position: static !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 20px !important;
|
||||
border-radius: 24px !important;
|
||||
font-size: 14px !important;
|
||||
background: rgba(255,255,255,.1) !important;
|
||||
border: 1px solid rgba(255,255,255,.2) !important;
|
||||
color: #fff !important;
|
||||
cursor: pointer;
|
||||
transition: background .15s, border-color .15s !important;
|
||||
}
|
||||
.mc-like-btn--lightbox:hover {
|
||||
background: rgba(239,68,68,.25) !important;
|
||||
border-color: rgba(239,68,68,.4) !important;
|
||||
}
|
||||
.mc-like-btn--lightbox.mc-like-btn--active {
|
||||
background: rgba(239,68,68,.2) !important;
|
||||
border-color: rgba(239,68,68,.5) !important;
|
||||
}
|
||||
.mc-like-btn--lightbox .mc-like-icon { width: 18px; height: 18px; }
|
||||
.mc-like-btn--lightbox .mc-like-label { font-size: 13px; opacity: .85; }
|
||||
|
||||
.mc-lightbox-close {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
@@ -782,4 +826,314 @@
|
||||
max-width: 90%;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
/* =================================================================== */
|
||||
/* === LIKE / VOTE BUTTON =========================================== */
|
||||
/* =================================================================== */
|
||||
|
||||
.mc-like-btn {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 5px 10px;
|
||||
background: rgba(0,0,0,0.65);
|
||||
border: 1px solid rgba(255,255,255,0.15);
|
||||
border-radius: 20px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: background 0.15s, border-color 0.15s, transform 0.1s;
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
.mc-like-btn:hover {
|
||||
background: rgba(239,68,68,0.3);
|
||||
border-color: rgba(239,68,68,0.5);
|
||||
transform: scale(1.08);
|
||||
}
|
||||
.mc-like-btn:active { transform: scale(0.96); }
|
||||
.mc-like-btn:disabled { opacity: 0.5; cursor: wait; }
|
||||
|
||||
.mc-like-btn--active {
|
||||
background: rgba(239,68,68,0.25);
|
||||
border-color: rgba(239,68,68,0.6);
|
||||
color: #fca5a5;
|
||||
}
|
||||
.mc-like-btn--active .mc-like-icon { stroke: #ef4444; fill: rgba(239,68,68,0.3); }
|
||||
|
||||
.mc-like-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
stroke: currentColor;
|
||||
flex-shrink: 0;
|
||||
transition: stroke 0.15s, fill 0.15s;
|
||||
}
|
||||
|
||||
.mc-like-count { min-width: 12px; text-align: center; }
|
||||
|
||||
/* =================================================================== */
|
||||
/* === KOMBINIERTER UPLOAD SHORTCODE ================================ */
|
||||
/* =================================================================== */
|
||||
|
||||
.mc-combined-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.mc-combined-two-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.mc-combined-upload-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 13px 20px;
|
||||
background: var(--mc-primary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: var(--mc-radius);
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
position: relative;
|
||||
}
|
||||
.mc-combined-upload-btn:hover { background: var(--mc-primary-hover); }
|
||||
|
||||
.mc-combined-method-tag {
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
letter-spacing: .05em;
|
||||
text-transform: uppercase;
|
||||
padding: 2px 8px;
|
||||
border-radius: 20px;
|
||||
background: rgba(255,255,255,0.18);
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mc-combined-divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 14px 0;
|
||||
color: #64748b;
|
||||
font-size: .75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .06em;
|
||||
}
|
||||
.mc-combined-divider::before,
|
||||
.mc-combined-divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: rgba(100,116,139,.25);
|
||||
}
|
||||
|
||||
.mc-combined-verified-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
margin-top: 10px;
|
||||
padding: 8px 14px;
|
||||
background: rgba(34,197,94,.08);
|
||||
border: 1px solid rgba(34,197,94,.2);
|
||||
border-radius: 8px;
|
||||
color: #22c55e;
|
||||
font-size: .83rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.mc-combined-verified-row svg {
|
||||
flex-shrink: 0;
|
||||
stroke: #22c55e;
|
||||
}
|
||||
.mc-combined-verified-row strong { font-weight: 700; }
|
||||
|
||||
/* Vote Board */
|
||||
.mc-vote-board .mc-player-header h2 { font-size: 1.3rem; }
|
||||
|
||||
/* =========================================================================
|
||||
VOTE BUTTONS (Daumen hoch / runter)
|
||||
========================================================================= */
|
||||
|
||||
.mc-vote-wrap {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.mc-vote-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 9px;
|
||||
background: rgba(0,0,0,.65);
|
||||
border: 1px solid rgba(255,255,255,.15);
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background .15s, border-color .15s, transform .1s;
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
line-height: 1;
|
||||
}
|
||||
.mc-vote-btn svg {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
flex-shrink: 0;
|
||||
stroke: #fff;
|
||||
transition: stroke .15s, fill .15s;
|
||||
}
|
||||
.mc-vote-btn:hover { transform: scale(1.08); }
|
||||
.mc-vote-btn:active { transform: scale(.94); }
|
||||
.mc-vote-btn:disabled { opacity: .5; cursor: wait; }
|
||||
|
||||
/* Daumen hoch aktiv */
|
||||
.mc-vote-up.mc-vote-btn--active {
|
||||
background: rgba(34,197,94,.25);
|
||||
border-color: rgba(34,197,94,.5);
|
||||
color: #86efac;
|
||||
}
|
||||
.mc-vote-up.mc-vote-btn--active svg { stroke: #22c55e; fill: #22c55e; }
|
||||
.mc-vote-up:not(.mc-vote-btn--active):hover { background: rgba(34,197,94,.2); border-color: rgba(34,197,94,.4); }
|
||||
|
||||
/* Daumen runter aktiv */
|
||||
.mc-vote-down.mc-vote-btn--active {
|
||||
background: rgba(239,68,68,.25);
|
||||
border-color: rgba(239,68,68,.5);
|
||||
color: #fca5a5;
|
||||
}
|
||||
.mc-vote-down.mc-vote-btn--active svg { stroke: #ef4444; fill: #ef4444; }
|
||||
.mc-vote-down:not(.mc-vote-btn--active):hover { background: rgba(239,68,68,.2); border-color: rgba(239,68,68,.4); }
|
||||
|
||||
.mc-vote-count { min-width: 10px; text-align: center; }
|
||||
|
||||
/* In der Lightbox: größer und zentriert */
|
||||
.mc-vote-wrap--lightbox {
|
||||
position: static;
|
||||
justify-content: center;
|
||||
margin-top: 14px;
|
||||
}
|
||||
.mc-vote-wrap--lightbox .mc-vote-btn {
|
||||
padding: 8px 18px;
|
||||
font-size: 13px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
.mc-vote-wrap--lightbox .mc-vote-btn svg { width: 16px; height: 16px; }
|
||||
|
||||
/* =========================================================================
|
||||
COMBINED UPLOAD WRAPPER
|
||||
========================================================================= */
|
||||
|
||||
/* Alle Buttons im Combined-Wrapper: gleiche Basis wie Upload-Button */
|
||||
.mc-combined-wrapper .mc-btn,
|
||||
.mc-combined-wrapper a.mc-btn,
|
||||
.mc-combined-upload-btn {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
border: none;
|
||||
border-radius: var(--mc-radius);
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, opacity 0.2s ease;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mc-combined-upload-btn {
|
||||
margin-top: 0;
|
||||
}
|
||||
.mc-combined-method-tag {
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
letter-spacing: .05em;
|
||||
text-transform: uppercase;
|
||||
background: rgba(255,255,255,.15);
|
||||
padding: 2px 8px;
|
||||
border-radius: 20px;
|
||||
color: rgba(255,255,255,.85);
|
||||
}
|
||||
.mc-combined-two-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
.mc-combined-divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 6px 0;
|
||||
color: rgba(148,163,184,.6);
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .06em;
|
||||
}
|
||||
.mc-combined-divider::before,
|
||||
.mc-combined-divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: rgba(100,116,139,.2);
|
||||
}
|
||||
.mc-combined-verified-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
margin-top: 8px;
|
||||
padding: 7px 12px;
|
||||
background: rgba(34,197,94,.08);
|
||||
border: 1px solid rgba(34,197,94,.2);
|
||||
border-radius: 8px;
|
||||
color: #22c55e;
|
||||
font-size: 13px;
|
||||
}
|
||||
.mc-combined-verified-row svg {
|
||||
flex-shrink: 0;
|
||||
stroke: #22c55e;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
VOTE BOARD
|
||||
========================================================================= */
|
||||
|
||||
.mc-vote-board .mc-player-avatar { font-size: 24px; }
|
||||
|
||||
/* Forum-Button — blaue Variante */
|
||||
.mc-combined-forum-btn {
|
||||
background-color: #2563eb !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.mc-combined-forum-btn:hover {
|
||||
background-color: #1d4ed8 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
405
assets/css/mc-gallery-forum-bridge.css
Normal file
405
assets/css/mc-gallery-forum-bridge.css
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* MC Gallery PRO — Forum Bridge Styles
|
||||
* Pfad: assets/css/mc-gallery-forum-bridge.css
|
||||
*/
|
||||
|
||||
/* ── Verify-Panel unter der Gallery ──────────────────────────────────────── */
|
||||
|
||||
.mc-bridge-verify-wrap {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.mc-bridge-divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 14px 0;
|
||||
color: var(--wbf-text-muted, #94a3b8);
|
||||
font-size: .8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .06em;
|
||||
}
|
||||
.mc-bridge-divider::before,
|
||||
.mc-bridge-divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--wbf-border, rgba(100,116,139,.25));
|
||||
}
|
||||
|
||||
/* ── Forum-Card — gemeinsame Hülle ───────────────────────────────────────── */
|
||||
|
||||
.mc-bridge-card {
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(56,189,248,.15);
|
||||
background: rgba(15,23,42,.55);
|
||||
overflow: hidden;
|
||||
}
|
||||
.mc-bridge-card--warn {
|
||||
border-color: rgba(245,158,11,.22);
|
||||
}
|
||||
.mc-bridge-card--ok {
|
||||
border-color: rgba(34,197,94,.22);
|
||||
}
|
||||
.mc-bridge-card-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 16px 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* Quadratisches Icon-Kästchen */
|
||||
.mc-bridge-card-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 10px;
|
||||
background: rgba(56,189,248,.09);
|
||||
border: 1px solid rgba(56,189,248,.18);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.mc-bridge-card-icon i {
|
||||
font-size: 1.15rem;
|
||||
color: #38bdf8;
|
||||
}
|
||||
|
||||
/* Text-Block */
|
||||
.mc-bridge-card-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.mc-bridge-card-label {
|
||||
font-size: .7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .07em;
|
||||
color: #475569;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.mc-bridge-card-desc {
|
||||
font-size: .84rem;
|
||||
color: #94a3b8;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.mc-bridge-card-desc strong {
|
||||
color: #cbd5e1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Action-Spalte */
|
||||
.mc-bridge-card-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 7px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Haupt-Button */
|
||||
.mc-bridge-action-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 7px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background: #38bdf8;
|
||||
color: #0c1222;
|
||||
font-size: .82rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: .01em;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
transition: opacity .15s;
|
||||
}
|
||||
.mc-bridge-action-btn:hover { opacity: .85; text-decoration: none; color: #0c1222; }
|
||||
.mc-bridge-action-btn--warn {
|
||||
background: #f59e0b;
|
||||
color: #1c1008;
|
||||
}
|
||||
|
||||
/* Sekundär-Button */
|
||||
.mc-bridge-action-btn-ghost {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 7px;
|
||||
padding: 7px 16px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(100,116,139,.3);
|
||||
color: #64748b;
|
||||
font-size: .78rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
transition: border-color .15s, color .15s;
|
||||
}
|
||||
.mc-bridge-action-btn-ghost:hover {
|
||||
border-color: rgba(100,116,139,.5);
|
||||
color: #94a3b8;
|
||||
text-decoration: none;
|
||||
}
|
||||
.mc-bridge-action-btn-ghost i { font-size: .82rem; }
|
||||
|
||||
/* Verifiziert-Badge */
|
||||
.mc-bridge-verified-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 7px 16px;
|
||||
border-radius: 20px;
|
||||
background: rgba(34,197,94,.1);
|
||||
border: 1px solid rgba(34,197,94,.25);
|
||||
color: #22c55e;
|
||||
font-size: .8rem;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Nicht eingeloggt / nicht verknüpft — jetzt via .mc-bridge-card */
|
||||
.mc-bridge-not-logged,
|
||||
.mc-bridge-not-linked {
|
||||
display: none; /* HTML-Ersatz durch mc-bridge-card */
|
||||
}
|
||||
.mc-bridge-btn-inline {
|
||||
color: #38bdf8;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
.mc-bridge-btn-inline:hover { text-decoration: underline; }
|
||||
|
||||
/* Eingeloggt & verknüpft — jetzt via .mc-bridge-card */
|
||||
.mc-bridge-forum-linked { display: none; }
|
||||
|
||||
.mc-bridge-head-sm {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
.mc-bridge-forum-name { font-weight: 500; color: #e2e8f0; }
|
||||
.mc-bridge-arrow { color: #475569; margin: 0 2px; }
|
||||
.mc-bridge-mc-name-sm { font-weight: 600; color: #38bdf8; }
|
||||
|
||||
.mc-bridge-unverified-hint {
|
||||
display: block;
|
||||
font-size: .75rem;
|
||||
color: #f59e0b;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.mc-bridge-verify-trigger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 8px 16px;
|
||||
background: #f59e0b;
|
||||
color: #1c1008;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: .82rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: opacity .15s;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.mc-bridge-verify-trigger:hover { opacity: .85; }
|
||||
.mc-bridge-verify-trigger:disabled { opacity: .5; cursor: wait; }
|
||||
|
||||
.mc-bridge-success {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px 18px;
|
||||
background: rgba(34,197,94,.08);
|
||||
border: 1px solid rgba(34,197,94,.22);
|
||||
border-radius: 12px;
|
||||
color: #22c55e;
|
||||
font-size: .88rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.mc-bridge-success i { font-size: 1.1rem; flex-shrink: 0; }
|
||||
|
||||
.mc-bridge-error {
|
||||
margin-top: 8px;
|
||||
padding: 10px 14px;
|
||||
background: rgba(239,68,68,.08);
|
||||
border: 1px solid rgba(239,68,68,.2);
|
||||
border-radius: 8px;
|
||||
color: #f87171;
|
||||
font-size: .83rem;
|
||||
}
|
||||
.mc-bridge-error i { margin-right: 5px; }
|
||||
|
||||
/* ── Profil-Tab: Minecraft ────────────────────────────────────────────────── */
|
||||
|
||||
.mc-bridge-profile-tab {
|
||||
padding: 4px 0;
|
||||
}
|
||||
.mc-bridge-intro {
|
||||
color: var(--wbf-text-muted, #94a3b8);
|
||||
margin-bottom: 14px;
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
/* Verknüpfte Karte */
|
||||
.mc-bridge-linked-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
padding: 14px 16px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(100,116,139,.2);
|
||||
background: rgba(30,41,59,.5);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.mc-bridge-linked-card.is-verified {
|
||||
border-color: rgba(34,197,94,.3);
|
||||
background: rgba(34,197,94,.05);
|
||||
}
|
||||
.mc-bridge-linked-card.is-pending {
|
||||
border-color: rgba(245,158,11,.25);
|
||||
background: rgba(245,158,11,.04);
|
||||
}
|
||||
|
||||
.mc-bridge-head {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 6px;
|
||||
image-rendering: pixelated;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.mc-bridge-linked-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.mc-bridge-mc-name {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--wbf-text, #e2e8f0);
|
||||
}
|
||||
.mc-bridge-server-hint {
|
||||
font-size: .78rem;
|
||||
color: var(--wbf-text-muted, #64748b);
|
||||
}
|
||||
.mc-bridge-server-hint i { margin-right: 3px; }
|
||||
|
||||
/* Badges */
|
||||
.mc-bridge-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 2px 9px;
|
||||
border-radius: 20px;
|
||||
font-size: .78rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.mc-bridge-badge--ok { background: rgba(34,197,94,.15); color: #22c55e; }
|
||||
.mc-bridge-badge--wait { background: rgba(245,158,11,.15); color: #f59e0b; }
|
||||
|
||||
/* Buttons */
|
||||
.mc-bridge-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
.mc-bridge-btn {
|
||||
padding: 6px 12px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: .82rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: opacity .15s;
|
||||
}
|
||||
.mc-bridge-btn:disabled { opacity: .5; cursor: wait; }
|
||||
.mc-bridge-btn--link {
|
||||
background: var(--wbf-accent, #38bdf8);
|
||||
color: #0f172a;
|
||||
}
|
||||
.mc-bridge-btn--link:hover { opacity: .85; }
|
||||
.mc-bridge-btn--approve {
|
||||
background: rgba(34,197,94,.2);
|
||||
color: #22c55e;
|
||||
}
|
||||
.mc-bridge-btn--approve:hover { background: rgba(34,197,94,.35); }
|
||||
.mc-bridge-btn--unlink {
|
||||
background: rgba(239,68,68,.15);
|
||||
color: #f87171;
|
||||
}
|
||||
.mc-bridge-btn--unlink:hover { background: rgba(239,68,68,.28); }
|
||||
|
||||
/* Pending-Hinweis */
|
||||
.mc-bridge-pending-hint {
|
||||
margin-top: 10px;
|
||||
padding: 9px 13px;
|
||||
background: rgba(245,158,11,.07);
|
||||
border-left: 3px solid #f59e0b;
|
||||
border-radius: 0 6px 6px 0;
|
||||
font-size: .85rem;
|
||||
color: #fcd34d;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.mc-bridge-pending-hint i { margin-right: 5px; }
|
||||
|
||||
/* Verknüpfungs-Formular */
|
||||
.mc-bridge-link-form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: flex-end;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.mc-bridge-link-form label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
font-size: .82rem;
|
||||
color: var(--wbf-text-muted, #94a3b8);
|
||||
}
|
||||
.mc-bridge-link-form input,
|
||||
.mc-bridge-link-form select {
|
||||
padding: 7px 11px;
|
||||
background: rgba(15,23,42,.6);
|
||||
border: 1px solid rgba(100,116,139,.3);
|
||||
border-radius: 6px;
|
||||
color: var(--wbf-text, #e2e8f0);
|
||||
font-size: .9rem;
|
||||
min-width: 180px;
|
||||
}
|
||||
.mc-bridge-link-form input:focus,
|
||||
.mc-bridge-link-form select:focus {
|
||||
outline: none;
|
||||
border-color: var(--wbf-accent, #38bdf8);
|
||||
}
|
||||
|
||||
/* ── Admin-Badge in User-Tabelle ──────────────────────────────────────────── */
|
||||
|
||||
.mc-bridge-admin-mc-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 2px 7px;
|
||||
background: rgba(56,189,248,.1);
|
||||
border: 1px solid rgba(56,189,248,.25);
|
||||
border-radius: 20px;
|
||||
font-size: .78rem;
|
||||
color: #38bdf8;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.mc-bridge-admin-mc-badge img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 3px;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
41
assets/js/forum-bridge.js
Normal file
41
assets/js/forum-bridge.js
Normal file
@@ -0,0 +1,41 @@
|
||||
(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 ) {
|
||||
$(document).trigger('mc_gallery_forum_verified', [ r.data ]);
|
||||
if ( typeof window.mcGalleryOnVerified === 'function' ) {
|
||||
window.mcGalleryOnVerified( r.data );
|
||||
}
|
||||
$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);
|
||||
@@ -119,16 +119,15 @@
|
||||
function loadAlbums() {
|
||||
const $select = $('#mc-upload-album');
|
||||
$select.html('<option value="">Kein Album</option>').prop('disabled', true);
|
||||
|
||||
if (!sessionData.token || !sessionData.verified) return;
|
||||
|
||||
// Auch ohne Token laden, wenn Forum-Session aktiv
|
||||
if ((!sessionData.token && !sessionData.verified) || !sessionData.username) return;
|
||||
fetch(api + '/albums', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
token: sessionData.token,
|
||||
username: sessionData.username,
|
||||
server_id: sessionData.serverId
|
||||
token: sessionData.token || '',
|
||||
username: sessionData.username,
|
||||
server_id: sessionData.serverId || ''
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
@@ -235,6 +234,23 @@
|
||||
|
||||
resetModal();
|
||||
loadServers();
|
||||
|
||||
// Wenn User bereits forum-verifiziert ist: direkt zu Schritt 3 springen
|
||||
if (mcGalleryPro.forumVerified) {
|
||||
const fv = mcGalleryPro.forumVerified;
|
||||
sessionData.verified = true;
|
||||
sessionData.username = fv.mc_username;
|
||||
sessionData.serverId = fv.server_id;
|
||||
sessionData.token = null;
|
||||
|
||||
$('#mc-session-user').text(fv.display_name || fv.mc_username);
|
||||
$('#mc_form_username').val(fv.mc_username);
|
||||
$('#mc_form_server').val(fv.server_id);
|
||||
$('#mc_form_token').val('');
|
||||
|
||||
switchStep(3);
|
||||
loadAlbums();
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
@@ -245,6 +261,30 @@
|
||||
setTimeout(resetModal, 300);
|
||||
}
|
||||
|
||||
// Forum-Login: Auf globales Event reagieren
|
||||
$(document).on('mc_gallery_forum_verified', function(e, data) {
|
||||
if (!data || !data.mc_username || !data.server_id) {
|
||||
showFeedback('Forum-Login: Ungültige Antwort vom Server.', 'error');
|
||||
return;
|
||||
}
|
||||
sessionData.verified = true;
|
||||
sessionData.username = data.mc_username;
|
||||
sessionData.serverId = data.server_id;
|
||||
sessionData.token = null; // Kein Token nötig
|
||||
|
||||
$('#mc-session-user').text(data.display_name || data.mc_username);
|
||||
$('#mc_form_username').val(data.mc_username);
|
||||
$('#mc_form_server').val(data.server_id);
|
||||
$('#mc_form_token').val('');
|
||||
|
||||
showFeedback('✓ Erfolgreich mit Forum-Login verifiziert!', 'success');
|
||||
setTimeout(() => {
|
||||
switchStep(3);
|
||||
console.log('[MC-Gallery] mc_gallery_forum_verified: switchStep(3) ausgeführt, Upload-Schritt sollte sichtbar sein.');
|
||||
loadAlbums();
|
||||
}, 800);
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
loadServers();
|
||||
@@ -264,6 +304,53 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Forum-Login-Button im Modal (Schritt 1) — einmalig binden, NICHT inside btn-generate
|
||||
$(document).on('click', '#mc-btn-forum-login', function () {
|
||||
const serverId = $('#mc-upload-server').val();
|
||||
if (!serverId || serverId === '') {
|
||||
showFeedback('Bitte wähle einen Server aus.', 'error');
|
||||
return;
|
||||
}
|
||||
const $btn = $(this);
|
||||
const originalText = $btn.html();
|
||||
$btn.prop('disabled', true).html('<span class="mc-loading"></span> Prüfe Forum-Login...');
|
||||
|
||||
$.ajax({
|
||||
url: ajaxUrl,
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
action: 'mc_forum_verify_upload',
|
||||
nonce: mcGalleryPro.forumNonce || mcGalleryPro.nonce,
|
||||
server_id: serverId
|
||||
},
|
||||
success: function (data) {
|
||||
$btn.prop('disabled', false).html(originalText);
|
||||
if (data.success && data.data && data.data.mc_username) {
|
||||
sessionData.verified = true;
|
||||
sessionData.username = data.data.mc_username;
|
||||
sessionData.serverId = data.data.server_id;
|
||||
sessionData.token = null;
|
||||
|
||||
$('#mc-session-user').text(data.data.display_name || data.data.mc_username);
|
||||
$('#mc_form_username').val(data.data.mc_username);
|
||||
$('#mc_form_server').val(data.data.server_id);
|
||||
$('#mc_form_token').val('');
|
||||
|
||||
showFeedback('✓ Erfolgreich mit Forum-Login verifiziert!', 'success');
|
||||
setTimeout(() => { switchStep(3); loadAlbums(); }, 800);
|
||||
} else {
|
||||
const msg = (data.data && data.data.message) ? data.data.message : (data.message || 'Verifizierung fehlgeschlagen.');
|
||||
showFeedback(msg, 'error');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
$btn.prop('disabled', false).html(originalText);
|
||||
showFeedback('Netzwerkfehler bei der Forum-Login-Prüfung', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#mc-btn-generate').on('click', function () {
|
||||
const username = $('#mc-upload-username').val().trim();
|
||||
const serverId = $('#mc-upload-server').val();
|
||||
@@ -432,9 +519,9 @@
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'mc_gallery_create_album');
|
||||
formData.append('mc_upload_nonce', mcGalleryPro.nonce);
|
||||
formData.append('mc_token', sessionData.token);
|
||||
formData.append('mc_token', sessionData.token || '');
|
||||
formData.append('mc_username', sessionData.username);
|
||||
formData.append('mc_server_id', sessionData.serverId);
|
||||
formData.append('mc_server_id', sessionData.serverId || '');
|
||||
formData.append('album_name', albumName);
|
||||
|
||||
fetch(ajaxUrl, {
|
||||
@@ -477,10 +564,16 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Auch ohne Token erlauben, wenn Forum-Session aktiv
|
||||
if (!sessionData.verified || !sessionData.username) {
|
||||
showFeedback('Bitte verifiziere dich zuerst.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'mc_gallery_upload');
|
||||
formData.append('mc_upload_nonce', mcGalleryPro.nonce);
|
||||
formData.append('mc_token', sessionData.token);
|
||||
formData.append('mc_token', sessionData.token || '');
|
||||
formData.append('mc_username', sessionData.username);
|
||||
formData.append('mc_server_id', sessionData.serverId);
|
||||
formData.append('mc_album_id', $('#mc-upload-album').val() || '');
|
||||
@@ -546,6 +639,77 @@
|
||||
$('#mc-upload-file').click();
|
||||
});
|
||||
|
||||
// === VOTE BUTTONS (Daumen hoch / runter) ===
|
||||
if (mcGalleryPro.votingEnabled) {
|
||||
|
||||
// Cookie-Zustand initialisieren
|
||||
function initVoteBtns() {
|
||||
$('.mc-vote-wrap').each(function() {
|
||||
const aid = $(this).data('attach-id');
|
||||
const up = document.cookie.split(';').some(c => c.trim() === 'mc_vote_' + aid + '=up');
|
||||
const down = document.cookie.split(';').some(c => c.trim() === 'mc_vote_' + aid + '=down');
|
||||
if (up) $(this).find('.mc-vote-up').addClass('mc-vote-btn--active');
|
||||
if (down) $(this).find('.mc-vote-down').addClass('mc-vote-btn--active');
|
||||
});
|
||||
}
|
||||
initVoteBtns();
|
||||
|
||||
$(document).on('click', '.mc-vote-btn', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const $btn = $(this);
|
||||
const $wrap = $btn.closest('.mc-vote-wrap');
|
||||
const aid = $wrap.data('attach-id');
|
||||
const nonce = $wrap.data('nonce');
|
||||
const type = $btn.data('type'); // 'up' oder 'down'
|
||||
const ck = 'mc_vote_' + aid;
|
||||
const current = document.cookie.split(';').find(c => c.trim().startsWith(ck + '='));
|
||||
const curVal = current ? current.trim().split('=')[1] : null;
|
||||
|
||||
if ($btn.prop('disabled')) return;
|
||||
$wrap.find('.mc-vote-btn').prop('disabled', true);
|
||||
|
||||
// Toggle-Logik: nochmal klicken = entfernen
|
||||
const isActive = $btn.hasClass('mc-vote-btn--active');
|
||||
const action = isActive ? 'remove' : 'add';
|
||||
|
||||
$.post(ajaxUrl, {
|
||||
action: 'mc_gallery_vote',
|
||||
attach_id: aid,
|
||||
vote_type: type,
|
||||
vote_action: action,
|
||||
nonce: nonce
|
||||
})
|
||||
.done(function(r) {
|
||||
if (r.success) {
|
||||
$wrap.find('.mc-vote-up-count').text(r.data.votes_up);
|
||||
$wrap.find('.mc-vote-down-count').text(r.data.votes_down);
|
||||
|
||||
if (action === 'add') {
|
||||
// Gegenpart deaktivieren falls aktiv
|
||||
const other = type === 'up' ? 'down' : 'up';
|
||||
$wrap.find('.mc-vote-' + other).removeClass('mc-vote-btn--active');
|
||||
$btn.addClass('mc-vote-btn--active');
|
||||
const exp = new Date(); exp.setDate(exp.getDate() + 30);
|
||||
document.cookie = ck + '=' + type + '; expires=' + exp.toUTCString() + '; path=/; SameSite=Lax';
|
||||
} else {
|
||||
$btn.removeClass('mc-vote-btn--active');
|
||||
document.cookie = ck + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
|
||||
}
|
||||
|
||||
// Lightbox-Zähler synchronisieren
|
||||
$('.mc-vote-wrap[data-attach-id="' + aid + '"] .mc-vote-up-count').text(r.data.votes_up);
|
||||
$('.mc-vote-wrap[data-attach-id="' + aid + '"] .mc-vote-down-count').text(r.data.votes_down);
|
||||
}
|
||||
$wrap.find('.mc-vote-btn').prop('disabled', false);
|
||||
})
|
||||
.fail(function() {
|
||||
$wrap.find('.mc-vote-btn').prop('disabled', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// === LIGHTBOX & VIEW COUNT ===
|
||||
$(document).on('click', '.mc-gallery-item', function (e) {
|
||||
e.preventDefault();
|
||||
@@ -566,31 +730,40 @@
|
||||
}
|
||||
|
||||
const player = $item.data('player') || $item.find('.mc-watermark').text().trim();
|
||||
const date = $item.data('date') || '';
|
||||
const album = $item.data('album') || '';
|
||||
const views = $item.data('views') || 0;
|
||||
const date = $item.data('date') || '';
|
||||
const album = $item.data('album') || '';
|
||||
|
||||
const $lightbox = $('<div class="mc-lightbox active"></div>');
|
||||
const $content = $('<div class="mc-lightbox-content"></div>');
|
||||
const $img = $('<img>').attr({
|
||||
'src': href,
|
||||
'alt': player
|
||||
});
|
||||
const $close = $('<button class="mc-lightbox-close" aria-label="Schließen">×</button>');
|
||||
|
||||
const $content = $('<div class="mc-lightbox-content"></div>');
|
||||
const $img = $('<img>').attr({ src: href, alt: player });
|
||||
const $close = $('<button class="mc-lightbox-close" aria-label="Schließen">×</button>');
|
||||
|
||||
// Info-Zeile
|
||||
let infoHtml = '';
|
||||
if (player) infoHtml += `👤 ${player}`;
|
||||
if (date && player) infoHtml += ' • ';
|
||||
if (date) infoHtml += `📅 ${date}`;
|
||||
if (album) infoHtml += ` • 📁 ${album}`;
|
||||
// Views auch in Lightbox zeigen
|
||||
if (views) infoHtml += ' • 👁️ ' + views;
|
||||
|
||||
if (infoHtml) {
|
||||
const $info = $('<div class="mc-lightbox-info"></div>').html(infoHtml);
|
||||
$content.append($info);
|
||||
}
|
||||
|
||||
// Vote-Buttons in Lightbox
|
||||
if (attachId) {
|
||||
const $voteWrap = $item.find('.mc-vote-wrap').clone();
|
||||
if ($voteWrap.length) {
|
||||
$voteWrap.addClass('mc-vote-wrap--lightbox');
|
||||
$content.append($voteWrap);
|
||||
// Cookie-Zustand wiederherstellen
|
||||
const ck = 'mc_vote_' + attachId;
|
||||
const cur = document.cookie.split(';').find(c => c.trim().startsWith(ck + '='));
|
||||
const curV = cur ? cur.trim().split('=')[1] : null;
|
||||
if (curV === 'up') $voteWrap.find('.mc-vote-up').addClass('mc-vote-btn--active');
|
||||
if (curV === 'down') $voteWrap.find('.mc-vote-down').addClass('mc-vote-btn--active');
|
||||
}
|
||||
}
|
||||
|
||||
$content.append($close).append($img);
|
||||
$lightbox.append($content).appendTo('body');
|
||||
|
||||
@@ -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,13 +220,39 @@ 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() {
|
||||
$thumb_h = get_option(self::OPTION_THUMB_H, 200);
|
||||
$resize_pct = get_option(self::OPTION_RESIZE_PCT, 100);
|
||||
$show_date = get_option(self::OPTION_SHOW_DATE, true);
|
||||
$thumb_h = get_option(self::OPTION_THUMB_H, 200);
|
||||
$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))
|
||||
'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'),
|
||||
'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() {
|
||||
@@ -435,38 +574,60 @@ class MC_Gallery_Core {
|
||||
}
|
||||
|
||||
public static function rest_get_albums($req) {
|
||||
$params = $req->get_json_params();
|
||||
$token = sanitize_text_field($params['token'] ?? '');
|
||||
$username = sanitize_text_field($params['username'] ?? '');
|
||||
$server_id = intval($params['server_id'] ?? 0);
|
||||
|
||||
if (!$token || !$username || !$server_id) {
|
||||
return new WP_REST_Response(['success'=>false,'message'=>'Missing data'],400);
|
||||
$params = $req->get_json_params();
|
||||
$token = sanitize_text_field($params['token'] ?? '');
|
||||
$username = sanitize_text_field($params['username'] ?? '');
|
||||
$server_id = sanitize_text_field($params['server_id'] ?? '');
|
||||
|
||||
if (!$username) {
|
||||
return new WP_REST_Response(['success'=>false,'message'=>'Missing username'],400);
|
||||
}
|
||||
|
||||
$tokens = MC_Gallery_Helpers::get_tokens();
|
||||
if (!isset($tokens[$token]) || !$tokens[$token]['claimed'] || $tokens[$token]['claimed_by'] !== $username) {
|
||||
|
||||
// ── 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 (!$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' => []]);
|
||||
}
|
||||
|
||||
$albums = get_posts([
|
||||
'post_type' => 'mc_album',
|
||||
'post_type' => 'mc_album',
|
||||
'posts_per_page' => -1,
|
||||
'meta_key' => 'mc_gallery_id',
|
||||
'meta_value' => $gallery->ID,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
'meta_key' => 'mc_gallery_id',
|
||||
'meta_value' => $gallery->ID,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
|
||||
$out = [];
|
||||
foreach ($albums as $album) {
|
||||
$out[] = [
|
||||
'id' => $album->ID,
|
||||
'id' => $album->ID,
|
||||
'title' => $album->post_title
|
||||
];
|
||||
}
|
||||
@@ -495,30 +656,87 @@ 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.']);
|
||||
}
|
||||
|
||||
$token = sanitize_text_field($_POST['mc_token'] ?? '');
|
||||
$username = sanitize_text_field($_POST['mc_username'] ?? '');
|
||||
$server_id = intval($_POST['mc_server_id'] ?? 0);
|
||||
$album_name = sanitize_text_field($_POST['album_name'] ?? '');
|
||||
|
||||
if (!$token || !$username || !$server_id || !$album_name) {
|
||||
$token = sanitize_text_field($_POST['mc_token'] ?? '');
|
||||
$username = sanitize_text_field($_POST['mc_username'] ?? '');
|
||||
$server_id = sanitize_text_field($_POST['mc_server_id'] ?? '');
|
||||
$album_name = sanitize_text_field($_POST['album_name'] ?? '');
|
||||
|
||||
if (!$username || !$album_name) {
|
||||
wp_send_json_error(['message' => 'Missing data']);
|
||||
}
|
||||
|
||||
$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']);
|
||||
|
||||
// ── 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 && $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.']);
|
||||
}
|
||||
|
||||
$server_id_val = is_numeric($server_id) ? intval($server_id) : $server_id;
|
||||
|
||||
$gallery = MC_Gallery_Helpers::find_or_create_gallery_post($username, $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']);
|
||||
}
|
||||
@@ -551,27 +769,60 @@ class MC_Gallery_Core {
|
||||
wp_send_json_error(['message' => 'Security check failed.']);
|
||||
}
|
||||
|
||||
$token = sanitize_text_field($_POST['mc_token'] ?? '');
|
||||
$username = sanitize_text_field($_POST['mc_username'] ?? '');
|
||||
$server_id = intval($_POST['mc_server_id'] ?? 0);
|
||||
$album_id = intval($_POST['mc_album_id'] ?? 0);
|
||||
|
||||
if (!$token || !$username || !$server_id) {
|
||||
wp_send_json_error(['message' => 'Token or data missing.']);
|
||||
$token = sanitize_text_field($_POST['mc_token'] ?? '');
|
||||
$username = sanitize_text_field($_POST['mc_username'] ?? '');
|
||||
$server_id = sanitize_text_field($_POST['mc_server_id'] ?? '');
|
||||
$album_id = intval($_POST['mc_album_id'] ?? 0);
|
||||
|
||||
if (!$username) {
|
||||
wp_send_json_error(['message' => 'Benutzername fehlt.']);
|
||||
}
|
||||
|
||||
$tokens = MC_Gallery_Helpers::get_tokens();
|
||||
if (!isset($tokens[$token])) {
|
||||
wp_send_json_error(['message' => 'Invalid token.']);
|
||||
|
||||
// ── 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$t = $tokens[$token];
|
||||
if ($t['expires'] < time()) {
|
||||
wp_send_json_error(['message' => 'Session expired.']);
|
||||
|
||||
if (!$authorized) {
|
||||
wp_send_json_error(['message' => 'Nicht autorisiert. Bitte zuerst verifizieren.']);
|
||||
}
|
||||
|
||||
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 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'])) {
|
||||
@@ -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,12 +3,16 @@ 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']);
|
||||
}
|
||||
|
||||
@@ -110,13 +114,15 @@ class MC_Gallery_Shortcodes {
|
||||
$albums = [];
|
||||
if (!empty($player_gallery_ids)) {
|
||||
$albums = get_posts([
|
||||
'post_type' => 'mc_album',
|
||||
'post_type' => 'mc_album',
|
||||
'posts_per_page' => -1,
|
||||
'meta_key' => 'mc_gallery_id',
|
||||
'value' => $player_gallery_ids,
|
||||
'compare' => 'IN',
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
'meta_query' => [[
|
||||
'key' => 'mc_gallery_id',
|
||||
'value' => $player_gallery_ids,
|
||||
'compare' => 'IN',
|
||||
]],
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -128,12 +134,13 @@ class MC_Gallery_Shortcodes {
|
||||
|
||||
foreach ($albums as $album) {
|
||||
$album_images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'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'
|
||||
'post_parent' => get_post_meta($album->ID, 'mc_gallery_id', true),
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
|
||||
$cover_url = '';
|
||||
@@ -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>';
|
||||
@@ -560,6 +570,12 @@ class MC_Gallery_Shortcodes {
|
||||
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',
|
||||
@@ -586,13 +602,14 @@ class MC_Gallery_Shortcodes {
|
||||
$album_count = get_post_meta($album->ID, 'mc_image_count', true) ?: 0;
|
||||
|
||||
$cover_images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'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'
|
||||
'meta_key' => 'mc_album_id',
|
||||
'meta_value' => $album->ID,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
|
||||
$cover_url = '';
|
||||
@@ -645,13 +662,14 @@ class MC_Gallery_Shortcodes {
|
||||
}
|
||||
|
||||
$images = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'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'
|
||||
'meta_key' => 'mc_album_id',
|
||||
'meta_value' => $album_id,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC'
|
||||
]);
|
||||
|
||||
$gallery_id = get_post_meta($album_id, 'mc_gallery_id', true);
|
||||
@@ -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.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
330
mc-multiserver-gallery-pro.php
Normal file
330
mc-multiserver-gallery-pro.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: MC MultiServer Gallery PRO
|
||||
Description: Professionelle Minecraft-Galerie mit Ingame-Verification, modernem UI, Lightbox und AJAX-Upload (multi-server fähig).
|
||||
Version: 2.5.5
|
||||
Author: M_Viper
|
||||
Plugin URI: https://git.viper.ipv64.net/M_Viper/Wordpress-MC-Gallery/releases
|
||||
Author URI: https://m-viper.de
|
||||
Text Domain: mc-multiserver-gallery-pro
|
||||
Domain Path: /languages
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
// ===========================================
|
||||
// MC GALLERY PRO - UPDATE NOTICE SYSTEM
|
||||
// ===========================================
|
||||
|
||||
// Plugin-Version aus Header lesen (NICHT aus Konstante)
|
||||
function mc_gallery_get_plugin_version() {
|
||||
if ( ! function_exists( 'get_plugin_data' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$plugin_data = get_plugin_data( __FILE__ );
|
||||
return $plugin_data['Version'] ?? '0.0.0';
|
||||
}
|
||||
|
||||
// Cache manuell leeren
|
||||
function mc_gallery_clear_update_cache() {
|
||||
if ( isset($_GET['mc_gallery_clear_cache']) && current_user_can('manage_options') ) {
|
||||
check_admin_referer('mc_gallery_clear_cache_action');
|
||||
delete_transient('mc_gallery_latest_release');
|
||||
wp_redirect( admin_url('plugins.php') );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
add_action('admin_init', 'mc_gallery_clear_update_cache');
|
||||
|
||||
// Neueste Release-Infos von Gitea holen
|
||||
function mc_gallery_get_latest_release_info( $force_refresh = false ) {
|
||||
$transient_key = 'mc_gallery_latest_release';
|
||||
|
||||
if ( $force_refresh ) {
|
||||
delete_transient( $transient_key );
|
||||
}
|
||||
|
||||
$release_info = get_transient( $transient_key );
|
||||
|
||||
if ( false === $release_info ) {
|
||||
$response = wp_remote_get(
|
||||
'https://git.viper.ipv64.net/api/v1/repos/M_Viper/Wordpress-MC-Gallery/releases/latest',
|
||||
['timeout' => 10]
|
||||
);
|
||||
|
||||
if ( ! is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response) ) {
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$data = json_decode($body, true);
|
||||
|
||||
if ( $data && isset($data['tag_name']) ) {
|
||||
$tag = ltrim( $data['tag_name'], 'vV' );
|
||||
|
||||
$release_info = [
|
||||
'version' => $tag,
|
||||
'download_url' => $data['zipball_url'] ?? '',
|
||||
'notes' => $data['body'] ?? '',
|
||||
'published_at' => $data['published_at'] ?? '',
|
||||
];
|
||||
|
||||
set_transient( $transient_key, $release_info, 6 * HOUR_IN_SECONDS );
|
||||
} else {
|
||||
set_transient( $transient_key, [], HOUR_IN_SECONDS );
|
||||
}
|
||||
} else {
|
||||
set_transient( $transient_key, [], HOUR_IN_SECONDS );
|
||||
}
|
||||
}
|
||||
|
||||
return $release_info;
|
||||
}
|
||||
|
||||
// Admin-Update-Hinweis anzeigen
|
||||
function mc_gallery_show_update_notice() {
|
||||
if ( ! current_user_can('manage_options') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_version = mc_gallery_get_plugin_version();
|
||||
$latest_release = mc_gallery_get_latest_release_info();
|
||||
|
||||
if ( ! empty($latest_release['version']) && version_compare($current_version, $latest_release['version'], '<') ) {
|
||||
|
||||
$refresh_url = wp_nonce_url(
|
||||
admin_url('plugins.php?mc_gallery_clear_cache=1'),
|
||||
'mc_gallery_clear_cache_action'
|
||||
);
|
||||
?>
|
||||
<div class="notice notice-warning is-dismissible">
|
||||
<h3>MC MultiServer Gallery PRO – Update verfügbar</h3>
|
||||
<p>
|
||||
Installiert: <strong><?php echo esc_html($current_version); ?></strong><br>
|
||||
Neueste Version: <strong><?php echo esc_html($latest_release['version']); ?></strong>
|
||||
</p>
|
||||
<p>
|
||||
<a href="<?php echo esc_url($latest_release['download_url']); ?>" class="button button-primary" target="_blank">
|
||||
Update herunterladen
|
||||
</a>
|
||||
<a href="https://git.viper.ipv64.net/M_Viper/Wordpress-MC-Gallery/releases" class="button" target="_blank">
|
||||
Release Notes
|
||||
</a>
|
||||
<a href="<?php echo esc_url($refresh_url); ?>" class="button">
|
||||
Jetzt neu prüfen
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
add_action('admin_notices', 'mc_gallery_show_update_notice');
|
||||
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.0', '<')) {
|
||||
if (is_admin()) {
|
||||
add_action('admin_notices', function() {
|
||||
echo '<div class="error"><p><strong>MC Gallery PRO:</strong> Dieses Plugin benötigt PHP 7.0 oder höher.</p></div>';
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (defined('MCGALLERY_PRO_VERSION')) { return; }
|
||||
|
||||
define('MCGALLERY_PRO_VERSION', '2.5.4');
|
||||
define('MCGALLERY_PRO_DIR', plugin_dir_path(__FILE__));
|
||||
define('MCGALLERY_PRO_URL', plugin_dir_url(__FILE__));
|
||||
define('MCGALLERY_TOKEN_TTL', 300);
|
||||
define('MCGALLERY_OPTION_KEY', 'mc_gallery_tokens_store');
|
||||
|
||||
function mc_gallery_pro_safe_require($path) {
|
||||
if (!file_exists($path)) {
|
||||
if (is_admin()) {
|
||||
add_action('admin_notices', function() use ($path) {
|
||||
echo '<div class="error"><p><strong>MC Gallery PRO Fehler:</strong> Datei nicht gefunden: <code>' . esc_html($path) . '</code>.</p></div>';
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
require_once $path;
|
||||
return true;
|
||||
}
|
||||
|
||||
function mc_gallery_pro_load_textdomain() {
|
||||
load_plugin_textdomain('mc-multiserver-gallery-pro', false, basename(dirname(__FILE__)) . '/languages');
|
||||
}
|
||||
add_action('plugins_loaded', 'mc_gallery_pro_load_textdomain');
|
||||
|
||||
$core_files = [
|
||||
'class-mc-gallery-helpers.php',
|
||||
'class-mc-gallery-core.php',
|
||||
'class-mc-gallery-shortcodes.php',
|
||||
];
|
||||
|
||||
if (!is_dir(MCGALLERY_PRO_DIR . 'includes')) {
|
||||
add_action('admin_notices', function() {
|
||||
echo '<div class="error"><p><strong>MC Gallery PRO Fehler:</strong> Der Ordner <code>includes/</code> fehlt.</p></div>';
|
||||
});
|
||||
} else {
|
||||
foreach ($core_files as $file) {
|
||||
if (!mc_gallery_pro_safe_require(MCGALLERY_PRO_DIR . 'includes/' . $file)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ── WP Business Forum — optionale Bridge ─────────────────────────────────
|
||||
// Wird nur geladen wenn das Forum-Plugin ebenfalls aktiv ist.
|
||||
// Keine harte Abhängigkeit — Gallery funktioniert ohne Forum genauso wie vorher.
|
||||
add_action('plugins_loaded', function() {
|
||||
$bridge_file = MCGALLERY_PRO_DIR . 'includes/class-mc-gallery-forum-bridge.php';
|
||||
if ( file_exists($bridge_file) && class_exists('WBF_Auth') ) {
|
||||
require_once $bridge_file;
|
||||
MC_Gallery_Forum_Bridge::init();
|
||||
|
||||
// Shortcode für manuelles Einbetten des Verify-Panels auf beliebigen Seiten:
|
||||
// [mc_gallery_forum_login server_id="survival"]
|
||||
add_shortcode('mc_gallery_forum_login', ['MC_Gallery_Forum_Bridge', 'shortcode_verify_panel']);
|
||||
}
|
||||
}, 20); // Prio 20 → nach Forum (Prio 1) und Gallery-Core (Prio 10)
|
||||
}
|
||||
|
||||
// ── Aktivierungs- / Deinstallations-Hooks ────────────────────────────────────
|
||||
|
||||
function mc_gallery_pro_activate_callback() {
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
if (!get_option(MC_Gallery_Core::OPTION_THUMB_H)) {
|
||||
update_option(MC_Gallery_Core::OPTION_THUMB_H, 200);
|
||||
}
|
||||
}
|
||||
if (get_option(MCGALLERY_OPTION_KEY) === false) {
|
||||
update_option(MCGALLERY_OPTION_KEY, []);
|
||||
}
|
||||
}
|
||||
register_activation_hook(__FILE__, 'mc_gallery_pro_activate_callback');
|
||||
|
||||
function mc_gallery_pro_uninstall_callback() {
|
||||
delete_option(MCGALLERY_OPTION_KEY);
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
delete_option(MC_Gallery_Core::OPTION_THUMB_H);
|
||||
}
|
||||
}
|
||||
register_uninstall_hook(__FILE__, 'mc_gallery_pro_uninstall_callback');
|
||||
|
||||
// ── Core-Klassen initialisieren ───────────────────────────────────────────────
|
||||
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
add_action('plugins_loaded', ['MC_Gallery_Core', 'init']);
|
||||
}
|
||||
if (class_exists('MC_Gallery_Shortcodes')) {
|
||||
add_action('plugins_loaded', ['MC_Gallery_Shortcodes', 'init']);
|
||||
}
|
||||
|
||||
/* ================= SIDEBAR WIDGET: BILD DES TAGES ================= */
|
||||
class MC_Daily_Image_Widget extends WP_Widget {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
'mc_daily_image_widget',
|
||||
'MC Bild des Tages',
|
||||
array( 'description' => 'Zeigt jeden Tag ein anderes, zufälliges Bild aus allen MC Galerien an.' )
|
||||
);
|
||||
}
|
||||
|
||||
// Frontend-Ausgabe
|
||||
public function widget( $args, $instance ) {
|
||||
$title = ! empty( $instance['title'] ) ? $instance['title'] : 'Bild des Tages';
|
||||
|
||||
echo $args['before_widget'];
|
||||
if ( ! empty( $title ) ) {
|
||||
echo $args['before_title'] . apply_filters( 'widget_title', $title ) . $args['after_title'];
|
||||
}
|
||||
|
||||
// 1. Eindeutiger Key für heute (z.B. mc_daily_image_2023-10-27)
|
||||
$today_key = 'mc_daily_image_' . date('Y-m-d');
|
||||
|
||||
// 2. Prüfen, ob wir heute schon ein Bild ausgewählt haben
|
||||
$image_id = get_transient( $today_key );
|
||||
|
||||
// Falls kein Bild für heute im Cache ist:
|
||||
if ( false === $image_id ) {
|
||||
|
||||
// Alle MC Galerien finden
|
||||
$galleries = get_posts([
|
||||
'post_type' => 'mc_gallery',
|
||||
'numberposts' => -1,
|
||||
'fields' => 'ids',
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
if ( ! empty( $galleries ) ) {
|
||||
// Ein zufälliges Bild aus diesen Galerien holen
|
||||
$random_image = get_posts([
|
||||
'post_type' => 'attachment',
|
||||
'post_mime_type' => 'image',
|
||||
'post_parent__in' => $galleries,
|
||||
'numberposts' => 1,
|
||||
'orderby' => 'rand',
|
||||
'suppress_filters' => false,
|
||||
]);
|
||||
|
||||
if ( ! empty( $random_image ) ) {
|
||||
$image_id = $random_image[0]->ID;
|
||||
// Das Bild für 24 Stunden (bis morgen) speichern
|
||||
set_transient( $today_key, $image_id, DAY_IN_SECONDS );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Bild anzeigen (wird aus Cache oder neu geladen)
|
||||
if ( $image_id && wp_attachment_is_image( $image_id ) ) {
|
||||
|
||||
$img_src = wp_get_attachment_image_src( $image_id, 'medium' );
|
||||
$full_src = wp_get_attachment_image_src( $image_id, 'full' );
|
||||
|
||||
if ( $img_src ) {
|
||||
?>
|
||||
<div class="mc-daily-image-container" style="text-align: center;">
|
||||
<a href="<?php echo esc_url( $full_src[0] ); ?>" target="_blank" title="Vollbild anzeigen">
|
||||
<img src="<?php echo esc_url( $img_src[0] ); ?>" alt="MC Bild des Tages"
|
||||
style="max-width: 100%; height: auto; border-radius: 4px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);" />
|
||||
</a>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
echo '<p style="text-align:center; color:#888;">Keine Bilder verfügbar.</p>';
|
||||
}
|
||||
|
||||
echo $args['after_widget'];
|
||||
}
|
||||
|
||||
// Backend Formular
|
||||
public function form( $instance ) {
|
||||
$title = ! empty( $instance['title'] ) ? $instance['title'] : 'Bild des Tages';
|
||||
?>
|
||||
<p>
|
||||
<label for="<?php echo $this->get_field_id( 'title' ); ?>">Titel:</label>
|
||||
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>"
|
||||
name="<?php echo $this->get_field_name( 'title' ); ?>" type="text"
|
||||
value="<?php echo esc_attr( $title ); ?>">
|
||||
</p>
|
||||
<p class="description" style="font-size: 0.9em; color: #666;">
|
||||
Dieses Widget wählt einmal pro Tag (um 00:00 Uhr) ein zufälliges Bild aus allen Spieler-Galerien aus und zeigt es an. Der Bildtext ist ausgeblendet.
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Speichern der Einstellungen
|
||||
public function update( $new_instance, $old_instance ) {
|
||||
$instance = array();
|
||||
$instance['title'] = ( ! empty( $new_instance['title'] ) )
|
||||
? sanitize_text_field( $new_instance['title'] )
|
||||
: 'Bild des Tages';
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
|
||||
// Widget registrieren
|
||||
function mc_register_daily_image_widget() {
|
||||
register_widget( 'MC_Daily_Image_Widget' );
|
||||
}
|
||||
add_action( 'widgets_init', 'mc_register_daily_image_widget' );
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
Plugin Name: MC MultiServer Gallery PRO
|
||||
Description: Professionelle Minecraft-Galerie mit Ingame-Verification, modernem UI, Lightbox und AJAX-Upload (multi-server fähig).
|
||||
Version: 2.5.2
|
||||
Author: M_Viper
|
||||
Text Domain: mc-multiserver-gallery-pro
|
||||
Domain Path: /languages
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.0', '<')) {
|
||||
if (is_admin()) {
|
||||
add_action('admin_notices', function() {
|
||||
echo '<div class="error"><p><strong>MC Gallery PRO:</strong> Dieses Plugin benötigt PHP 7.0 oder höher.</p></div>';
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (defined('MCGALLERY_PRO_VERSION')) { return; }
|
||||
|
||||
define('MCGALLERY_PRO_VERSION', '2.5.2');
|
||||
define('MCGALLERY_PRO_DIR', plugin_dir_path(__FILE__));
|
||||
define('MCGALLERY_PRO_URL', plugin_dir_url(__FILE__));
|
||||
define('MCGALLERY_TOKEN_TTL', 300);
|
||||
define('MCGALLERY_OPTION_KEY', 'mc_gallery_tokens_store');
|
||||
|
||||
function mc_gallery_pro_safe_require($path) {
|
||||
if (!file_exists($path)) {
|
||||
if (is_admin()) {
|
||||
add_action('admin_notices', function() use ($path) {
|
||||
echo '<div class="error"><p><strong>MC Gallery PRO Fehler:</strong> Datei nicht gefunden: <code>' . esc_html($path) . '</code>.</p></div>';
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
require_once $path;
|
||||
return true;
|
||||
}
|
||||
|
||||
function mc_gallery_pro_load_textdomain() {
|
||||
load_plugin_textdomain('mc-multiserver-gallery-pro', false, basename(dirname(__FILE__)) . '/languages');
|
||||
}
|
||||
add_action('plugins_loaded', 'mc_gallery_pro_load_textdomain');
|
||||
|
||||
$core_files = [
|
||||
'class-mc-gallery-helpers.php',
|
||||
'class-mc-gallery-core.php',
|
||||
'class-mc-gallery-shortcodes.php'
|
||||
];
|
||||
|
||||
if (!is_dir(MCGALLERY_PRO_DIR . 'includes')) {
|
||||
add_action('admin_notices', function() {
|
||||
echo '<div class="error"><p><strong>MC Gallery PRO Fehler:</strong> Der Ordner <code>includes/</code> fehlt.</p></div>';
|
||||
});
|
||||
} else {
|
||||
foreach ($core_files as $file) {
|
||||
if (!mc_gallery_pro_safe_require(MCGALLERY_PRO_DIR . 'includes/' . $file)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mc_gallery_pro_activate_callback() {
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
if (!get_option(MC_Gallery_Core::OPTION_THUMB_H)) {
|
||||
update_option(MC_Gallery_Core::OPTION_THUMB_H, 200);
|
||||
}
|
||||
}
|
||||
if (get_option(MCGALLERY_OPTION_KEY) === false) {
|
||||
update_option(MCGALLERY_OPTION_KEY, []);
|
||||
}
|
||||
}
|
||||
register_activation_hook(__FILE__, 'mc_gallery_pro_activate_callback');
|
||||
|
||||
function mc_gallery_pro_uninstall_callback() {
|
||||
delete_option(MCGALLERY_OPTION_KEY);
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
delete_option(MC_Gallery_Core::OPTION_THUMB_H);
|
||||
}
|
||||
}
|
||||
register_uninstall_hook(__FILE__, 'mc_gallery_pro_uninstall_callback');
|
||||
|
||||
if (class_exists('MC_Gallery_Core')) {
|
||||
add_action('plugins_loaded', ['MC_Gallery_Core', 'init']);
|
||||
}
|
||||
if (class_exists('MC_Gallery_Shortcodes')) {
|
||||
add_action('plugins_loaded', ['MC_Gallery_Shortcodes', 'init']);
|
||||
}
|
||||
Reference in New Issue
Block a user