get_charset_collate(); $tables = []; // Items $tables[] = "CREATE TABLE {$wpdb->prefix}wis_items ( id mediumint(9) NOT NULL AUTO_INCREMENT, item_id varchar(100) NOT NULL, name varchar(255) NOT NULL, description text, price int(11) DEFAULT 0, offer_price int(11) DEFAULT 0, is_offer tinyint(1) DEFAULT 0, is_daily_deal tinyint(1) DEFAULT 0, servers text, categories text, status varchar(20) DEFAULT 'draft', created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY item_id (item_id), KEY status (status) ) $charset_collate;"; // Orders $tables[] = "CREATE TABLE {$wpdb->prefix}wis_orders ( id mediumint(9) NOT NULL AUTO_INCREMENT, player_name varchar(100) NOT NULL, server varchar(100) NOT NULL, item_id varchar(100) NOT NULL, item_title varchar(255) NOT NULL, price int(11) NOT NULL, quantity int(11) DEFAULT 1, status varchar(20) DEFAULT 'pending', response text, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY player_name (player_name), KEY status (status) ) $charset_collate;"; // Coupons $tables[] = "CREATE TABLE {$wpdb->prefix}wis_coupons ( id mediumint(9) NOT NULL AUTO_INCREMENT, code varchar(50) NOT NULL, value int(11) NOT NULL, type varchar(10) DEFAULT 'fixed', usage_limit int(11) DEFAULT 1, used_count int(11) DEFAULT 0, expiry date DEFAULT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY code (code) ) $charset_collate;"; // Servers $tables[] = "CREATE TABLE {$wpdb->prefix}wis_servers ( id mediumint(9) NOT NULL AUTO_INCREMENT, slug varchar(100) NOT NULL, name varchar(255) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY slug (slug) ) $charset_collate;"; // Categories $tables[] = "CREATE TABLE {$wpdb->prefix}wis_categories ( id mediumint(9) NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, slug varchar(100) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY slug (slug) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); foreach ($tables as $sql) { dbDelta($sql); } } private static function set_default_options() { $defaults = [ 'wis_currency_name' => 'Coins', 'wis_image_base_url' => 'https://git.viper.ipv64.net/M_Viper/minecraft-items/raw/branch/main/images/', 'wis_header_text' => '✅ Auto-Bilder | 💰 Sicherer Checkout | 🎮 Ingame-Bestätigung', 'wis_coupon_exclude_offers' => '0', 'wis_daily_deal_enabled' => '0', 'wis_daily_deal_discount' => '20' ]; foreach ($defaults as $key => $value) { if (get_option($key) === false) { add_option($key, $value); } } } public static function run_daily_deal() { if (get_option('wis_daily_deal_enabled') !== '1') return; global $wpdb; $table = $wpdb->prefix . 'wis_items'; $discount = intval(get_option('wis_daily_deal_discount', 20)); // Reset old daily deal $wpdb->update($table, ['is_daily_deal' => 0], ['is_daily_deal' => 1]); // Select random item $item = $wpdb->get_row("SELECT * FROM $table WHERE status = 'publish' AND price > 0 ORDER BY RAND() LIMIT 1"); if ($item) { // Syntax Error Fix here: removed extra parent $offer_price = max(0, floor($item->price - ($item->price * ($discount / 100)))); $wpdb->update($table, [ 'is_daily_deal' => 1, 'is_offer' => 1, 'offer_price' => $offer_price ], ['id' => $item->id]); } } public static function reset_shop() { global $wpdb; $tables = [ 'wis_items', 'wis_orders', 'wis_coupons', 'wis_servers', 'wis_categories' ]; foreach ($tables as $table) { $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}$table"); } self::set_default_options(); return true; } } // =========================================================== // DATABASE HELPER // =========================================================== class WIS_DB { public static function get_items($args = []) { global $wpdb; $table = $wpdb->prefix . 'wis_items'; $where = isset($args['status']) ? $wpdb->prepare("WHERE status = %s", $args['status']) : "WHERE 1=1"; $limit = isset($args['limit']) ? "LIMIT " . intval($args['limit']) : ""; $orderby = isset($args['orderby']) ? "ORDER BY " . sanitize_text_field($args['orderby']) : "ORDER BY name ASC"; return $wpdb->get_results("SELECT * FROM $table $where $orderby $limit"); } public static function get_item($id) { global $wpdb; return $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wis_items WHERE id = %d", $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", $item_id )); } public static function insert_item($data) { global $wpdb; return $wpdb->insert($wpdb->prefix . 'wis_items', $data); } public static function update_item($id, $data) { global $wpdb; return $wpdb->update($wpdb->prefix . 'wis_items', $data, ['id' => $id]); } public static function delete_item($id) { global $wpdb; return $wpdb->delete($wpdb->prefix . 'wis_items', ['id' => $id]); } // Servers public static function get_servers() { global $wpdb; return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_servers ORDER BY name ASC"); } public static function insert_server($slug, $name) { global $wpdb; return $wpdb->insert($wpdb->prefix . 'wis_servers', [ 'slug' => sanitize_title($slug), 'name' => sanitize_text_field($name) ]); } public static function delete_server($id) { global $wpdb; return $wpdb->delete($wpdb->prefix . 'wis_servers', ['id' => $id]); } // Categories public static function get_categories() { global $wpdb; return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_categories ORDER BY name ASC"); } public static function insert_category($name) { global $wpdb; return $wpdb->insert($wpdb->prefix . 'wis_categories', [ 'name' => sanitize_text_field($name), 'slug' => sanitize_title($name) ]); } public static function delete_category($id) { global $wpdb; return $wpdb->delete($wpdb->prefix . 'wis_categories', ['id' => $id]); } // Coupons public static function get_coupons() { global $wpdb; return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_coupons ORDER BY created_at DESC"); } public static function get_coupon_by_code($code) { global $wpdb; return $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wis_coupons WHERE code = %s", strtoupper($code) )); } public static function insert_coupon($data) { global $wpdb; $data['code'] = strtoupper($data['code']); return $wpdb->insert($wpdb->prefix . 'wis_coupons', $data); } public static function update_coupon($id, $data) { global $wpdb; if (isset($data['code'])) { $data['code'] = strtoupper($data['code']); } return $wpdb->update($wpdb->prefix . 'wis_coupons', $data, ['id' => $id]); } public static function delete_coupon($id) { global $wpdb; return $wpdb->delete($wpdb->prefix . 'wis_coupons', ['id' => $id]); } // Orders public static function get_orders($limit = 100) { global $wpdb; return $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wis_orders ORDER BY created_at DESC LIMIT %d", $limit )); } public static function get_order($id) { global $wpdb; return $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wis_orders WHERE id = %d", $id )); } public static function insert_order($data) { global $wpdb; return $wpdb->insert($wpdb->prefix . 'wis_orders', $data); } public static function update_order_status($id, $status) { global $wpdb; return $wpdb->update( $wpdb->prefix . 'wis_orders', ['status' => $status], ['id' => $id] ); } public static function delete_order($id) { global $wpdb; return $wpdb->delete($wpdb->prefix . 'wis_orders', ['id' => $id]); } } // =========================================================== // ADMIN PAGES // =========================================================== class WIS_Admin { public static function register_menu() { add_menu_page( 'Ingame Shop', 'Ingame Shop', 'manage_options', 'wis_shop', [self::class, 'page_overview'], 'dashicons-cart', 6 ); add_submenu_page('wis_shop', 'Einstellungen', 'Einstellungen', 'manage_options', 'wis_shop'); add_submenu_page('wis_shop', 'Items', 'Items', 'manage_options', 'wis_items', [self::class, 'page_items']); add_submenu_page('wis_shop', 'Bestellungen', 'Bestellungen', 'manage_options', 'wis_orders', [self::class, 'page_orders']); add_submenu_page('wis_shop', 'Server', 'Server', 'manage_options', 'wis_servers', [self::class, 'page_servers']); add_submenu_page('wis_shop', 'Kategorien', 'Kategorien', 'manage_options', 'wis_categories', [self::class, 'page_categories']); add_submenu_page('wis_shop', 'Gutscheine', 'Gutscheine', 'manage_options', 'wis_coupons', [self::class, 'page_coupons']); add_submenu_page('wis_shop', 'JSON Export/Import', 'JSON Tools', 'manage_options', 'wis_json', [self::class, 'page_json']); add_submenu_page('wis_shop', 'Shop Reset', '🔄 Reset', 'manage_options', 'wis_reset', [self::class, 'page_reset']); add_submenu_page('wis_shop', 'Top Spender', 'Top Spender', 'manage_options', 'wis_top_spenders', [self::class, 'page_top_spenders']); } public static function page_overview() { // Handle settings save if (isset($_POST['wis_save_settings']) && check_admin_referer('wis_settings')) { update_option('wis_currency_name', sanitize_text_field($_POST['wis_currency_name'])); update_option('wis_image_base_url', esc_url_raw($_POST['wis_image_base_url'])); update_option('wis_header_text', sanitize_textarea_field($_POST['wis_header_text'])); update_option('wis_coupon_exclude_offers', isset($_POST['wis_coupon_exclude_offers']) ? '1' : '0'); update_option('wis_daily_deal_enabled', isset($_POST['wis_daily_deal_enabled']) ? '1' : '0'); update_option('wis_daily_deal_discount', intval($_POST['wis_daily_deal_discount'])); echo '

✅ Einstellungen gespeichert!

'; } global $wpdb; $stats = [ 'items' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_items"), 'orders' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_orders"), 'servers' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_servers"), 'coupons' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_coupons") ]; ?>

🛒 WP Ingame Shop Pro v

📊 Statistiken

Items im Shop:
Bestellungen:
Server:
Gutscheine:

⚙️ Einstellungen

Muss mit / enden! Z.B.: https://git.viper.ipv64.net/.../images/

Gutscheine bei Angeboten
Daily Deal

= 0) { $data['price'] = $new_price; } break; case 'offer': $is_offer = isset($_POST['bulk_is_offer']) ? 1 : 0; $data['is_offer'] = $is_offer; if (!$is_offer) { $data['offer_price'] = 0; } break; case 'status': $new_status = sanitize_text_field($_POST['bulk_status']); if (in_array($new_status, ['publish', 'draft'])) { $data['status'] = $new_status; } break; case 'server': $servers = isset($_POST['bulk_servers']) ? $_POST['bulk_servers'] : []; $data['servers'] = json_encode($servers); break; case 'category': $categories = isset($_POST['bulk_categories']) ? $_POST['bulk_categories'] : []; $data['categories'] = json_encode($categories); break; } if (!empty($data)) { WIS_DB::update_item($id, $data); $count++; } } echo '

✅ ' . $count . ' Items erfolgreich aktualisiert!

'; } } // 2. Bulk Apply: Zeigt das Formular für die gewählte Aktion an if (isset($_POST['wis_bulk_apply']) && !empty($_POST['wis_bulk_action']) && isset($_POST['item_ids'])) { $action = sanitize_text_field($_POST['wis_bulk_action']); $selected_ids = array_map('intval', $_POST['item_ids']); // Daten für Dropdowns laden $all_servers = WIS_DB::get_servers(); $all_categories = WIS_DB::get_categories(); ?>

📦 Mehrfachbearbeitung

Aktion: für Items.

Keine Server vorhanden.

Hake die Server an, denen die Items zugewiesen werden sollen (überschreibt aktuelle Zuweisung).

Keine Kategorien vorhanden.

Hake die Kategorien an (überschreibt aktuelle Zuweisung).

Abbrechen

✅ Item gelöscht!

'; } elseif ($_GET['action'] === 'toggle_status') { $item = WIS_DB::get_item($id); $new_status = ($item->status === 'publish') ? 'draft' : 'publish'; WIS_DB::update_item($id, ['status' => $new_status]); echo '

✅ Status geändert!

'; } } // Handle edit/add 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!

'; } else { WIS_DB::insert_item($data); echo '

✅ Item erstellt!

'; } } // Show form if edit or add if (isset($_GET['edit']) || isset($_GET['add'])) { $item = isset($_GET['edit']) ? WIS_DB::get_item(intval($_GET['edit'])) : null; $servers = WIS_DB::get_servers(); $categories = WIS_DB::get_categories(); $currency = get_option('wis_currency_name', 'Coins'); $item_servers = $item ? json_decode($item->servers, true) : []; $item_cats = $item ? json_decode($item->categories, true) : []; ?>

← Zurück zur Liste

Z.B.: minecraft:diamond

Optional: Wenn gesetzt, wird der normale Preis durchgestrichen

Markierungen
Server

Keine Server vorhanden. Server erstellen

Kategorien

Keine Kategorien vorhanden. Kategorien erstellen

Items Neu erstellen


ID Name Item ID Preis Status Aktionen
Noch keine Items vorhanden.
id); ?> name); ?> item_id); ?> price); ?> status === 'publish'): ?> ✅ Aktiv 📝 Entwurf Bearbeiten Löschen

✅ Server erstellt!

'; } // Handle delete if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') { check_admin_referer('wis_server_action', '_wpnonce'); WIS_DB::delete_server(intval($_GET['id'])); echo '

✅ Server gelöscht!

'; } $servers = WIS_DB::get_servers(); ?>

Server

Neuen Server erstellen

Kleinbuchstaben ohne Leerzeichen

Vorhandene Server

ID Name Slug Aktionen
Noch keine Server vorhanden.
id); ?> name); ?> slug); ?> Löschen

✅ Kategorie erstellt!

'; } // Handle delete if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') { check_admin_referer('wis_category_action', '_wpnonce'); WIS_DB::delete_category(intval($_GET['id'])); echo '

✅ Kategorie gelöscht!

'; } $categories = WIS_DB::get_categories(); ?>

Kategorien

Neue Kategorie erstellen

Vorhandene Kategorien

ID Name Slug Aktionen
Noch keine Kategorien vorhanden.
id); ?> name); ?> slug); ?> Löschen
sanitize_text_field($_POST['code']), 'value' => intval($_POST['value']), 'type' => sanitize_text_field($_POST['type']), 'usage_limit' => intval($_POST['usage_limit']), 'expiry' => !empty($_POST['expiry']) ? sanitize_text_field($_POST['expiry']) : null ]; if (isset($_GET['edit'])) { unset($data['used_count']); // Don't reset usage count WIS_DB::update_coupon(intval($_GET['edit']), $data); echo '

✅ Gutschein gespeichert!

'; } else { $data['used_count'] = 0; WIS_DB::insert_coupon($data); echo '

✅ Gutschein erstellt!

'; } } // Handle delete if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') { check_admin_referer('wis_coupon_action', '_wpnonce'); WIS_DB::delete_coupon(intval($_GET['id'])); echo '

✅ Gutschein gelöscht!

'; } // Show form if (isset($_GET['add']) || isset($_GET['edit'])) { global $wpdb; $coupon = isset($_GET['edit']) ? $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wis_coupons WHERE id = %d", intval($_GET['edit']))) : null; $currency = get_option('wis_currency_name', 'Coins'); ?>

← Zurück zur Liste

Z.B.: SUMMER20

Bei Festbetrag: Betrag in . Bei Prozent: Zahl ohne %

Optional

Gutscheine Neu erstellen

Code Rabatt Genutzt Gültig bis Aktionen
Noch keine Gutscheine vorhanden.
code); ?> type === 'percent'): ?> value); ?>% value); ?> used_count); ?> / usage_limit); ?> expiry ? esc_html(date('d.m.Y', strtotime($coupon->expiry))) : '∞'; ?> Bearbeiten Löschen

✅ Bestellung gelöscht!

'; } // Handle status change if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'complete') { check_admin_referer('wis_order_action', '_wpnonce'); WIS_DB::update_order_status(intval($_GET['id']), 'completed'); echo '

✅ Status geändert!

'; } // Show details if (isset($_GET['view'])) { $order = WIS_DB::get_order(intval($_GET['view'])); if (!$order) { echo '

Bestellung nicht gefunden.

'; return; } $currency = get_option('wis_currency_name', 'Coins'); $status_colors = [ 'pending' => '#ffc107', 'processing' => '#0073aa', 'completed' => 'green', 'cancelled' => 'red', 'failed' => 'red' ]; $status_labels = [ 'pending' => 'Warte auf Ingame', 'processing' => 'In Bearbeitung', 'completed' => 'Erledigt', 'cancelled' => 'Abgebrochen', 'failed' => 'Fehler' ]; $decoded = json_decode($order->response, true); ?>

Bestellung #id; ?> - Details

← Zurück
IDid); ?>
Datumcreated_at))); ?>
Spielerplayer_name); ?>
Serverserver); ?>
Zusammenfassungitem_title); ?>
Preisprice); ?>
Statusstatus] ?? $order->status; ?>
Details (JSON) response); ?>

Bestellungen

'Warte', 'processing' => 'Geben...', 'completed' => 'Fertig', 'cancelled' => 'Abgebrochen', 'failed' => 'Fehler' ]; $status_colors = [ 'pending' => '#ffc107', 'processing' => '#0073aa', 'completed' => 'green', 'cancelled' => 'red', 'failed' => 'red' ]; ?>
Datum Spieler Inhalt Preis Status Aktionen
Noch keine Bestellungen vorhanden.
created_at))); ?> player_name); ?> item_title, 0, 50)) . (strlen($order->item_title) > 50 ? '...' : ''); ?> price); ?> status] ?? $order->status; ?> 👁️ Details 🗑️ Löschen
'publish']); $img_base = get_option('wis_image_base_url', ''); $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 ]; } $json_output = json_encode($json_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); echo '

📦 JSON Export

'; echo '

✅ JSON erfolgreich generiert!

'; echo ''; echo '

'; echo ''; echo '

📤 Nächste Schritte:

'; echo '
    '; echo '
  1. Lade die JSON-Datei herunter
  2. '; echo '
  3. Gehe zu deinem Gitea Repository
  4. '; echo '
  5. Lade die items.json hoch unter: https://git.viper.ipv64.net/M_Viper/WP-Ingame-Shop-Pro
  6. '; echo '
  7. Klicke dann auf den Quick-Import Button unten!
  8. '; echo '
'; echo '
'; return; } // Default Gitea URL $default_url = 'https://git.viper.ipv64.net/M_Viper/WP-Ingame-Shop-Pro/raw/branch/main/items.json'; ?>

📦 JSON Export/Import

📤 JSON Export

Generiere eine JSON-Datei mit allen deinen Items für Gitea.

⚡ Quick-Import von Gitea

Importiert direkt von deinem Gitea Repository!

📥 JSON Import (Manuelle URL)

Importiere Items aus einer beliebigen JSON-URL.


✅ Shop wurde komplett zurückgesetzt!

'; } ?>

🔄 Shop Reset

⚠️ WARNUNG

Diese Aktion löscht ALLE Daten:

Diese Aktion kann NICHT rückgängig gemacht werden!

get_results(" SELECT player_name, SUM(price) as total_spent, COUNT(*) as order_count FROM {$wpdb->prefix}wis_orders WHERE status = 'completed' GROUP BY player_name ORDER BY total_spent DESC LIMIT 50 "); ?>

🏆 Top Spender

Spieler mit den höchsten Gesamtausgaben

Rang Spieler Ausgegeben Bestellungen
Noch keine Statistiken vorhanden.
# player_name); ?> total_spent)); ?> order_count); ?>
'POST', 'callback' => [self::class, 'import_json'], 'permission_callback' => '__return_true' ]); register_rest_route('wis/v1', '/order', [ 'methods' => 'POST', 'callback' => [self::class, 'create_order'], 'permission_callback' => '__return_true' ]); register_rest_route('wis/v1', '/validate_coupon', [ 'methods' => 'POST', 'callback' => [self::class, 'validate_coupon'], 'permission_callback' => '__return_true' ]); // =================== SPIGOT COMPATIBILITY ROUTES =================== // Get pending orders for a specific player (called by Spigot plugin) register_rest_route('wis/v1', '/pending_orders', [ 'methods' => 'GET', 'callback' => [self::class, 'get_pending_orders'], 'permission_callback' => '__return_true' ]); // Execute order (called when player clicks Yes in Spigot GUI) register_rest_route('wis/v1', '/execute_order', [ 'methods' => 'POST', 'callback' => [self::class, 'execute_order'], 'permission_callback' => '__return_true' ]); // Complete order (called after items given in Spigot) register_rest_route('wis/v1', '/complete_order', [ 'methods' => 'POST', 'callback' => [self::class, 'complete_order'], 'permission_callback' => '__return_true' ]); // Cancel order (called when player clicks No in Spigot GUI) register_rest_route('wis/v1', '/cancel_order', [ 'methods' => 'POST', 'callback' => [self::class, 'cancel_order'], 'permission_callback' => '__return_true' ]); } // --- SPIGOT ENDPOINTS --- public static function get_pending_orders($request) { global $wpdb; $player = sanitize_text_field($request->get_param('player')); if (!$player) { return new WP_REST_Response(['orders' => []]); } $results = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wis_orders WHERE player_name = %s AND status = 'pending' ORDER BY created_at ASC LIMIT 10", $player )); return new WP_REST_Response(['orders' => $results]); } public static function execute_order($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]); } public static function complete_order($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' => 'completed'], ['id' => $id] ); return new WP_REST_Response(['success' => true]); } public static function cancel_order($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]); } // --- EXISTING ENDPOINTS --- public static function import_json($request) { $data = $request->get_json_params(); $url = esc_url_raw($data['url'] ?? ''); if (!$url) { return new WP_REST_Response(['success' => false, 'message' => 'Keine URL angegeben'], 400); } $response = wp_remote_get($url, ['timeout' => 30]); if (is_wp_error($response)) { return new WP_REST_Response(['success' => false, 'message' => $response->get_error_message()], 400); } $body = wp_remote_retrieve_body($response); $json = json_decode($body, true); if (!isset($json['items']) || !is_array($json['items'])) { return new WP_REST_Response(['success' => false, 'message' => 'Ungültiges JSON Format'], 400); } $imported = 0; $skipped = 0; foreach ($json['items'] as $item) { $item_id = sanitize_text_field($item['id'] ?? ''); $name = sanitize_text_field($item['name'] ?? 'Unbekannt'); if (empty($item_id)) continue; $exists = WIS_DB::get_item_by_item_id($item_id); if ($exists) { $skipped++; continue; } WIS_DB::insert_item([ 'item_id' => $item_id, 'name' => $name, 'description' => sanitize_textarea_field($item['description'] ?? ''), 'price' => intval($item['price'] ?? 0), 'status' => intval($item['price'] ?? 0) > 0 ? 'publish' : 'draft', 'servers' => '[]', 'categories' => '[]' ]); $imported++; } return new WP_REST_Response(['success' => true, 'imported' => $imported, 'skipped' => $skipped]); } public static function create_order($request) { global $wpdb; $data = $request->get_json_params(); $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'])) : ''; if (!$player || empty($cart) || !$server) { return new WP_REST_Response(['success' => false, 'message' => 'Fehlende Daten'], 400); } $exclude_offers = get_option('wis_coupon_exclude_offers', '0'); $currency = get_option('wis_currency_name', 'Coins'); $valid_cart = []; $total_normal = 0; $total_offer = 0; foreach ($cart as $item_data) { $item = WIS_DB::get_item(intval($item_data['id'] ?? 0)); if (!$item || $item->status !== 'publish') continue; $qty = intval($item_data['quantity'] ?? 1); if ($qty <= 0) continue; $servers = json_decode($item->servers, true); if (!in_array($server, $servers ?: [])) continue; $price = $item->offer_price > 0 ? $item->offer_price : $item->price; $valid_cart[] = [ 'id' => $item->item_id, // Important: Spigot needs the item ID (e.g., minecraft:diamond) 'title' => $item->name, 'price' => $price, 'qty' => $qty, 'is_offer' => $item->is_offer ]; $item_total = $price * $qty; if ($item->is_offer && $exclude_offers === '1') { $total_offer += $item_total; } else { $total_normal += $item_total; } } if (empty($valid_cart)) { return new WP_REST_Response(['success' => false, 'message' => 'Keine gültigen Items'], 400); } // Coupon validation $coupon_discount = 0; $coupon_msg = ''; $coupon_applied = false; if (!empty($coupon_code)) { $coupon = WIS_DB::get_coupon_by_code($coupon_code); if ($coupon) { if ($coupon->expiry && date('Y-m-d') > $coupon->expiry) { $coupon_msg = 'Gutschein abgelaufen'; } elseif ($coupon->used_count >= $coupon->usage_limit) { $coupon_msg = 'Gutschein bereits aufgebraucht'; } else { if ($exclude_offers === '1' && $total_normal <= 0) { $coupon_msg = 'Gutschein gilt nicht für Angebote'; } else { if ($coupon->type === 'percent') { $coupon_discount = floor($total_normal * ($coupon->value / 100)); } else { $coupon_discount = $coupon->value; } WIS_DB::update_coupon($coupon->id, ['used_count' => $coupon->used_count + 1]); $coupon_applied = true; $coupon_msg = "Gutschein eingelöst: -{$coupon_discount} {$currency}"; } } } else { $coupon_msg = 'Ungültiger Code'; } } $final_price = max(0, $total_normal - $coupon_discount) + $total_offer; // Build order $items_payload = []; $title_parts = []; foreach ($valid_cart as $item) { $items_payload[] = [ 'id' => $item['id'], // minecraft:diamond '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] : [] ]; 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) ]); $msg = '✅ Bestellung erfolgreich!'; if ($coupon_msg) $msg .= ' (' . $coupon_msg . ')'; return new WP_REST_Response(['success' => true, 'message' => $msg]); } public static function validate_coupon($request) { $data = $request->get_json_params(); $code = sanitize_text_field(strtoupper($data['code'] ?? '')); $cart = $data['cart'] ?? []; if (!$code) { return new WP_REST_Response(['success' => false, 'message' => 'Kein Code']); } $coupon = WIS_DB::get_coupon_by_code($code); if (!$coupon) { return new WP_REST_Response(['success' => false, 'message' => 'Gutschein nicht gefunden']); } if ($coupon->expiry && date('Y-m-d') > $coupon->expiry) { return new WP_REST_Response(['success' => false, 'message' => 'Gutschein abgelaufen']); } if ($coupon->used_count >= $coupon->usage_limit) { return new WP_REST_Response(['success' => false, 'message' => 'Bereits aufgebraucht']); } $exclude_offers = get_option('wis_coupon_exclude_offers', '0'); if ($exclude_offers === '1' && !empty($cart)) { $has_normal = false; foreach ($cart as $item_data) { $item = WIS_DB::get_item(intval($item_data['id'] ?? 0)); if ($item && !$item->is_offer) { $has_normal = true; break; } } if (!$has_normal) { return new WP_REST_Response(['success' => false, 'message' => 'Gutschein gilt nicht für Angebote']); } } $currency = get_option('wis_currency_name', 'Coins'); $msg = $coupon->type === 'percent' ? "Gutschein gültig (-{$coupon->value}%)" : "Gutschein gültig (-{$coupon->value} {$currency})"; return new WP_REST_Response([ 'success' => true, 'type' => $coupon->type, 'value' => $coupon->value, 'message' => $msg ]); } } // =========================================================== // SHORTCODE - FRONTEND SHOP // =========================================================== class WIS_Shortcode { public static function register() { add_shortcode('ingame_shop_form', [self::class, 'render']); } public static function render() { $servers = WIS_DB::get_servers(); $items = WIS_DB::get_items(['status' => 'publish']); $categories = WIS_DB::get_categories(); $currency = get_option('wis_currency_name', 'Coins'); $img_base = get_option('wis_image_base_url', ''); $header_text = get_option('wis_header_text', ''); $exclude_offers = get_option('wis_coupon_exclude_offers', '0'); ob_start(); ?>

🛒 Ingame Shop

Keine Items im Shop verfügbar.
servers, true) ?: []; $cats_arr = json_decode($item->categories, true) ?: []; $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; $server_names = []; foreach ($servers_arr as $slug) { foreach ($servers as $s) { if ($s->slug === $slug) { $server_names[] = $s->name; break; } } } $servers_display = !empty($server_names) ? implode(', ', $server_names) : 'Kein Server'; ?>
is_daily_deal): ?>
🎁 Angebot des Tages
is_offer): ?>
🔥 Angebot
<?php echo esc_attr($item->name); ?>

name); ?>

description): ?>
description); ?>
price); ?>
📡

🛒 Dein Warenkorb

Dein Warenkorb ist leer
'Zeigt Daily Deal oder Angebot an'] ); } public function widget($args, $instance) { echo $args['before_widget']; if (!empty($instance['title'])) { echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title']; } global $wpdb; $currency = get_option('wis_currency_name', 'Coins'); $img_base = get_option('wis_image_base_url', ''); // Try daily deal first $item = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wis_items WHERE is_daily_deal = 1 AND status = 'publish' LIMIT 1"); // Fallback to regular offer if (!$item) { $item = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wis_items WHERE is_offer = 1 AND status = 'publish' ORDER BY updated_at DESC LIMIT 1"); } 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; $target_url = !empty($instance['shop_url']) ? $instance['shop_url'] : home_url(); ?>
is_daily_deal): ?>
🎁 DAILY DEAL
is_offer): ?>
🔥 ANGEBOT
<?php echo esc_attr($item->name); ?>

name); ?>

price); ?>
🛒

Kein Angebot verfügbar.

'; } echo $args['after_widget']; } public function form($instance) { $title = !empty($instance['title']) ? $instance['title'] : '🔥 Angebot des Tages'; $btn_text = !empty($instance['btn_text']) ? $instance['btn_text'] : 'Zum Shop'; $shop_url = !empty($instance['shop_url']) ? $instance['shop_url'] : ''; ?>