From 3ba519b53d9539516bd62e3a4ddb8a3812348730 Mon Sep 17 00:00:00 2001 From: Git Manager GUI Date: Fri, 24 Apr 2026 09:12:43 +0200 Subject: [PATCH] Upload via Git Manager GUI --- wp-ingame-shop/wp-ingame-shop-pro.php | 399 ++++++++++++++++++++++---- 1 file changed, 341 insertions(+), 58 deletions(-) diff --git a/wp-ingame-shop/wp-ingame-shop-pro.php b/wp-ingame-shop/wp-ingame-shop-pro.php index 066e818..739ec80 100644 --- a/wp-ingame-shop/wp-ingame-shop-pro.php +++ b/wp-ingame-shop/wp-ingame-shop-pro.php @@ -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'; @@ -836,11 +859,11 @@ class WIS_DB { $id )); } - + public static function get_item_by_item_id($item_id) { global $wpdb; return $wpdb->get_row($wpdb->prepare( - "SELECT * FROM {$wpdb->prefix}wis_items WHERE item_id = %s", + "SELECT * FROM {$wpdb->prefix}wis_items WHERE item_id = %s", $item_id )); } @@ -1448,28 +1471,79 @@ class WIS_Admin { if (isset($_POST['wis_save_item'])) { check_admin_referer('wis_item_form'); - - $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 '

✅ Item gespeichert!

'; + global $wpdb; + + // 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 '

✅ Item erstellt!

'; + $resolved_item_id = sanitize_text_field($_POST['item_id'] ?? ''); + } + + // Pflichtfeld-Prüfung + if (empty($resolved_item_id) || empty(trim($_POST['name'] ?? ''))) { + echo '

❌ Name und Item-ID sind Pflichtfelder.

'; + } 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 '

❌ Fehler beim Speichern: ' . esc_html($wpdb->last_error) . '

'; + } + } 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 '

❌ Fehler beim Erstellen: ' . esc_html($err) . '

'; + } + } } } - + + if (isset($_GET['created'])) { + echo '

✅ Item erfolgreich erstellt!

'; + } + if (isset($_GET['saved'])) { + echo '

✅ Item gespeichert!

'; + } + if (isset($_GET['edit']) || isset($_GET['add'])) { $item = isset($_GET['edit']) ? WIS_DB::get_item(intval($_GET['edit'])) : null; $servers = WIS_DB::get_servers(); @@ -1497,10 +1571,120 @@ class WIS_Admin { - + - -

Z.B.: minecraft:diamond (Kategorien werden automatisch zugewiesen)

+ 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'); + ?> + + +
+ +

Z.B.: minecraft:diamond (Kategorien werden automatisch zugewiesen)

+
+ + + + + + + + + + + + +

+ Eigene Bild-URL – überschreibt die automatische Minecraft-Item-ID-URL.
+ Ideal für Fly-Gutscheine, VIP-Pakete etc. Leer lassen = Standard. +

+
+ Vorschau + Vorschau +
+ @@ -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 { id); ?> name); ?> - item_id); ?> + + item_id, $rm2)) { + $rd = intval($rm2[4]); + echo '👑 LP: ' . esc_html($rm2[2]) . ' — ' . ($rd === 0 ? 'dauerhaft' : esc_html($rd) . ' Tage') . ''; + } elseif (preg_match('/^rank_(.+)_(\d+)$/', $item->item_id, $rm2)) { + $rd = intval($rm2[2]); + echo '👑 ' . esc_html($rm2[1]) . ' — ' . ($rd === 0 ? 'dauerhaft' : esc_html($rd) . ' Tage') . ''; + } else { + echo '' . esc_html($item->item_id) . ''; + } + ?> + price); ?> 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, @@ -2786,24 +2997,94 @@ 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 '
' + badge - + '
' + + '
' + '' + escHtml(item.name) + '' + '
' @@ -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(); ?>