Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0bec83593 | |||
| 7ef72641f6 | |||
| c4c02c1b9d | |||
| 0ab87297ac |
@@ -144,4 +144,10 @@ Die StatusAPI muss auf deinem Minecraft-Bungeecord laufen, um die Kommunikation
|
||||
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.
|
||||
@@ -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.']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,306 +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.4
|
||||
Author: M_Viper
|
||||
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.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']);
|
||||
}
|
||||
|
||||
/* ================= 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', // Zufällig wählen
|
||||
'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' );
|
||||
}
|
||||
<?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' );
|
||||
Reference in New Issue
Block a user