Upload via Git Manager GUI
This commit is contained in:
@@ -243,6 +243,18 @@ class WIS_Activator {
|
||||
$wpdb->query("ALTER TABLE $table ADD COLUMN sell_price_value int(11) NOT NULL DEFAULT 80 AFTER sell_price_mode");
|
||||
}
|
||||
|
||||
// Gift-Spalte nachrüsten (ab v6.5-gift)
|
||||
$orders_table = $wpdb->prefix . 'wis_orders';
|
||||
$col_gift = $wpdb->get_var("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '$orders_table' AND COLUMN_NAME = 'gift_recipient'");
|
||||
if (!$col_gift) {
|
||||
$wpdb->query("ALTER TABLE $orders_table ADD COLUMN gift_recipient varchar(100) DEFAULT NULL AFTER player_name");
|
||||
}
|
||||
|
||||
// Auto-Expire Cron registrieren (7-Tage-Ablauf für unbestätigte Orders)
|
||||
if (!wp_next_scheduled('wis_auto_expire_orders')) {
|
||||
wp_schedule_event(time(), 'hourly', 'wis_auto_expire_orders');
|
||||
}
|
||||
|
||||
// Sell-Log-Tabelle anlegen
|
||||
$wpdb->query("CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wis_sell_log (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
@@ -278,6 +290,7 @@ class WIS_Activator {
|
||||
public static function deactivate() {
|
||||
wp_clear_scheduled_hook('wis_daily_deal_event');
|
||||
wp_clear_scheduled_hook('wis_abo_renewal_event');
|
||||
wp_clear_scheduled_hook('wis_auto_expire_orders');
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
@@ -312,6 +325,7 @@ class WIS_Activator {
|
||||
$tables[] = "CREATE TABLE {$wpdb->prefix}wis_orders (
|
||||
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
||||
player_name varchar(100) NOT NULL,
|
||||
gift_recipient varchar(100) DEFAULT NULL,
|
||||
server varchar(100) NOT NULL,
|
||||
item_id varchar(100) NOT NULL,
|
||||
item_title varchar(255) NOT NULL,
|
||||
@@ -322,6 +336,7 @@ class WIS_Activator {
|
||||
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
KEY player_name (player_name),
|
||||
KEY gift_recipient (gift_recipient),
|
||||
KEY status (status)
|
||||
) $charset_collate;";
|
||||
|
||||
@@ -2717,7 +2732,10 @@ class WIS_Admin {
|
||||
<table class="widefat" style="max-width:800px; margin-top:20px;">
|
||||
<tr><th>ID</th><td><?php echo esc_html($order->id); ?></td></tr>
|
||||
<tr><th>Datum</th><td><?php echo esc_html(date('d.m.Y H:i', strtotime($order->created_at))); ?></td></tr>
|
||||
<tr><th>Spieler</th><td><strong><?php echo esc_html($order->player_name); ?></strong></td></tr>
|
||||
<tr><th>Käufer</th><td><strong><?php echo esc_html($order->player_name); ?></strong></td></tr>
|
||||
<?php if (!empty($order->gift_recipient)): ?>
|
||||
<tr><th>🎁 Geschenk für</th><td style="color:#9b59b6; font-weight:bold;"><?php echo esc_html($order->gift_recipient); ?></td></tr>
|
||||
<?php endif; ?>
|
||||
<tr><th>Server</th><td><?php echo esc_html($order->server); ?></td></tr>
|
||||
<tr><th>Zusammenfassung</th><td><?php echo esc_html($order->item_title); ?></td></tr>
|
||||
<tr><th>Preis</th><td><?php echo esc_html($order->price); ?> <?php echo esc_html($currency); ?></td></tr>
|
||||
@@ -2742,7 +2760,8 @@ class WIS_Admin {
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:140px;">Datum</th>
|
||||
<th style="width:150px;">Spieler</th>
|
||||
<th style="width:130px;">Käufer</th>
|
||||
<th style="width:130px;">Empfänger</th>
|
||||
<th>Inhalt</th>
|
||||
<th style="width:100px;">Preis</th>
|
||||
<th style="width:120px;">Status</th>
|
||||
@@ -2775,6 +2794,7 @@ class WIS_Admin {
|
||||
<tr>
|
||||
<td><?php echo esc_html(date('d.m.Y H:i', strtotime($order->created_at))); ?></td>
|
||||
<td><strong><?php echo esc_html($order->player_name); ?></strong></td>
|
||||
<td><?php if (!empty($order->gift_recipient)): ?><span title="Geschenk" style="color:#9b59b6;">🎁 <?php echo esc_html($order->gift_recipient); ?></span><?php else: ?><span style="color:#aaa;">–</span><?php endif; ?></td>
|
||||
<td><?php echo esc_html(substr($order->item_title, 0, 50)) . (strlen($order->item_title) > 50 ? '...' : ''); ?></td>
|
||||
<td><?php echo esc_html($order->price); ?> <?php echo esc_html($currency); ?></td>
|
||||
<td style="color:<?php echo $status_colors[$order->status] ?? 'black'; ?>; font-weight:bold;"><?php echo $status_map[$order->status] ?? $order->status; ?></td>
|
||||
@@ -3086,6 +3106,22 @@ class WIS_API {
|
||||
'callback' => [self::class, 'cancel_order'],
|
||||
'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
|
||||
]);
|
||||
// Gift-System Endpunkte (ab v6.5-gift)
|
||||
register_rest_route('wis/v1', '/pending_gifts', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [self::class, 'get_pending_gifts'],
|
||||
'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
|
||||
]);
|
||||
register_rest_route('wis/v1', '/gift_accept', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [self::class, 'gift_accept'],
|
||||
'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
|
||||
]);
|
||||
register_rest_route('wis/v1', '/gift_decline', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [self::class, 'gift_decline'],
|
||||
'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
|
||||
]);
|
||||
register_rest_route('wis/v1', '/pending_offline', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [self::class, 'get_pending_offline'],
|
||||
@@ -3327,6 +3363,9 @@ class WIS_API {
|
||||
|
||||
$table = $wpdb->prefix . 'wis_orders';
|
||||
|
||||
// Gift-Orders werden genauso wie normale Orders für Spieler A gepollt.
|
||||
// Spieler A muss zuerst ingame bestätigen (Geld abbuchen), erst dann
|
||||
// bekommt Spieler B die Gift-Anfrage.
|
||||
$results = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM $table
|
||||
WHERE player_name = %s AND status = 'pending'
|
||||
@@ -3436,6 +3475,74 @@ class WIS_API {
|
||||
|
||||
return new WP_REST_Response(['success' => true]);
|
||||
}
|
||||
|
||||
// ── Gift-System Endpoints ─────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* GET /wis/v1/pending_gifts?recipient={player}
|
||||
* Gibt ausstehende Geschenk-Orders zurück, die an diesen Empfänger gerichtet sind.
|
||||
*/
|
||||
public static function get_pending_gifts($request) {
|
||||
global $wpdb;
|
||||
$recipient = sanitize_text_field($request->get_param('recipient'));
|
||||
|
||||
if (!$recipient) {
|
||||
return new WP_REST_Response(['orders' => []]);
|
||||
}
|
||||
|
||||
$table = $wpdb->prefix . 'wis_orders';
|
||||
// Status NICHT auf 'claimed' setzen – bleibt 'pending' bis der Empfänger
|
||||
// ingame annimmt (gift_accept) oder ablehnt (gift_decline).
|
||||
// Das Spigot-Plugin prüft pendingGiftRequests intern gegen Duplikate.
|
||||
$results = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM $table
|
||||
WHERE gift_recipient = %s AND status IN ('pending', 'processing')
|
||||
ORDER BY created_at ASC LIMIT 1",
|
||||
$recipient
|
||||
));
|
||||
|
||||
return new WP_REST_Response(['orders' => $results]);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /wis/v1/gift_accept { "id": 123 }
|
||||
* Wird aufgerufen wenn Empfänger das Geschenk annimmt.
|
||||
* Setzt Status auf 'processing' – der Spigot-Server liefert dann die Ware aus.
|
||||
*/
|
||||
public static function gift_accept($request) {
|
||||
global $wpdb;
|
||||
$data = $request->get_json_params();
|
||||
$id = intval($data['id'] ?? 0);
|
||||
if (!$id) return new WP_REST_Response(['success' => false], 400);
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wis_orders',
|
||||
['status' => 'processing'],
|
||||
['id' => $id]
|
||||
);
|
||||
|
||||
return new WP_REST_Response(['success' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /wis/v1/gift_decline { "id": 123, "sender": "SpielerA", "price": 500 }
|
||||
* Empfänger lehnt ab → Order stornieren.
|
||||
* Rückerstattung erfolgt auf Spigot-Seite via Vault direkt.
|
||||
*/
|
||||
public static function gift_decline($request) {
|
||||
global $wpdb;
|
||||
$data = $request->get_json_params();
|
||||
$id = intval($data['id'] ?? 0);
|
||||
if (!$id) return new WP_REST_Response(['success' => false], 400);
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wis_orders',
|
||||
['status' => 'cancelled'],
|
||||
['id' => $id]
|
||||
);
|
||||
|
||||
return new WP_REST_Response(['success' => true]);
|
||||
}
|
||||
|
||||
public static function import_json($request) {
|
||||
$data = $request->get_json_params();
|
||||
@@ -3494,14 +3601,21 @@ class WIS_API {
|
||||
global $wpdb;
|
||||
$data = $request->get_json_params();
|
||||
|
||||
$player = sanitize_text_field($data['player'] ?? '');
|
||||
$cart = $data['cart'] ?? [];
|
||||
$server = sanitize_text_field($data['server'] ?? '');
|
||||
$player = sanitize_text_field($data['player'] ?? '');
|
||||
$cart = $data['cart'] ?? [];
|
||||
$server = sanitize_text_field($data['server'] ?? '');
|
||||
$coupon_code = isset($data['coupon_code']) ? sanitize_text_field(strtoupper($data['coupon_code'])) : '';
|
||||
|
||||
// Gift: optionaler Empfänger-Spielername
|
||||
$gift_recipient = isset($data['gift_recipient'])
|
||||
? sanitize_text_field(trim($data['gift_recipient'])) : '';
|
||||
|
||||
if (!$player || empty($cart) || !$server) {
|
||||
return new WP_REST_Response(['success' => false, 'message' => 'Fehlende Daten'], 400);
|
||||
}
|
||||
// Gift-Validierung: Spieler kann sich nicht selbst beschenken
|
||||
if ($gift_recipient !== '' && strcasecmp($gift_recipient, $player) === 0) {
|
||||
return new WP_REST_Response(['success' => false, 'message' => 'Selbst-Geschenk nicht erlaubt'], 400);
|
||||
}
|
||||
|
||||
$exclude_offers = get_option('wis_coupon_exclude_offers', '0');
|
||||
$currency = get_option('wis_currency_name', 'Coins');
|
||||
@@ -3702,14 +3816,15 @@ class WIS_API {
|
||||
];
|
||||
|
||||
WIS_DB::insert_order([
|
||||
'player_name' => $player,
|
||||
'server' => $server,
|
||||
'item_id' => 'cart',
|
||||
'item_title' => $title,
|
||||
'price' => $final_price,
|
||||
'quantity' => count($valid_cart),
|
||||
'status' => 'pending',
|
||||
'response' => json_encode($payload)
|
||||
'player_name' => $player,
|
||||
'gift_recipient' => $gift_recipient !== '' ? $gift_recipient : null,
|
||||
'server' => $server,
|
||||
'item_id' => 'cart',
|
||||
'item_title' => $title,
|
||||
'price' => $final_price,
|
||||
'quantity' => count($valid_cart),
|
||||
'status' => 'pending',
|
||||
'response' => json_encode($payload)
|
||||
]);
|
||||
|
||||
// Fly-Abo Abonnements registrieren / verlängern
|
||||
@@ -3758,7 +3873,9 @@ class WIS_API {
|
||||
}
|
||||
}
|
||||
|
||||
$msg = '✅ Bestellung erfolgreich!';
|
||||
$msg = $gift_recipient !== ''
|
||||
? "🎁 Geschenk-Bestellung für {$gift_recipient} erfolgreich!"
|
||||
: '✅ Bestellung erfolgreich!';
|
||||
if ($coupon_msg) $msg .= ' (' . $coupon_msg . ')';
|
||||
|
||||
return new WP_REST_Response(['success' => true, 'message' => $msg]);
|
||||
@@ -3900,6 +4017,12 @@ class WIS_Shortcode {
|
||||
.wis-coupon-input { flex-grow: 1; padding: 10px; border: 1px solid #ddd; border-radius: 6px; }
|
||||
.wis-coupon-btn { padding: 10px 15px; background: #6f42c1; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; }
|
||||
.wis-coupon-msg { font-size: 0.85rem; color: #e67e22; margin-top: 5px; min-height: 20px; }
|
||||
.wis-gift-toggle { display: flex; align-items: center; gap: 10px; margin-bottom: 15px; cursor: pointer; font-weight: 600; color: #6f42c1; user-select: none; }
|
||||
.wis-gift-toggle input[type=checkbox] { width: 18px; height: 18px; cursor: pointer; accent-color: #9b59b6; }
|
||||
.wis-gift-field { display: none; background: #f3eeff; border: 1px solid #c39bd3; border-radius: 8px; padding: 14px 16px; margin-bottom: 15px; }
|
||||
.wis-gift-field label { display: block; font-weight: 600; color: #6f42c1; margin-bottom: 6px; font-size: 0.9rem; }
|
||||
.wis-gift-input { width: 100%; padding: 10px 14px; border: 1px solid #c39bd3; border-radius: 6px; font-size: 1rem; box-sizing: border-box; background: #fff; }
|
||||
.wis-gift-hint { font-size: 0.8rem; color: #888; margin-top: 6px; }
|
||||
.wis-alert { margin-top: 15px; padding: 12px; border-radius: 5px; display: none; }
|
||||
.wis-alert.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
||||
.wis-alert.error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
||||
@@ -3993,6 +4116,17 @@ class WIS_Shortcode {
|
||||
|
||||
<input type="text" id="checkout-player" class="wis-modal-input" placeholder="Dein Spielername">
|
||||
|
||||
<!-- Gift-System -->
|
||||
<label class="wis-gift-toggle">
|
||||
<input type="checkbox" id="wis-gift-toggle">
|
||||
🎁 Als Geschenk für einen anderen Spieler kaufen
|
||||
</label>
|
||||
<div class="wis-gift-field" id="wis-gift-field">
|
||||
<label for="wis-gift-recipient">Empfänger-Spielername</label>
|
||||
<input type="text" id="wis-gift-recipient" class="wis-gift-input" placeholder="z.B. Steve123" autocomplete="off">
|
||||
<div class="wis-gift-hint">⚠️ Der Empfänger muss das Geschenk ingame annehmen. Bei Ablehnung erhältst du dein Geld zurück.</div>
|
||||
</div>
|
||||
|
||||
<div class="wis-modal-actions">
|
||||
<button class="wis-modal-btn wis-btn-confirm" id="wis-checkout-btn">💰 Kauf abschließen</button>
|
||||
<button class="wis-modal-btn wis-btn-cancel" id="wis-close-cart-btn">Abbrechen</button>
|
||||
@@ -4131,6 +4265,18 @@ class WIS_Shortcode {
|
||||
// ---- Kauf abschließen ----
|
||||
var checkoutBtn = document.getElementById('wis-checkout-btn');
|
||||
if (checkoutBtn) checkoutBtn.addEventListener('click', checkout);
|
||||
|
||||
// ---- Gift-Toggle ----
|
||||
var giftToggle = document.getElementById('wis-gift-toggle');
|
||||
var giftField = document.getElementById('wis-gift-field');
|
||||
if (giftToggle && giftField) {
|
||||
giftToggle.addEventListener('change', function() {
|
||||
giftField.style.display = giftToggle.checked ? 'block' : 'none';
|
||||
if (!giftToggle.checked) {
|
||||
document.getElementById('wis-gift-recipient').value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
@@ -4344,6 +4490,11 @@ class WIS_Shortcode {
|
||||
if (cart.length === 0) {
|
||||
content.innerHTML = '<div style="text-align:center;padding:40px;color:#999;">Dein Warenkorb ist leer</div>';
|
||||
checkout.style.display = 'none';
|
||||
// Gift-Feld zurücksetzen wenn Warenkorb leer
|
||||
var gt = document.getElementById('wis-gift-toggle');
|
||||
var gf = document.getElementById('wis-gift-field');
|
||||
if (gt) gt.checked = false;
|
||||
if (gf) gf.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
content.innerHTML = cart.map(function(item, idx) {
|
||||
@@ -4416,19 +4567,41 @@ class WIS_Shortcode {
|
||||
var alertEl = document.getElementById('cart-alert');
|
||||
var btn = document.getElementById('wis-checkout-btn');
|
||||
|
||||
// Gift-Feld auslesen
|
||||
var giftToggle = document.getElementById('wis-gift-toggle');
|
||||
var giftRecipient = '';
|
||||
if (giftToggle && giftToggle.checked) {
|
||||
giftRecipient = (document.getElementById('wis-gift-recipient').value || '').trim();
|
||||
}
|
||||
|
||||
if (!player) { alertEl.textContent = 'Bitte Spielername eingeben!'; alertEl.className = 'wis-alert error'; alertEl.style.display = 'block'; return; }
|
||||
if (!server) { alertEl.textContent = 'Bitte Server auswählen!'; alertEl.className = 'wis-alert error'; alertEl.style.display = 'block'; return; }
|
||||
|
||||
// Gift-Validierungen im Frontend
|
||||
if (giftToggle && giftToggle.checked) {
|
||||
if (!giftRecipient) {
|
||||
alertEl.textContent = '🎁 Bitte den Empfänger-Spielernamen eingeben!';
|
||||
alertEl.className = 'wis-alert error'; alertEl.style.display = 'block'; return;
|
||||
}
|
||||
if (giftRecipient.toLowerCase() === player.toLowerCase()) {
|
||||
alertEl.textContent = '🎁 Du kannst dir nicht selbst etwas schenken!';
|
||||
alertEl.className = 'wis-alert error'; alertEl.style.display = 'block'; return;
|
||||
}
|
||||
}
|
||||
|
||||
var invalid = cart.filter(function(i){ return i.servers.indexOf(server) === -1; });
|
||||
if (invalid.length) { alertEl.textContent = 'Einige Items sind nicht für diesen Server!'; alertEl.className = 'wis-alert error'; alertEl.style.display = 'block'; return; }
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⏳ Speichere…';
|
||||
|
||||
var payload = {player: player, cart: cart, server: server, coupon_code: couponCode};
|
||||
if (giftRecipient) payload.gift_recipient = giftRecipient;
|
||||
|
||||
fetch(apiBase + '/order', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({player: player, cart: cart, server: server, coupon_code: couponCode})
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(data) {
|
||||
@@ -4437,6 +4610,11 @@ class WIS_Shortcode {
|
||||
alertEl.className = 'wis-alert success';
|
||||
alertEl.style.display = 'block';
|
||||
cart = []; couponData = {};
|
||||
// Gift-Feld zurücksetzen
|
||||
if (giftToggle) { giftToggle.checked = false; }
|
||||
var giftField = document.getElementById('wis-gift-field');
|
||||
if (giftField) giftField.style.display = 'none';
|
||||
document.getElementById('wis-gift-recipient').value = '';
|
||||
updateCartBadge();
|
||||
setTimeout(function(){ closeCart(); location.reload(); }, 2000);
|
||||
} else {
|
||||
@@ -4579,4 +4757,22 @@ add_action('widgets_init', function() {
|
||||
register_widget('WIS_Sidebar_Widget');
|
||||
});
|
||||
add_action('wis_daily_deal_event', [WIS_Activator::class, 'run_daily_deal']);
|
||||
add_action('wis_abo_renewal_event', [WIS_Activator::class, 'run_abo_renewal']);
|
||||
add_action('wis_abo_renewal_event', [WIS_Activator::class, 'run_abo_renewal']);
|
||||
|
||||
// ── Auto-Expire: Orders nach 7 Tagen ohne Ingame-Bestätigung stornieren ──
|
||||
add_action('wis_auto_expire_orders', function () {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . 'wis_orders';
|
||||
|
||||
// Alle Orders die seit > 7 Tagen pending/claimed sind → cancelled
|
||||
$affected = $wpdb->query(
|
||||
"UPDATE {$table}
|
||||
SET status = 'cancelled'
|
||||
WHERE status IN ('pending', 'claimed')
|
||||
AND created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)"
|
||||
);
|
||||
|
||||
if ($affected > 0) {
|
||||
error_log("[WIS] Auto-Expire: {$affected} Order(s) nach 7 Tagen storniert.");
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user