Upload folder via GUI - includes
This commit is contained in:
@@ -49,6 +49,30 @@ class WBF_Abo {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Item-Abos aus WordPress DB (wis_item_abo_subs)
|
||||||
|
$item_abos = $wpdb->get_results( $wpdb->prepare(
|
||||||
|
"SELECT id, label, item_id, daily_qty, cancelled,
|
||||||
|
DATE_FORMAT(expires_at, '%%d.%%m.%%Y') AS expires_at_fmt
|
||||||
|
FROM {$wpdb->prefix}wis_item_abo_subs
|
||||||
|
WHERE player_name = %s
|
||||||
|
AND status = 'active'
|
||||||
|
AND expires_at > NOW()
|
||||||
|
ORDER BY created_at ASC",
|
||||||
|
$mc_name
|
||||||
|
), ARRAY_A );
|
||||||
|
|
||||||
|
if ( $item_abos ) {
|
||||||
|
foreach ( $item_abos as &$row ) {
|
||||||
|
$row['id'] = (int) $row['id'];
|
||||||
|
$row['daily_qty'] = (int) $row['daily_qty'];
|
||||||
|
$row['cancelled'] = (bool) $row['cancelled'];
|
||||||
|
}
|
||||||
|
unset($row);
|
||||||
|
$result['item_abos'] = $item_abos;
|
||||||
|
} else {
|
||||||
|
$result['item_abos'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
// Spigot MySQL für Fly-Usage + Plot-Daten
|
// Spigot MySQL für Fly-Usage + Plot-Daten
|
||||||
$conn = self::get_spigot_db();
|
$conn = self::get_spigot_db();
|
||||||
if ( $conn ) {
|
if ( $conn ) {
|
||||||
@@ -78,7 +102,7 @@ class WBF_Abo {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function cancel_abo( string $mc_name, string $type ): bool {
|
public static function cancel_abo( string $mc_name, string $type, int $abo_id = 0 ): bool {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
if ( $type === 'fly_abo' ) {
|
if ( $type === 'fly_abo' ) {
|
||||||
$rows = $wpdb->update(
|
$rows = $wpdb->update(
|
||||||
@@ -97,6 +121,22 @@ class WBF_Abo {
|
|||||||
$a = $stmt->affected_rows; $stmt->close(); $conn->close();
|
$a = $stmt->affected_rows; $stmt->close(); $conn->close();
|
||||||
return $a > 0;
|
return $a > 0;
|
||||||
}
|
}
|
||||||
|
if ( $type === 'item_abo' ) {
|
||||||
|
if ( $abo_id <= 0 ) return false;
|
||||||
|
// Sicherheitscheck: Abo muss dem Spieler gehören
|
||||||
|
$existing = $wpdb->get_row( $wpdb->prepare(
|
||||||
|
"SELECT id, label FROM {$wpdb->prefix}wis_item_abo_subs
|
||||||
|
WHERE id = %d AND player_name = %s AND status = 'active' AND cancelled = 0",
|
||||||
|
$abo_id, $mc_name
|
||||||
|
) );
|
||||||
|
if ( ! $existing ) return false;
|
||||||
|
$rows = $wpdb->update(
|
||||||
|
$wpdb->prefix . 'wis_item_abo_subs',
|
||||||
|
['cancelled' => 1, 'cancelled_at' => current_time('mysql')],
|
||||||
|
['id' => $abo_id]
|
||||||
|
);
|
||||||
|
return $rows > 0;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +150,7 @@ class WBF_Abo {
|
|||||||
$abos = self::get_all_abos($mc_name);
|
$abos = self::get_all_abos($mc_name);
|
||||||
$fly_abo = $abos['fly_abo'] ?? null;
|
$fly_abo = $abos['fly_abo'] ?? null;
|
||||||
$plot_abo = $abos['plot_abo'] ?? null;
|
$plot_abo = $abos['plot_abo'] ?? null;
|
||||||
|
$item_abos = $abos['item_abos'] ?? [];
|
||||||
$plot_extra = (int)($abos['plot_extra'] ?? 0);
|
$plot_extra = (int)($abos['plot_extra'] ?? 0);
|
||||||
$fly_used = (int)($abos['fly_used_sec'] ?? 0);
|
$fly_used = (int)($abos['fly_used_sec'] ?? 0);
|
||||||
$fly_max = (int) get_option('wis_fly_abo_max_daily_hours', 6) * 3600;
|
$fly_max = (int) get_option('wis_fly_abo_max_daily_hours', 6) * 3600;
|
||||||
@@ -117,7 +158,7 @@ class WBF_Abo {
|
|||||||
$shop_url = esc_url(get_option('wis_shop_url', home_url('/ingame-shop/')));
|
$shop_url = esc_url(get_option('wis_shop_url', home_url('/ingame-shop/')));
|
||||||
$nonce = wp_create_nonce('wbf_nonce');
|
$nonce = wp_create_nonce('wbf_nonce');
|
||||||
$ajax_url = admin_url('admin-ajax.php');
|
$ajax_url = admin_url('admin-ajax.php');
|
||||||
$has_any = $fly_abo || $plot_abo || $plot_extra > 0;
|
$has_any = $fly_abo || $plot_abo || $plot_extra > 0 || !empty($item_abos);
|
||||||
|
|
||||||
ob_start(); ?>
|
ob_start(); ?>
|
||||||
<style>
|
<style>
|
||||||
@@ -306,8 +347,66 @@ class WBF_Abo {
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; // plot_abo ?>
|
<?php endif; // plot_abo ?>
|
||||||
|
|
||||||
|
<?php /* ITEM-ABOS */ foreach ($item_abos as $idx => $ia):
|
||||||
|
$ia_nr = $idx + 1;
|
||||||
|
$ia_id = (int) $ia['id'];
|
||||||
|
$ia_label = $ia['label'] ?? 'Item-Abo';
|
||||||
|
$ia_item = $ia['item_id'] ?? '?';
|
||||||
|
$ia_qty = (int)($ia['daily_qty'] ?? 1);
|
||||||
|
$ia_expires = $ia['expires_at_fmt'] ?? '?';
|
||||||
|
$ia_cancelled = !empty($ia['cancelled']);
|
||||||
|
?>
|
||||||
|
<div class="wbf-abo-item <?php echo $ia_cancelled ? 'wbf-abo-item--cancelled' : 'wbf-abo-item--active'; ?>" id="wbf-abo-item-<?php echo $ia_id; ?>">
|
||||||
|
<div class="wbf-abo-item__head">
|
||||||
|
<div class="wbf-abo-item__icon-wrap">📦</div>
|
||||||
|
<div class="wbf-abo-item__info">
|
||||||
|
<div class="wbf-abo-item__name"><?php echo esc_html($ia_label); ?></div>
|
||||||
|
<div class="wbf-abo-item__price"><?php echo $ia_qty; ?>× täglich · <code style="font-size:.78rem;opacity:.8"><?php echo esc_html($ia_item); ?></code></div>
|
||||||
|
</div>
|
||||||
|
<div class="wbf-abo-item__status">
|
||||||
|
<?php if ($ia_cancelled): ?>
|
||||||
|
<span class="wbf-abo-badge wbf-abo-badge--cancelled"><i class="fas fa-clock"></i> Gekündigt</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="wbf-abo-badge wbf-abo-badge--active"><i class="fas fa-circle-check"></i> Aktiv</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wbf-abo-item__body">
|
||||||
|
<div class="wbf-abo-grid">
|
||||||
|
<div class="wbf-abo-grid__item">
|
||||||
|
<span class="wbf-abo-grid__label"><i class="fas fa-calendar-day"></i> Läuft bis</span>
|
||||||
|
<span class="wbf-abo-grid__value <?php echo $ia_cancelled ? 'wbf-abo-grid__value--warn' : ''; ?>"><?php echo esc_html($ia_expires); ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="wbf-abo-grid__item">
|
||||||
|
<span class="wbf-abo-grid__label"><i class="fas fa-box-open"></i> Tageslieferung</span>
|
||||||
|
<span class="wbf-abo-grid__value"><?php echo $ia_qty; ?>× <?php echo esc_html($ia_item); ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php if (!$ia_cancelled): ?>
|
||||||
|
<div class="wbf-abo-item__foot">
|
||||||
|
<button class="wbf-btn wbf-btn--danger wbf-btn--sm wbf-abo-cancel-btn"
|
||||||
|
data-type="item_abo"
|
||||||
|
data-abo-id="<?php echo $ia_id; ?>"
|
||||||
|
data-nonce="<?php echo $nonce; ?>"
|
||||||
|
data-label="<?php echo esc_attr($ia_label); ?>"
|
||||||
|
data-period="<?php echo esc_attr($ia_expires); ?>">
|
||||||
|
<i class="fas fa-xmark"></i> Kündigen
|
||||||
|
</button>
|
||||||
|
<span class="wbf-abo-item__hint">Bleibt bis <?php echo esc_html($ia_expires); ?> aktiv</span>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="wbf-abo-item__foot wbf-abo-item__foot--cancelled">
|
||||||
|
<div class="wbf-abo-notice wbf-abo-notice--info">
|
||||||
|
<i class="fas fa-circle-info"></i>
|
||||||
|
Kündigung vorgemerkt – Lieferungen laufen bis <strong><?php echo esc_html($ia_expires); ?></strong> weiter.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; // item_abos ?>
|
||||||
|
|
||||||
<?php if ($plot_extra > 0 || $plot_abo): ?>
|
<?php if ($plot_extra > 0 || $plot_abo): ?>
|
||||||
<div class="wbf-abo-item wbf-abo-item--info">
|
|
||||||
<div class="wbf-abo-item__head">
|
<div class="wbf-abo-item__head">
|
||||||
<div class="wbf-abo-item__icon-wrap">🗺️</div>
|
<div class="wbf-abo-item__icon-wrap">🗺️</div>
|
||||||
<div class="wbf-abo-item__info">
|
<div class="wbf-abo-item__info">
|
||||||
@@ -363,7 +462,7 @@ class WBF_Abo {
|
|||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
var AJAX = <?php echo json_encode($ajax_url); ?>;
|
var AJAX = <?php echo json_encode($ajax_url); ?>;
|
||||||
var p = {type:null, nonce:null, btn:null};
|
var p = {type:null, nonce:null, btn:null, aboId:0};
|
||||||
var modal = document.getElementById('wbf-abo-modal');
|
var modal = document.getElementById('wbf-abo-modal');
|
||||||
var yesBtn = document.getElementById('wbf-abo-modal-yes');
|
var yesBtn = document.getElementById('wbf-abo-modal-yes');
|
||||||
var noBtn = document.getElementById('wbf-abo-modal-no');
|
var noBtn = document.getElementById('wbf-abo-modal-no');
|
||||||
@@ -371,7 +470,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
document.querySelectorAll('.wbf-abo-cancel-btn').forEach(function(b) {
|
document.querySelectorAll('.wbf-abo-cancel-btn').forEach(function(b) {
|
||||||
b.addEventListener('click', function(e) {
|
b.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
p = {type:b.dataset.type, nonce:b.dataset.nonce, btn:b};
|
p = {type:b.dataset.type, nonce:b.dataset.nonce, btn:b, aboId:parseInt(b.dataset.aboId||'0',10)};
|
||||||
document.getElementById('wbf-abo-modal-label').textContent = b.dataset.label || 'dieses Abo';
|
document.getElementById('wbf-abo-modal-label').textContent = b.dataset.label || 'dieses Abo';
|
||||||
document.getElementById('wbf-abo-modal-period').textContent = b.dataset.period || '';
|
document.getElementById('wbf-abo-modal-period').textContent = b.dataset.period || '';
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
@@ -389,15 +488,23 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
yesBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Kündigen…';
|
yesBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Kündigen…';
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
|
var params = {action:'wbf_cancel_abo', nonce:p.nonce, type:p.type};
|
||||||
|
if (p.type === 'item_abo' && p.aboId > 0) params.abo_id = p.aboId;
|
||||||
|
|
||||||
fetch(AJAX, {
|
fetch(AJAX, {
|
||||||
method:'POST',
|
method:'POST',
|
||||||
headers:{'Content-Type':'application/x-www-form-urlencoded'},
|
headers:{'Content-Type':'application/x-www-form-urlencoded'},
|
||||||
body: new URLSearchParams({action:'wbf_cancel_abo', nonce:p.nonce, type:p.type}).toString()
|
body: new URLSearchParams(params).toString()
|
||||||
})
|
})
|
||||||
.then(function(r){return r.json();})
|
.then(function(r){return r.json();})
|
||||||
.then(function(res) {
|
.then(function(res) {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
var card = document.getElementById(p.type==='fly_abo'?'wbf-abo-fly':'wbf-abo-plot');
|
var card;
|
||||||
|
if (p.type === 'item_abo') {
|
||||||
|
card = p.aboId > 0 ? document.getElementById('wbf-abo-item-'+p.aboId) : null;
|
||||||
|
} else {
|
||||||
|
card = document.getElementById(p.type==='fly_abo'?'wbf-abo-fly':'wbf-abo-plot');
|
||||||
|
}
|
||||||
if (card) {
|
if (card) {
|
||||||
card.classList.replace('wbf-abo-item--active','wbf-abo-item--cancelled');
|
card.classList.replace('wbf-abo-item--active','wbf-abo-item--cancelled');
|
||||||
var badge = card.querySelector('.wbf-abo-badge');
|
var badge = card.querySelector('.wbf-abo-badge');
|
||||||
@@ -412,13 +519,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert((res.data&&res.data.message)?res.data.message:'Fehler beim Kündigen.\nAlternativ: /flyabocancel confirm ingame');
|
alert((res.data&&res.data.message)?res.data.message:'Fehler beim Kündigen.');
|
||||||
}
|
}
|
||||||
yesBtn.disabled=false;
|
yesBtn.disabled=false;
|
||||||
yesBtn.innerHTML='<i class="fas fa-xmark"></i> Ja, kündigen';
|
yesBtn.innerHTML='<i class="fas fa-xmark"></i> Ja, kündigen';
|
||||||
p={type:null,nonce:null,btn:null};
|
p={type:null,nonce:null,btn:null,aboId:0};
|
||||||
})
|
})
|
||||||
.catch(function(){ alert('Verbindungsfehler. Bitte ingame kündigen.'); yesBtn.disabled=false; p={type:null,nonce:null,btn:null}; });
|
.catch(function(){ alert('Verbindungsfehler. Bitte ingame kündigen.'); yesBtn.disabled=false; p={type:null,nonce:null,btn:null,aboId:0}; });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1846,11 +1846,21 @@ class WBF_Ajax {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$type = sanitize_key($_POST['type'] ?? '');
|
$type = sanitize_key($_POST['type'] ?? '');
|
||||||
if ( ! in_array($type, ['fly_abo', 'plot_abo'], true) ) {
|
if ( ! in_array($type, ['fly_abo', 'plot_abo', 'item_abo'], true) ) {
|
||||||
wp_send_json_error(['message' => 'Ungültiger Abo-Typ.']);
|
wp_send_json_error(['message' => 'Ungültiger Abo-Typ.']);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bei item_abo: abo_id pflichtfeld
|
||||||
|
$abo_id = 0;
|
||||||
|
if ( $type === 'item_abo' ) {
|
||||||
|
$abo_id = (int)($_POST['abo_id'] ?? 0);
|
||||||
|
if ( $abo_id <= 0 ) {
|
||||||
|
wp_send_json_error(['message' => 'Abo-ID fehlt oder ungültig.']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MC-Name ermitteln (Spielername = Forum-Username oder verknüpfter MC-Name)
|
// MC-Name ermitteln (Spielername = Forum-Username oder verknüpfter MC-Name)
|
||||||
$mc_name = '';
|
$mc_name = '';
|
||||||
if ( class_exists('WBF_MC_Bridge') ) {
|
if ( class_exists('WBF_MC_Bridge') ) {
|
||||||
@@ -1866,7 +1876,7 @@ class WBF_Ajax {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ok = WBF_Abo::cancel_abo($mc_name, $type);
|
$ok = WBF_Abo::cancel_abo($mc_name, $type, $abo_id);
|
||||||
|
|
||||||
if ($ok) {
|
if ($ok) {
|
||||||
wp_send_json_success(['message' => 'Abo erfolgreich gekündigt.']);
|
wp_send_json_success(['message' => 'Abo erfolgreich gekündigt.']);
|
||||||
|
|||||||
Reference in New Issue
Block a user