Upload via Git Manager GUI
This commit is contained in:
@@ -227,6 +227,14 @@ add_action('admin_notices', [WIS_Dashboard::class, 'show_update_notice']);
|
||||
// ===========================================================
|
||||
class WIS_Activator {
|
||||
public static function activate() {
|
||||
// Spalte custom_image_url nachrüsten (für bestehende Installationen)
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . 'wis_items';
|
||||
$col = $wpdb->get_var("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '$table' AND COLUMN_NAME = 'custom_image_url'");
|
||||
if (!$col) {
|
||||
$wpdb->query("ALTER TABLE $table ADD COLUMN custom_image_url varchar(500) DEFAULT NULL AFTER categories");
|
||||
}
|
||||
|
||||
self::create_tables();
|
||||
self::set_default_options();
|
||||
self::create_default_categories();
|
||||
@@ -260,6 +268,7 @@ class WIS_Activator {
|
||||
is_daily_deal tinyint(1) DEFAULT 0,
|
||||
servers text,
|
||||
categories text,
|
||||
custom_image_url varchar(500) DEFAULT NULL,
|
||||
status varchar(20) DEFAULT 'draft',
|
||||
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
@@ -775,6 +784,20 @@ class WIS_Item_Categorizer {
|
||||
// DATABASE HELPER
|
||||
// ===========================================================
|
||||
class WIS_DB {
|
||||
|
||||
/**
|
||||
* Gibt die Bild-URL eines Items zurück.
|
||||
* Priorität: custom_image_url > automatisch generierte URL aus item_id.
|
||||
*/
|
||||
public static function get_item_image($item) {
|
||||
if (!empty($item->custom_image_url)) {
|
||||
return esc_url($item->custom_image_url);
|
||||
}
|
||||
$img_base = get_option('wis_image_base_url', '');
|
||||
$img_name = str_replace(':', '_', $item->item_id) . '.png';
|
||||
return $img_base . $img_name;
|
||||
}
|
||||
|
||||
public static function get_items($args = []) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . 'wis_items';
|
||||
@@ -1448,26 +1471,77 @@ class WIS_Admin {
|
||||
|
||||
if (isset($_POST['wis_save_item'])) {
|
||||
check_admin_referer('wis_item_form');
|
||||
global $wpdb;
|
||||
|
||||
$data = [
|
||||
'item_id' => sanitize_text_field($_POST['item_id']),
|
||||
'name' => sanitize_text_field($_POST['name']),
|
||||
'description' => sanitize_textarea_field($_POST['description']),
|
||||
'price' => intval($_POST['price']),
|
||||
'offer_price' => intval($_POST['offer_price']),
|
||||
'is_offer' => isset($_POST['is_offer']) ? 1 : 0,
|
||||
'servers' => isset($_POST['servers']) ? json_encode($_POST['servers']) : '[]',
|
||||
'categories' => isset($_POST['categories']) ? json_encode($_POST['categories']) : '[]',
|
||||
'status' => intval($_POST['price']) > 0 ? 'publish' : 'draft'
|
||||
];
|
||||
|
||||
if (isset($_GET['edit'])) {
|
||||
WIS_DB::update_item(intval($_GET['edit']), $data);
|
||||
echo '<div class="updated"><p>✅ Item gespeichert!</p></div>';
|
||||
// item_id je nach Typ ermitteln
|
||||
$item_type = sanitize_text_field($_POST['item_type'] ?? 'minecraft');
|
||||
if ($item_type === 'fly') {
|
||||
$resolved_item_id = sanitize_text_field($_POST['fly_duration'] ?? 'fly_5min');
|
||||
} elseif ($item_type === 'rank') {
|
||||
$rank_id = preg_replace('/[^a-z0-9_\-]/', '', strtolower($_POST['rank_id'] ?? 'vip'));
|
||||
$lp_group = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_POST['lp_group'] ?? $rank_id);
|
||||
$default_group = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_POST['default_group'] ?? 'default');
|
||||
$rank_days = max(0, intval($_POST['rank_days'] ?? 30));
|
||||
if (empty($lp_group)) $lp_group = $rank_id;
|
||||
if (empty($default_group)) $default_group = 'default';
|
||||
// Format: rank_{rank_id}_{lp_group}_{default_group}_{days}
|
||||
$resolved_item_id = 'rank_' . $rank_id . '_' . $lp_group . '_' . $default_group . '_' . $rank_days;
|
||||
} else {
|
||||
WIS_DB::insert_item($data);
|
||||
echo '<div class="updated"><p>✅ Item erstellt!</p></div>';
|
||||
$resolved_item_id = sanitize_text_field($_POST['item_id'] ?? '');
|
||||
}
|
||||
|
||||
// Pflichtfeld-Prüfung
|
||||
if (empty($resolved_item_id) || empty(trim($_POST['name'] ?? ''))) {
|
||||
echo '<div class="error"><p>❌ Name und Item-ID sind Pflichtfelder.</p></div>';
|
||||
} else {
|
||||
$data = [
|
||||
'item_id' => $resolved_item_id,
|
||||
'name' => sanitize_text_field($_POST['name']),
|
||||
'description' => sanitize_textarea_field($_POST['description'] ?? ''),
|
||||
'price' => intval($_POST['price'] ?? 0),
|
||||
'offer_price' => intval($_POST['offer_price'] ?? 0),
|
||||
'is_offer' => isset($_POST['is_offer']) ? 1 : 0,
|
||||
'servers' => isset($_POST['servers']) ? json_encode(array_map('sanitize_text_field', $_POST['servers'])) : '[]',
|
||||
'categories' => isset($_POST['categories']) ? json_encode(array_map('sanitize_text_field', $_POST['categories'])) : '[]',
|
||||
'custom_image_url' => esc_url_raw($_POST['custom_image_url'] ?? ''),
|
||||
'status' => (intval($_POST['price'] ?? 0) > 0 || $item_type === 'fly' || $item_type === 'rank') ? 'publish' : 'draft',
|
||||
];
|
||||
|
||||
if (isset($_GET['edit'])) {
|
||||
$result = WIS_DB::update_item(intval($_GET['edit']), $data);
|
||||
if ($result !== false) {
|
||||
wp_redirect(admin_url('admin.php?page=wis_items&edit=' . intval($_GET['edit']) . '&saved=1'));
|
||||
exit;
|
||||
} else {
|
||||
echo '<div class="error"><p>❌ Fehler beim Speichern: ' . esc_html($wpdb->last_error) . '</p></div>';
|
||||
}
|
||||
} else {
|
||||
// Prüfen ob item_id bereits existiert → direkt zum Edit weiterleiten
|
||||
$existing = WIS_DB::get_item_by_item_id($resolved_item_id);
|
||||
if ($existing) {
|
||||
// Bestehenden Artikel aktualisieren statt Duplikat-Fehler
|
||||
WIS_DB::update_item($existing->id, $data);
|
||||
wp_redirect(admin_url('admin.php?page=wis_items&edit=' . $existing->id . '&saved=1'));
|
||||
exit;
|
||||
}
|
||||
$result = WIS_DB::insert_item($data);
|
||||
if ($result) {
|
||||
$new_id = $wpdb->insert_id;
|
||||
wp_redirect(admin_url('admin.php?page=wis_items&edit=' . $new_id . '&created=1'));
|
||||
exit;
|
||||
} else {
|
||||
$err = $wpdb->last_error ?: 'Unbekannter Fehler.';
|
||||
echo '<div class="error"><p>❌ Fehler beim Erstellen: ' . esc_html($err) . '</p></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['created'])) {
|
||||
echo '<div class="updated"><p>✅ Item erfolgreich erstellt!</p></div>';
|
||||
}
|
||||
if (isset($_GET['saved'])) {
|
||||
echo '<div class="updated"><p>✅ Item gespeichert!</p></div>';
|
||||
}
|
||||
|
||||
if (isset($_GET['edit']) || isset($_GET['add'])) {
|
||||
@@ -1497,10 +1571,120 @@ class WIS_Admin {
|
||||
<td><input type="text" id="name" name="name" value="<?php echo $item ? esc_attr($item->name) : ''; ?>" class="regular-text" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="item_id">Item ID *</label></th>
|
||||
<th><label for="item_id">Item ID / Typ *</label></th>
|
||||
<td>
|
||||
<input type="text" id="item_id" name="item_id" value="<?php echo $item ? esc_attr($item->item_id) : ''; ?>" class="regular-text" placeholder="minecraft:diamond" required>
|
||||
<p class="description">Z.B.: minecraft:diamond (Kategorien werden automatisch zugewiesen)</p>
|
||||
<?php
|
||||
$fly_ids = ['fly_5min','fly_15min','fly_30min','fly_1h','fly_2h','fly_3h'];
|
||||
$is_fly = $item && in_array($item->item_id, $fly_ids);
|
||||
$is_rank = $item && preg_match('/^rank_([^_]+(?:_[^_]+)*)_([a-zA-Z0-9_\-]+)_([a-zA-Z0-9_\-]+)_(\d+)$/', $item->item_id, $rm);
|
||||
// Format: rank_{rank_id}_{lp_group}_{default_group}_{days}
|
||||
// Fallback für altes Format rank_{rank_id}_{days}
|
||||
$is_rank_old = !$is_rank && $item && preg_match('/^rank_(.+)_(\d+)$/', $item->item_id, $rm_old);
|
||||
$cur_rank_id = $is_rank ? $rm[1] : ($is_rank_old ? $rm_old[1] : 'vip');
|
||||
$cur_lp_group = $is_rank ? $rm[2] : $cur_rank_id;
|
||||
$cur_default_group = $is_rank ? $rm[3] : 'default';
|
||||
$cur_rank_days = $is_rank ? intval($rm[4]) : ($is_rank_old ? intval($rm_old[2]) : 30);
|
||||
$cur_label = $item ? esc_attr($item->name) : '';
|
||||
$detected_type = $is_fly ? 'fly' : (($is_rank || $is_rank_old) ? 'rank' : 'minecraft');
|
||||
?>
|
||||
<select id="item_type" name="item_type" onchange="wisToggleItemType(this.value)" style="margin-bottom:8px;">
|
||||
<option value="minecraft" <?php echo $detected_type === 'minecraft' ? 'selected' : ''; ?>>Minecraft Item</option>
|
||||
<option value="fly" <?php echo $detected_type === 'fly' ? 'selected' : ''; ?>>✈ Fly-Gutschein</option>
|
||||
<option value="rank" <?php echo $detected_type === 'rank' ? 'selected' : ''; ?>>👑 Rang (LuckPerms)</option>
|
||||
</select>
|
||||
|
||||
<div id="wis_item_minecraft">
|
||||
<input type="text" id="item_id" name="item_id" value="<?php echo ($item && !$is_fly && !$is_rank) ? esc_attr($item->item_id) : ''; ?>" class="regular-text" placeholder="minecraft:diamond">
|
||||
<p class="description">Z.B.: minecraft:diamond (Kategorien werden automatisch zugewiesen)</p>
|
||||
</div>
|
||||
|
||||
<div id="wis_item_fly" style="display:none;">
|
||||
<select name="fly_duration" id="fly_duration">
|
||||
<option value="fly_5min" <?php echo ($item && $item->item_id === 'fly_5min') ? 'selected' : ''; ?>>✈ 5 Minuten Fly</option>
|
||||
<option value="fly_15min" <?php echo ($item && $item->item_id === 'fly_15min') ? 'selected' : ''; ?>>✈ 15 Minuten Fly</option>
|
||||
<option value="fly_30min" <?php echo ($item && $item->item_id === 'fly_30min') ? 'selected' : ''; ?>>✈ 30 Minuten Fly</option>
|
||||
<option value="fly_1h" <?php echo ($item && $item->item_id === 'fly_1h') ? 'selected' : ''; ?>>✈ 1 Stunde Fly</option>
|
||||
<option value="fly_2h" <?php echo ($item && $item->item_id === 'fly_2h') ? 'selected' : ''; ?>>✈ 2 Stunden Fly</option>
|
||||
<option value="fly_3h" <?php echo ($item && $item->item_id === 'fly_3h') ? 'selected' : ''; ?>>✈ 3 Stunden Fly</option>
|
||||
</select>
|
||||
<p class="description">Der Spieler bekommt nach dem Kauf Fly für die gewählte Dauer.</p>
|
||||
</div>
|
||||
|
||||
<div id="wis_item_rank" style="display:none;">
|
||||
<table style="border-collapse:collapse;">
|
||||
<tr>
|
||||
<td style="padding:4px 10px 4px 0;"><label for="rank_id"><strong>Rang-ID:</strong></label></td>
|
||||
<td><input type="text" id="rank_id" name="rank_id" value="<?php echo esc_attr($cur_rank_id); ?>" class="regular-text" placeholder="vip" style="width:160px;"></td>
|
||||
<td style="padding:4px 0 4px 12px; color:#666; font-size:12px;">Interner Name (frei wählbar, z. B. <code>vip</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:4px 10px 4px 0;"><label for="lp_group"><strong>LuckPerms-Gruppe:</strong></label></td>
|
||||
<td><input type="text" id="lp_group" name="lp_group" value="<?php echo esc_attr($cur_lp_group); ?>" class="regular-text" placeholder="vip" style="width:160px;"></td>
|
||||
<td style="padding:4px 0 4px 12px; color:#666; font-size:12px;">Exakter Gruppenname in LuckPerms</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:4px 10px 4px 0;"><label for="default_group"><strong>Standard-Gruppe (nach Ablauf):</strong></label></td>
|
||||
<td><input type="text" id="default_group" name="default_group" value="<?php echo esc_attr($cur_default_group); ?>" class="regular-text" placeholder="default" style="width:160px;"></td>
|
||||
<td style="padding:4px 0 4px 12px; color:#666; font-size:12px;">Gruppe nach Rang-Ablauf (z. B. <code>default</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:4px 10px 4px 0;"><label for="rank_days"><strong>Laufzeit (Tage):</strong></label></td>
|
||||
<td>
|
||||
<input type="number" id="rank_days" name="rank_days" value="<?php echo esc_attr($cur_rank_days); ?>" min="0" style="width:80px;">
|
||||
<span class="description" style="margin-left:8px;">0 = dauerhaft</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="description" style="margin-top:6px;">
|
||||
Der Spielername im Shop (Feld <em>Name</em> oben) wird dem Spieler als Rang-Label angezeigt.<br>
|
||||
Gespeicherte Item-ID: <code>rank_{rang-id}_{lp-gruppe}_{standard-gruppe}_{tage}</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function wisToggleItemType(val) {
|
||||
document.getElementById('wis_item_minecraft').style.display = (val === 'minecraft') ? '' : 'none';
|
||||
document.getElementById('wis_item_fly').style.display = (val === 'fly') ? '' : 'none';
|
||||
document.getElementById('wis_item_rank').style.display = (val === 'rank') ? '' : 'none';
|
||||
// item_id Pflichtfeld nur bei Minecraft-Items
|
||||
document.getElementById('item_id').required = (val === 'minecraft');
|
||||
}
|
||||
// Initial state
|
||||
wisToggleItemType(document.getElementById('item_type').value);
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="custom_image_url">Bild-URL (optional)</label></th>
|
||||
<td>
|
||||
<input type="url" id="custom_image_url" name="custom_image_url"
|
||||
value="<?php echo ($item && !empty($item->custom_image_url)) ? esc_attr($item->custom_image_url) : ''; ?>"
|
||||
class="large-text" placeholder="https://example.com/mein-fly-bild.png"
|
||||
oninput="wisPreviewImage(this.value)">
|
||||
<p class="description">
|
||||
Eigene Bild-URL – überschreibt die automatische Minecraft-Item-ID-URL.<br>
|
||||
Ideal für Fly-Gutscheine, VIP-Pakete etc. Leer lassen = Standard.
|
||||
</p>
|
||||
<div id="wis_img_preview" style="margin-top:8px; <?php echo ($item && !empty($item->custom_image_url)) ? '' : 'display:none;'; ?>">
|
||||
<img id="wis_img_preview_img"
|
||||
src="<?php echo ($item && !empty($item->custom_image_url)) ? esc_url($item->custom_image_url) : ''; ?>"
|
||||
style="max-height:80px; border-radius:6px; border:1px solid #ddd; padding:4px; background:#2d2d2d;"
|
||||
alt="Vorschau"
|
||||
onerror="document.getElementById('wis_img_preview').style.display='none';">
|
||||
<span style="margin-left:8px; color:#666; font-size:12px;">Vorschau</span>
|
||||
</div>
|
||||
<script>
|
||||
function wisPreviewImage(url) {
|
||||
var box = document.getElementById('wis_img_preview');
|
||||
var img = document.getElementById('wis_img_preview_img');
|
||||
if (url) {
|
||||
img.src = url;
|
||||
box.style.display = '';
|
||||
} else {
|
||||
box.style.display = 'none';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -1576,7 +1760,7 @@ class WIS_Admin {
|
||||
$per_page = 24;
|
||||
$current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
|
||||
|
||||
$fetch_args = ['status' => 'publish'];
|
||||
$fetch_args = []; // kein Status-Filter → alle Items zählen
|
||||
if (!empty($current_category)) $fetch_args['category_slug'] = $current_category;
|
||||
if (!empty($search_query)) $fetch_args['search'] = $search_query;
|
||||
|
||||
@@ -1587,21 +1771,28 @@ class WIS_Admin {
|
||||
|
||||
global $wpdb;
|
||||
$table_items = $wpdb->prefix . 'wis_items';
|
||||
$where_parts = ["status = 'publish'"];
|
||||
// Admin-Liste: alle Items anzeigen (publish + draft), Query ohne doppeltes prepare()
|
||||
$where_parts = [];
|
||||
$where_vals = [];
|
||||
if (!empty($current_category)) {
|
||||
$search_pattern = '%"' . $current_category . '"%';
|
||||
$where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern);
|
||||
$where_parts[] = "categories LIKE %s";
|
||||
$where_vals[] = '%"' . $wpdb->esc_like($current_category) . '"%';
|
||||
}
|
||||
if (!empty($search_query)) {
|
||||
$search_like = '%' . $wpdb->esc_like($search_query) . '%';
|
||||
$where_parts[] = $wpdb->prepare("(name LIKE %s OR item_id LIKE %s)", $search_like, $search_like);
|
||||
$like = '%' . $wpdb->esc_like($search_query) . '%';
|
||||
$where_parts[] = "(name LIKE %s OR item_id LIKE %s)";
|
||||
$where_vals[] = $like;
|
||||
$where_vals[] = $like;
|
||||
}
|
||||
$where_sql = implode(" AND ", $where_parts);
|
||||
$items = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT * FROM $table_items WHERE $where_sql ORDER BY name ASC LIMIT %d OFFSET %d",
|
||||
$per_page,
|
||||
$offset
|
||||
));
|
||||
$where_sql = !empty($where_parts) ? 'WHERE ' . implode(' AND ', $where_parts) : '';
|
||||
$where_vals[] = $per_page;
|
||||
$where_vals[] = $offset;
|
||||
$items = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT * FROM $table_items $where_sql ORDER BY name ASC LIMIT %d OFFSET %d",
|
||||
$where_vals
|
||||
)
|
||||
);
|
||||
|
||||
$currency = get_option('wis_currency_name', 'Coins');
|
||||
|
||||
@@ -1717,7 +1908,19 @@ class WIS_Admin {
|
||||
</th>
|
||||
<td><?php echo esc_html($item->id); ?></td>
|
||||
<td><strong><?php echo esc_html($item->name); ?></strong></td>
|
||||
<td><code><?php echo esc_html($item->item_id); ?></code></td>
|
||||
<td>
|
||||
<?php
|
||||
if (preg_match('/^rank_([^_]+)_([a-zA-Z0-9_\-]+)_([a-zA-Z0-9_\-]+)_(\d+)$/', $item->item_id, $rm2)) {
|
||||
$rd = intval($rm2[4]);
|
||||
echo '<span title="' . esc_attr($item->item_id) . '">👑 LP: <code>' . esc_html($rm2[2]) . '</code> — ' . ($rd === 0 ? '<em>dauerhaft</em>' : esc_html($rd) . ' Tage') . '</span>';
|
||||
} elseif (preg_match('/^rank_(.+)_(\d+)$/', $item->item_id, $rm2)) {
|
||||
$rd = intval($rm2[2]);
|
||||
echo '<span title="' . esc_attr($item->item_id) . '">👑 <code>' . esc_html($rm2[1]) . '</code> — ' . ($rd === 0 ? '<em>dauerhaft</em>' : esc_html($rd) . ' Tage') . '</span>';
|
||||
} else {
|
||||
echo '<code>' . esc_html($item->item_id) . '</code>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo esc_html($item->price); ?> <?php echo esc_html($currency); ?></td>
|
||||
<td>
|
||||
<?php if ($item->status === 'publish'): ?>
|
||||
@@ -2171,13 +2374,12 @@ class WIS_Admin {
|
||||
$json_data = ['items' => []];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$img_name = str_replace(':', '_', $item->item_id) . '.png';
|
||||
$json_data['items'][] = [
|
||||
'id' => $item->item_id,
|
||||
'name' => $item->name,
|
||||
'description' => $item->description,
|
||||
'price' => intval($item->price),
|
||||
'image' => $img_base . $img_name
|
||||
'image' => WIS_DB::get_item_image($item)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -2501,7 +2703,6 @@ class WIS_API {
|
||||
|
||||
$result = [];
|
||||
foreach ($items as $item) {
|
||||
$img_name = str_replace(':', '_', $item->item_id) . '.png';
|
||||
$result[] = [
|
||||
'id' => $item->id,
|
||||
'item_id' => $item->item_id,
|
||||
@@ -2513,10 +2714,20 @@ class WIS_API {
|
||||
'is_daily_deal' => (bool) $item->is_daily_deal,
|
||||
'servers' => json_decode($item->servers, true) ?: [],
|
||||
'categories' => json_decode($item->categories, true) ?: [],
|
||||
'image' => $img_base . $img_name,
|
||||
'image' => WIS_DB::get_item_image($item),
|
||||
'has_custom_image' => !empty($item->custom_image_url),
|
||||
];
|
||||
}
|
||||
|
||||
// Fly-Items nach Dauer sortieren: 5min→15min→30min→1h→2h→3h
|
||||
$fly_order = ['fly_5min'=>1,'fly_15min'=>2,'fly_30min'=>3,'fly_1h'=>4,'fly_2h'=>5,'fly_3h'=>6];
|
||||
usort($result, function($a, $b) use ($fly_order) {
|
||||
$ap = isset($fly_order[$a['item_id']]) ? $fly_order[$a['item_id']] : 999;
|
||||
$bp = isset($fly_order[$b['item_id']]) ? $fly_order[$b['item_id']] : 999;
|
||||
if ($ap !== 999 || $bp !== 999) return $ap - $bp;
|
||||
return strcmp($a['name'], $b['name']);
|
||||
});
|
||||
|
||||
return new WP_REST_Response([
|
||||
'items' => $result,
|
||||
'total' => $total,
|
||||
@@ -2787,23 +2998,93 @@ class WIS_API {
|
||||
|
||||
$final_price = max(0, $total_normal - $coupon_discount) + $total_offer;
|
||||
|
||||
$items_payload = [];
|
||||
$title_parts = [];
|
||||
// Fly-Dauern (item_id → Sekunden)
|
||||
// Fly-Dauern und lesbares Label (wird dem Spieler auf dem Code angezeigt)
|
||||
$fly_durations = [
|
||||
'fly_5min' => 5 * 60,
|
||||
'fly_15min' => 15 * 60,
|
||||
'fly_30min' => 30 * 60,
|
||||
'fly_1h' => 1 * 3600,
|
||||
'fly_2h' => 2 * 3600,
|
||||
'fly_3h' => 3 * 3600,
|
||||
];
|
||||
$fly_labels = [
|
||||
'fly_5min' => '5 Minuten Fly',
|
||||
'fly_15min' => '15 Minuten Fly',
|
||||
'fly_30min' => '30 Minuten Fly',
|
||||
'fly_1h' => '1 Stunde Fly',
|
||||
'fly_2h' => '2 Stunden Fly',
|
||||
'fly_3h' => '3 Stunden Fly',
|
||||
];
|
||||
|
||||
$items_payload = [];
|
||||
$commands_payload = [];
|
||||
$title_parts = [];
|
||||
|
||||
foreach ($valid_cart as $item) {
|
||||
$items_payload[] = [
|
||||
'id' => $item['id'],
|
||||
'amount' => $item['qty']
|
||||
];
|
||||
$title_parts[] = $item['qty'] . 'x ' . $item['title'];
|
||||
$item_id = $item['id']; // Das ist der item_id-String aus wis_items
|
||||
|
||||
if (isset($fly_durations[$item_id])) {
|
||||
// Fly-Gutschein: pro Stueck einen eigenen Code-Eintrag (qty > 1 = mehrere Codes)
|
||||
$base_sec = $fly_durations[$item_id];
|
||||
$base_label = $fly_labels[$item_id];
|
||||
for ($q = 0; $q < intval($item['qty']); $q++) {
|
||||
$commands_payload[] = [
|
||||
'type' => 'fly',
|
||||
'duration_sec' => $base_sec,
|
||||
'label' => $base_label,
|
||||
];
|
||||
}
|
||||
$title_parts[] = $item['qty'] . 'x ' . $item['title'];
|
||||
} elseif (preg_match('/^rank_([^_]+)_([a-zA-Z0-9_\-]+)_([a-zA-Z0-9_\-]+)_(\d+)$/', $item_id, $rm)) {
|
||||
// Neues Format: rank_{rank_id}_{lp_group}_{default_group}_{days}
|
||||
$rank_id = $rm[1];
|
||||
$lp_group = $rm[2];
|
||||
$default_group = $rm[3];
|
||||
$rank_days = intval($rm[4]);
|
||||
for ($q = 0; $q < intval($item['qty']); $q++) {
|
||||
$commands_payload[] = [
|
||||
'type' => 'rank',
|
||||
'rank_id' => $rank_id,
|
||||
'lp_group' => $lp_group,
|
||||
'default_group' => $default_group,
|
||||
'label' => $item['title'],
|
||||
'days' => $rank_days,
|
||||
];
|
||||
}
|
||||
$title_parts[] = $item['qty'] . 'x ' . $item['title'];
|
||||
} elseif (preg_match('/^rank_(.+)_(\d+)$/', $item_id, $rm)) {
|
||||
// Altes Format (Fallback): rank_{rank_id}_{days}
|
||||
$rank_id = $rm[1];
|
||||
$rank_days = intval($rm[2]);
|
||||
for ($q = 0; $q < intval($item['qty']); $q++) {
|
||||
$commands_payload[] = [
|
||||
'type' => 'rank',
|
||||
'rank_id' => $rank_id,
|
||||
'lp_group'=> $rank_id,
|
||||
'default_group' => 'default',
|
||||
'label' => $item['title'],
|
||||
'days' => $rank_days,
|
||||
];
|
||||
}
|
||||
$title_parts[] = $item['qty'] . 'x ' . $item['title'];
|
||||
} else {
|
||||
// Normales Item
|
||||
$items_payload[] = [
|
||||
'id' => $item_id,
|
||||
'amount' => $item['qty'],
|
||||
];
|
||||
$title_parts[] = $item['qty'] . 'x ' . $item['title'];
|
||||
}
|
||||
}
|
||||
|
||||
$title = "Warenkorb: " . implode(', ', $title_parts);
|
||||
if (strlen($title) > 240) $title = substr($title, 0, 237) . '...';
|
||||
|
||||
$payload = [
|
||||
'items' => $items_payload,
|
||||
'coupon' => $coupon_applied ? ['code' => $coupon_code, 'discount' => $coupon_discount] : []
|
||||
'items' => $items_payload,
|
||||
'commands' => $commands_payload,
|
||||
'coupon' => $coupon_applied ? ['code' => $coupon_code, 'discount' => $coupon_discount] : [],
|
||||
];
|
||||
|
||||
WIS_DB::insert_order([
|
||||
@@ -2914,8 +3195,11 @@ class WIS_Shortcode {
|
||||
.wis-card.offer { border: 2px solid #ffc107; }
|
||||
.wis-card:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0,0,0,0.1); }
|
||||
.wis-card-img { width: 100%; height: 180px; background: #2d2d2d; display: flex; align-items: center; justify-content: center; position: relative; padding: 20px; }
|
||||
.wis-card-img img { width: 100px !important; height: 100px !important; object-fit: contain; filter: drop-shadow(0 6px 8px rgba(0,0,0,0.7)); transition: transform 0.3s; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; }
|
||||
.wis-card-img img { width: 160px !important; height: 160px !important; object-fit: contain; filter: drop-shadow(0 6px 8px rgba(0,0,0,0.7)); transition: transform 0.3s; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; }
|
||||
.wis-card:hover .wis-card-img img { transform: scale(1.15) rotate(5deg); }
|
||||
.wis-card-img--custom { padding: 0 !important; overflow: hidden; }
|
||||
.wis-card-img--custom img { width: 100% !important; height: 100% !important; object-fit: cover !important; image-rendering: auto !important; filter: none !important; border-radius: 0; }
|
||||
.wis-card:hover .wis-card-img--custom img { transform: scale(1.05) !important; }
|
||||
.wis-offer-badge, .wis-daily-badge { position: absolute; top: 10px; left: 10px; background: linear-gradient(135deg, #ff416c, #ff4b2b); color: white; padding: 6px 12px; border-radius: 20px; font-size: 0.75rem; font-weight: bold; box-shadow: 0 2px 5px rgba(0,0,0,0.3); z-index: 2; }
|
||||
.wis-daily-badge { background: linear-gradient(135deg, #6f42c1, #8e44ad); border: 1px solid #fff; }
|
||||
.wis-card-body { padding: 15px; flex-grow: 1; display: flex; flex-direction: column; }
|
||||
@@ -3235,7 +3519,7 @@ class WIS_Shortcode {
|
||||
// Wichtig: data-item-id statt onclick mit JSON
|
||||
return '<div class="wis-card' + (item.is_offer ? ' offer' : '') + '">'
|
||||
+ badge
|
||||
+ '<div class="wis-card-img">'
|
||||
+ '<div class="wis-card-img' + (item.has_custom_image ? ' wis-card-img--custom' : '') + '">'
|
||||
+ '<img src="' + escHtml(item.image) + '" alt="' + escHtml(item.name) + '" loading="lazy"'
|
||||
+ ' onerror="this.onerror=null;this.src=\'https://via.placeholder.com/100/333/fff?text=?\';">'
|
||||
+ '</div>'
|
||||
@@ -3506,8 +3790,7 @@ class WIS_Sidebar_Widget extends WP_Widget {
|
||||
if ($item) {
|
||||
$price = $item->offer_price > 0 ? $item->offer_price : $item->price;
|
||||
$show_old = $item->offer_price > 0 && $item->offer_price != $item->price;
|
||||
$img_name = str_replace(':', '_', $item->item_id) . '.png';
|
||||
$img_url = $img_base . $img_name;
|
||||
$img_url = WIS_DB::get_item_image($item);
|
||||
$target_url = !empty($instance['shop_url']) ? $instance['shop_url'] : home_url();
|
||||
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user