diff --git a/wp-ingame-shop/wp-ingame-shop-pro.php b/wp-ingame-shop/wp-ingame-shop-pro.php
new file mode 100644
index 0000000..066e818
--- /dev/null
+++ b/wp-ingame-shop/wp-ingame-shop-pro.php
@@ -0,0 +1,3585 @@
+ 'Cache erfolgreich geleert!']);
+ }
+
+ // Prüfe auf Updates (läuft im Admin-Hintergrund)
+ public static function check_for_update() {
+ $update_data = get_transient(self::$transient_name);
+
+ if (false === $update_data) {
+ $response = wp_remote_get(self::$api_url, ['timeout' => 10]);
+
+ if (is_wp_error($response)) {
+ return; // Fehler beim Abrufen, nichts tun
+ }
+
+ $body = wp_remote_retrieve_body($response);
+ $data = json_decode($body);
+
+ if (isset($data->tag_name) && isset($data->html_url)) {
+ // Entferne 'v' vom Tag (z.B. v2.1.3 -> 2.1.3)
+ $remote_version = ltrim($data->tag_name, 'v');
+
+ $update_data = [
+ 'new_version' => $remote_version,
+ 'url' => self::$update_url,
+ 'package_url' => isset($data->assets[0]->browser_download_url) ? $data->assets[0]->browser_download_url : '',
+ 'changelog' => isset($data->body) ? substr($data->body, 0, 200) . '...' : ''
+ ];
+
+ // Speichere für 12 Stunden
+ set_transient(self::$transient_name, $update_data, 12 * HOUR_IN_SECONDS);
+ }
+ }
+ }
+
+ // Zeige Admin Notice wenn Update verfügbar
+ public static function show_update_notice() {
+ $update_data = get_transient(self::$transient_name);
+ if ($update_data && version_compare(WIS_VERSION, $update_data['new_version'], '<')) {
+ ?>
+
+ $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_items WHERE status = 'publish'"),
+ 'orders' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_orders WHERE status = 'completed'"),
+ 'pending' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wis_orders WHERE status IN ('pending', 'claimed')"),
+ 'revenue' => $wpdb->get_var("SELECT SUM(price) FROM {$wpdb->prefix}wis_orders WHERE status = 'completed'"),
+ ];
+ $currency = get_option('wis_currency_name', 'Coins');
+
+ // Update Status bestimmen
+ $update_html = '✅ Aktuell (v' . WIS_VERSION . ') ';
+ if ($update_data && version_compare(WIS_VERSION, $update_data['new_version'], '<')) {
+ $update_html = '⚠️ Update verfügbar! ';
+ }
+
+ ?>
+
+
+
+
+
+ Items
+
+
+
+ Bestellungen
+
+
+
+ Offen
+
+
+
+ Umsatz ()
+
+
+
+
+ Status:
+
+
+
+
+
+
+
+
+
+ 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',
+ 'wis_api_key' => bin2hex(random_bytes(24)),
+ ];
+
+ foreach ($defaults as $key => $value) {
+ if (get_option($key) === false) {
+ add_option($key, $value);
+ }
+ }
+ }
+
+ public static function check_api_key($request) {
+ $key = $request->get_header('X-WIS-Key');
+ if (empty($key)) {
+ $key = $request->get_param('api_key');
+ }
+ $stored = get_option('wis_api_key', '');
+ return ($stored !== '' && hash_equals($stored, (string) $key));
+ }
+
+ public static function spigot_permission($request) {
+ if (!self::check_api_key($request)) {
+ return new WP_Error('wis_unauthorized', 'Ungültiger oder fehlender API-Key.', ['status' => 401]);
+ }
+ return true;
+ }
+
+ private static function create_default_categories() {
+ $default_categories = [
+ ['name' => 'Baublöcke', 'slug' => 'baublocke'],
+ ['name' => 'Dekorationsblöcke', 'slug' => 'dekorationsblocke'],
+ ['name' => 'Redstone', 'slug' => 'redstone'],
+ ['name' => 'Transport', 'slug' => 'transport'],
+ ['name' => 'Natur', 'slug' => 'natur'],
+ ['name' => 'Werkzeuge & Hilfsmittel', 'slug' => 'werkzeuge-hilfsmittel'],
+ ['name' => 'Kampf', 'slug' => 'kampf'],
+ ['name' => 'Nahrung & Tränke', 'slug' => 'nahrung-tranke'],
+ ['name' => 'Zutaten', 'slug' => 'zutaten'],
+ ['name' => 'Spawn-Eier', 'slug' => 'spawn-eier']
+ ];
+
+ global $wpdb;
+ foreach ($default_categories as $cat) {
+ $exists = $wpdb->get_var($wpdb->prepare(
+ "SELECT id FROM {$wpdb->prefix}wis_categories WHERE slug = %s",
+ $cat['slug']
+ ));
+
+ if (!$exists) {
+ $wpdb->insert($wpdb->prefix . 'wis_categories', [
+ 'name' => $cat['name'],
+ 'slug' => $cat['slug']
+ ]);
+ }
+ }
+ }
+
+ 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));
+
+ $wpdb->update($table, ['is_daily_deal' => 0], ['is_daily_deal' => 1]);
+
+ $item = $wpdb->get_row("SELECT * FROM $table WHERE status = 'publish' AND price > 0 ORDER BY RAND() LIMIT 1");
+
+ if ($item) {
+ $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();
+ self::create_default_categories();
+ return true;
+ }
+}
+
+// ===========================================================
+// ITEM CATEGORIZER
+// ===========================================================
+class WIS_Item_Categorizer {
+ public static function auto_categorize($item_id) {
+ $item_id = strtolower($item_id);
+ $item_id = str_replace('minecraft:', '', $item_id);
+
+ if (strpos($item_id, 'spawn_egg') !== false) {
+ return ['spawn-eier'];
+ }
+
+ if (preg_match('/(wooden|stone|iron|golden|diamond|netherite|copper)_(pickaxe|axe|shovel|hoe)/', $item_id)) {
+ return ['werkzeuge-hilfsmittel'];
+ }
+
+ if (in_array($item_id, [
+ 'shears', 'fishing_rod', 'flint_and_steel', 'bucket', 'water_bucket', 'lava_bucket',
+ 'milk_bucket', 'powder_snow_bucket', 'axolotl_bucket', 'cod_bucket', 'pufferfish_bucket',
+ 'salmon_bucket', 'tadpole_bucket', 'tropical_fish_bucket',
+ 'compass', 'recovery_compass', 'clock', 'spyglass', 'map', 'filled_map',
+ 'brush', 'lead', 'name_tag', 'saddle', 'carrot_on_a_stick', 'warped_fungus_on_a_stick'
+ ])) {
+ return ['werkzeuge-hilfsmittel'];
+ }
+
+ if (preg_match('/(wooden|stone|iron|golden|diamond|netherite|copper)_(sword|spear)/', $item_id)) {
+ return ['kampf'];
+ }
+
+ if (preg_match('/(leather|chainmail|iron|golden|diamond|netherite|copper|turtle)_(helmet|chestplate|leggings|boots|cap|tunic|pants|shell)/', $item_id)) {
+ return ['kampf'];
+ }
+
+ if (in_array($item_id, [
+ 'bow', 'crossbow', 'arrow', 'spectral_arrow', 'tipped_arrow',
+ 'shield', 'trident', 'mace',
+ 'totem_of_undying', 'elytra',
+ 'horse_armor', 'iron_horse_armor', 'golden_horse_armor', 'diamond_horse_armor',
+ 'wolf_armor'
+ ]) || strpos($item_id, 'horse_armor') !== false) {
+ return ['kampf'];
+ }
+
+ if (preg_match('/(raw_|cooked_)?(beef|porkchop|mutton|chicken|rabbit|cod|salmon)/', $item_id)) {
+ return ['nahrung-tranke'];
+ }
+
+ if (in_array($item_id, [
+ 'apple', 'golden_apple', 'enchanted_golden_apple',
+ 'melon_slice', 'glow_berries', 'sweet_berries', 'chorus_fruit',
+ 'carrot', 'golden_carrot', 'potato', 'baked_potato', 'poisonous_potato',
+ 'beetroot',
+ 'bread', 'cookie', 'cake', 'pumpkin_pie',
+ 'dried_kelp',
+ 'tropical_fish', 'pufferfish', 'rotten_flesh', 'spider_eye'
+ ])) {
+ return ['nahrung-tranke'];
+ }
+
+ if (strpos($item_id, '_stew') !== false || strpos($item_id, '_soup') !== false) {
+ return ['nahrung-tranke'];
+ }
+
+ if (strpos($item_id, 'potion') !== false || in_array($item_id, [
+ 'honey_bottle', 'milk_bucket', 'glass_bottle', 'dragon_breath',
+ 'experience_bottle', 'ominous_bottle'
+ ])) {
+ return ['nahrung-tranke'];
+ }
+
+ if (strpos($item_id, '_boat') !== false || strpos($item_id, '_raft') !== false) {
+ return ['transport'];
+ }
+
+ if (strpos($item_id, 'minecart') !== false) {
+ return ['transport'];
+ }
+
+ if (in_array($item_id, ['elytra', 'saddle', 'lead'])) {
+ return ['transport'];
+ }
+
+ if (strpos($item_id, 'redstone') !== false && $item_id !== 'redstone_ore') {
+ return ['redstone'];
+ }
+
+ if (in_array($item_id, [
+ 'repeater', 'comparator', 'observer',
+ 'piston', 'sticky_piston',
+ 'dispenser', 'dropper', 'hopper',
+ 'lever', 'tripwire_hook', 'daylight_detector',
+ 'tnt', 'target', 'lightning_rod'
+ ]) || strpos($item_id, 'button') !== false || strpos($item_id, 'pressure_plate') !== false) {
+ return ['redstone'];
+ }
+
+ if (strpos($item_id, '_rail') !== false || $item_id === 'rail') {
+ return ['redstone'];
+ }
+
+ $pure_materials = [
+ 'stick', 'coal', 'charcoal', 'diamond', 'emerald', 'lapis_lazuli',
+ 'iron_ingot', 'gold_ingot', 'copper_ingot', 'netherite_ingot',
+ 'iron_nugget', 'gold_nugget', 'copper_nugget',
+ 'raw_iron', 'raw_gold', 'raw_copper',
+ 'netherite_scrap', 'netherite_upgrade',
+ 'amethyst_shard', 'prismarine_shard', 'prismarine_crystals',
+ 'quartz', 'nether_quartz', 'echo_shard', 'disc_fragment',
+ 'string', 'feather', 'leather', 'rabbit_hide',
+ 'slimeball', 'ender_pearl', 'ender_eye',
+ 'blaze_rod', 'blaze_powder', 'magma_cream', 'ghast_tear',
+ 'nether_star', 'nether_brick',
+ 'nautilus_shell', 'heart_of_the_sea', 'scute', 'turtle_scute', 'armadillo_scute',
+ 'bone', 'bone_meal', 'gunpowder', 'glowstone_dust', 'sugar',
+ 'phantom_membrane', 'ink_sac', 'glow_ink_sac',
+ 'paper', 'book', 'flint',
+ 'fermented_spider_eye', 'glistering_melon_slice', 'rabbit_foot',
+ 'nether_wart', 'breeze_rod',
+ 'clay_ball', 'brick', 'firework_star',
+ 'shulker_shell', 'popped_chorus_fruit'
+ ];
+
+ if (in_array($item_id, $pure_materials)) {
+ return ['zutaten'];
+ }
+
+ if (strpos($item_id, '_pottery_sherd') !== false || strpos($item_id, '_armor_trim') !== false) {
+ return ['zutaten'];
+ }
+
+ if (in_array($item_id, [
+ 'dirt', 'coarse_dirt', 'rooted_dirt', 'grass_block', 'podzol', 'mycelium',
+ 'farmland', 'dirt_path',
+ 'sand', 'red_sand', 'gravel', 'clay',
+ 'suspicious_sand', 'suspicious_gravel'
+ ])) {
+ return ['natur'];
+ }
+
+ if (strpos($item_id, '_leaves') !== false || strpos($item_id, '_sapling') !== false ||
+ strpos($item_id, 'azalea') !== false) {
+ return ['natur'];
+ }
+
+ $flowers = [
+ 'dandelion', 'poppy', 'blue_orchid', 'allium', 'azure_bluet',
+ 'red_tulip', 'orange_tulip', 'white_tulip', 'pink_tulip',
+ 'oxeye_daisy', 'cornflower', 'lily_of_the_valley', 'wither_rose',
+ 'sunflower', 'lilac', 'rose_bush', 'peony',
+ 'pitcher_plant', 'pitcher_pod', 'torchflower', 'torchflower_seeds',
+ 'pink_petals', 'spore_blossom'
+ ];
+ if (in_array($item_id, $flowers)) {
+ return ['natur'];
+ }
+
+ if (strpos($item_id, 'mushroom') !== false || strpos($item_id, 'fungus') !== false ||
+ in_array($item_id, ['short_grass', 'tall_grass', 'fern', 'large_fern', 'dead_bush'])) {
+ return ['natur'];
+ }
+
+ if (in_array($item_id, [
+ 'seagrass', 'tall_seagrass', 'kelp', 'dried_kelp', 'sea_pickle',
+ 'vine', 'weeping_vines', 'twisting_vines', 'cave_vines', 'glow_lichen',
+ 'hanging_roots', 'mangrove_roots', 'muddy_mangrove_roots'
+ ])) {
+ return ['natur'];
+ }
+
+ if (strpos($item_id, '_seeds') !== false || in_array($item_id, [
+ 'wheat', 'beetroot', 'carrot', 'potato',
+ 'melon', 'pumpkin', 'carved_pumpkin',
+ 'sugar_cane', 'bamboo', 'cocoa_beans',
+ 'sweet_berries', 'glow_berries', 'sweet_berry_bush',
+ 'nether_wart', 'cactus',
+ 'mangrove_propagule'
+ ])) {
+ return ['natur'];
+ }
+
+ if (in_array($item_id, [
+ 'crimson_roots', 'warped_roots', 'nether_sprouts',
+ 'crimson_nylium', 'warped_nylium'
+ ])) {
+ return ['natur'];
+ }
+
+ if (in_array($item_id, [
+ 'moss_block', 'moss_carpet',
+ 'big_dripleaf', 'small_dripleaf',
+ 'lily_pad', 'bee_nest', 'honeycomb', 'honeycomb_block',
+ 'snow', 'snowball', 'powder_snow'
+ ])) {
+ return ['natur'];
+ }
+
+ if (strpos($item_id, 'glass') !== false && strpos($item_id, '_pane') === false) {
+ return ['dekorationsblocke'];
+ }
+ if (strpos($item_id, 'glass_pane') !== false || strpos($item_id, 'stained_glass_pane') !== false) {
+ return ['dekorationsblocke'];
+ }
+
+ if (strpos($item_id, '_door') !== false || strpos($item_id, '_trapdoor') !== false ||
+ strpos($item_id, '_fence_gate') !== false) {
+ return ['dekorationsblocke'];
+ }
+
+ if ((strpos($item_id, '_fence') !== false && strpos($item_id, '_fence_gate') === false) ||
+ (strpos($item_id, '_wall') !== false && !in_array($item_id, ['wall_banner', 'wall_sign', 'wall_torch'])) ||
+ $item_id === 'iron_bars') {
+ return ['dekorationsblocke'];
+ }
+
+ if (strpos($item_id, '_stairs') !== false || strpos($item_id, '_slab') !== false) {
+ return ['dekorationsblocke'];
+ }
+
+ if (strpos($item_id, '_carpet') !== false) {
+ return ['dekorationsblocke'];
+ }
+
+ if (in_array($item_id, [
+ 'torch', 'soul_torch', 'lantern', 'soul_lantern',
+ 'campfire', 'soul_campfire', 'end_rod',
+ 'shroomlight', 'froglight', 'sea_lantern'
+ ]) || strpos($item_id, '_candle') !== false || $item_id === 'candle') {
+ return ['dekorationsblocke'];
+ }
+
+ if (in_array($item_id, [
+ 'crafting_table', 'furnace', 'blast_furnace', 'smoker',
+ 'chest', 'trapped_chest', 'ender_chest', 'barrel',
+ 'enchanting_table', 'anvil', 'chipped_anvil', 'damaged_anvil',
+ 'grindstone', 'smithing_table', 'cartography_table', 'fletching_table',
+ 'loom', 'stonecutter', 'brewing_stand', 'cauldron', 'composter',
+ 'lectern', 'bookshelf', 'chiseled_bookshelf',
+ 'bell', 'beacon', 'conduit', 'lodestone', 'respawn_anchor'
+ ]) || strpos($item_id, '_bed') !== false || strpos($item_id, 'shulker_box') !== false) {
+ return ['dekorationsblocke'];
+ }
+
+ if (strpos($item_id, '_sign') !== false || strpos($item_id, '_hanging_sign') !== false ||
+ strpos($item_id, '_banner') !== false ||
+ in_array($item_id, ['item_frame', 'glow_item_frame', 'painting', 'armor_stand'])) {
+ return ['dekorationsblocke'];
+ }
+
+ if (in_array($item_id, [
+ 'ladder', 'scaffolding', 'chain',
+ 'flower_pot', 'decorated_pot',
+ 'dragon_egg', 'dragon_head',
+ 'note_block', 'jukebox'
+ ]) || strpos($item_id, '_head') !== false || strpos($item_id, '_skull') !== false ||
+ strpos($item_id, 'coral') !== false) {
+ return ['dekorationsblocke'];
+ }
+
+ if (in_array($item_id, [
+ 'stone', 'cobblestone', 'mossy_cobblestone',
+ 'granite', 'polished_granite', 'diorite', 'polished_diorite',
+ 'andesite', 'polished_andesite', 'calcite', 'tuff',
+ 'smooth_stone'
+ ]) || strpos($item_id, 'stone_brick') !== false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'deepslate') !== false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'brick') !== false && $item_id !== 'brick' && $item_id !== 'nether_brick') {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'sandstone') !== false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'quartz_') !== false && strpos($item_id, 'nether_quartz') === false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'prismarine') !== false || strpos($item_id, 'purpur') !== false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'concrete') !== false || strpos($item_id, 'terracotta') !== false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, '_wool') !== false) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, '_planks') !== false ||
+ (strpos($item_id, '_log') !== false && strpos($item_id, 'stripped') === false) ||
+ (strpos($item_id, '_wood') !== false && strpos($item_id, 'stripped') === false)) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'stripped_') !== false) {
+ return ['baublocke'];
+ }
+
+ if (in_array($item_id, ['bamboo_block', 'bamboo_mosaic', 'crimson_stem', 'warped_stem',
+ 'crimson_hyphae', 'warped_hyphae'])) {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, 'copper_') !== false && strpos($item_id, '_ingot') === false &&
+ strpos($item_id, '_nugget') === false && $item_id !== 'copper_door' && $item_id !== 'copper_trapdoor') {
+ return ['baublocke'];
+ }
+
+ if (strpos($item_id, '_block') !== false) {
+ return ['baublocke'];
+ }
+
+ if (in_array($item_id, [
+ 'netherrack', 'soul_sand', 'soul_soil',
+ 'basalt', 'polished_basalt', 'smooth_basalt',
+ 'end_stone', 'obsidian', 'crying_obsidian'
+ ]) || strpos($item_id, 'blackstone') !== false || strpos($item_id, 'end_stone_brick') !== false) {
+ return ['baublocke'];
+ }
+
+ if (in_array($item_id, [
+ 'glowstone', 'sponge', 'wet_sponge',
+ 'ice', 'packed_ice', 'blue_ice',
+ 'magma_block', 'slime_block', 'honey_block',
+ 'hay_block', 'dried_kelp_block',
+ 'mud', 'packed_mud', 'mud_bricks',
+ 'dripstone_block', 'amethyst_block', 'budding_amethyst'
+ ])) {
+ return ['baublocke'];
+ }
+
+ return ['baublocke'];
+ }
+}
+
+// ===========================================================
+// DATABASE HELPER
+// ===========================================================
+class WIS_DB {
+ public static function get_items($args = []) {
+ global $wpdb;
+ $table = $wpdb->prefix . 'wis_items';
+
+ $where_parts = ["1=1"];
+
+ if (isset($args['status'])) {
+ $where_parts[] = $wpdb->prepare("status = %s", $args['status']);
+ }
+
+ if (isset($args['category_slug']) && !empty($args['category_slug'])) {
+ $search_pattern = '%"' . $args['category_slug'] . '"%';
+ $where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern);
+ }
+
+ if (isset($args['ids']) && is_array($args['ids']) && !empty($args['ids'])) {
+ $ids = array_map('intval', $args['ids']);
+ $placeholders = implode(',', array_fill(0, count($ids), '%d'));
+ $where_parts[] = sprintf("id IN ($placeholders)", ...$ids);
+ }
+
+ if (isset($args['search']) && !empty($args['search'])) {
+ $search_like = '%' . $wpdb->esc_like($args['search']) . '%';
+ $where_parts[] = $wpdb->prepare("(name LIKE %s OR item_id LIKE %s)", $search_like, $search_like);
+ }
+
+ $where = implode(" AND ", $where_parts);
+ $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 $where $orderby $limit");
+ }
+
+ public static function count_items($args = []) {
+ global $wpdb;
+ $table = $wpdb->prefix . 'wis_items';
+ $where_parts = ["1=1"];
+
+ if (isset($args['status'])) {
+ $where_parts[] = $wpdb->prepare("status = %s", $args['status']);
+ }
+ if (isset($args['category_slug']) && !empty($args['category_slug'])) {
+ $search_pattern = '%"' . $args['category_slug'] . '"%';
+ $where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern);
+ }
+ if (isset($args['search']) && !empty($args['search'])) {
+ $search_like = '%' . $wpdb->esc_like($args['search']) . '%';
+ $where_parts[] = $wpdb->prepare("(name LIKE %s OR item_id LIKE %s)", $search_like, $search_like);
+ }
+
+ $where = implode(" AND ", $where_parts);
+ return (int) $wpdb->get_var("SELECT COUNT(*) FROM $table WHERE $where");
+ }
+
+ 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;
+
+ if (empty($data['categories']) || $data['categories'] === '[]') {
+ $auto_cats = WIS_Item_Categorizer::auto_categorize($data['item_id']);
+ $data['categories'] = json_encode($auto_cats);
+ }
+
+ 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]);
+ }
+
+ 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]);
+ }
+
+ 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]);
+ }
+
+ 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]);
+ }
+
+ 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() {
+ 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']));
+ update_option('wis_offline_queue_enabled', isset($_POST['wis_offline_queue_enabled']) ? '1' : '0');
+ echo '✅ Einstellungen gespeichert!
';
+ }
+
+ if (isset($_POST['wis_regen_key']) && check_admin_referer('wis_regen_key')) {
+ update_option('wis_api_key', bin2hex(random_bytes(24)));
+ echo '🔑 Neuer API-Key generiert! Bitte in der config.yml des Spigot-Plugins aktualisieren.
';
+ }
+
+ 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:
+
+
+
+
+
+
+
🔑 Spigot API-Key
+
Dieser Key muss in der config.yml des Spigot-Plugins als api-key eingetragen werden.
+
+
+ 📋 Kopieren
+
+
+
+ Geschützte Endpunkte: pending_orders, execute_order, complete_order, cancel_order, pending_offline
+
+
+
+ = 0) {
+ $data['price'] = $new_price;
+ }
+ }
+ break;
+
+ case 'offer':
+ $is_offer = isset($_POST['item_offers'][$id]) ? 1 : 0;
+ $data['is_offer'] = $is_offer;
+
+ if (isset($_POST['item_offer_prices'][$id])) {
+ $offer_price = intval($_POST['item_offer_prices'][$id]);
+ $data['offer_price'] = $is_offer ? $offer_price : 0;
+ } else 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':
+ if (isset($_POST['item_servers'][$id])) {
+ $data['servers'] = json_encode($_POST['item_servers'][$id]);
+ } else {
+ $data['servers'] = '[]';
+ }
+ break;
+
+ case 'category':
+ if (isset($_POST['item_cat_assignments'][$id])) {
+ $data['categories'] = json_encode($_POST['item_cat_assignments'][$id]);
+ }
+ break;
+ }
+
+ if (!empty($data)) {
+ WIS_DB::update_item($id, $data);
+ $count++;
+ }
+ }
+ echo '✅ ' . $count . ' Items erfolgreich aktualisiert!
';
+ }
+ }
+
+ 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']);
+
+ $all_servers = WIS_DB::get_servers();
+ $all_categories = WIS_DB::get_categories();
+ $currency = get_option('wis_currency_name', 'Coins');
+
+ $items_to_edit = WIS_DB::get_items(['ids' => $selected_ids]);
+
+ ?>
+
+
📦 Mehrfachbearbeitung
+
Aktion: für Items.
+
+
+
+ ✅ 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 '';
+ }
+ }
+
+ 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 '';
+ } else {
+ WIS_DB::insert_item($data);
+ echo '';
+ }
+ }
+
+ 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) : [];
+
+ if (!$item && isset($_GET['add'])) {
+ $item_cats = [];
+ }
+
+ ?>
+
+ 'publish'];
+ if (!empty($current_category)) $fetch_args['category_slug'] = $current_category;
+ if (!empty($search_query)) $fetch_args['search'] = $search_query;
+
+ $total_items = WIS_DB::count_items($fetch_args);
+ $total_pages = max(1, (int) ceil($total_items / $per_page));
+ $current_page = min($current_page, $total_pages);
+ $offset = ($current_page - 1) * $per_page;
+
+ global $wpdb;
+ $table_items = $wpdb->prefix . 'wis_items';
+ $where_parts = ["status = 'publish'"];
+ if (!empty($current_category)) {
+ $search_pattern = '%"' . $current_category . '"%';
+ $where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern);
+ }
+ 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);
+ }
+ $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
+ ));
+
+ $currency = get_option('wis_currency_name', 'Coins');
+
+ $base_url = admin_url('admin.php?page=wis_items');
+ if (!empty($current_category)) $base_url .= '&wis_category=' . urlencode($current_category);
+ if (!empty($search_query)) $base_url .= '&wis_search=' . urlencode($search_query);
+ ?>
+
+
+
+
+
+
+
+ Alle
+
+
+
+ name); ?>
+
+
+
+
+
+
+
+
+ Massenaktionen wählen
+
+ Massenaktionen
+ Preis ändern
+ Angebot ändern
+ Server zuweisen
+ Kategorie zuweisen
+ Aktivieren/Deaktivieren
+
+
+
+
+
+ 1): ?>
+ Einträge
+
+
+ Einträge
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
+
+ ✅ Server erstellt!
';
+ }
+
+ if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') {
+ check_admin_referer('wis_server_action', '_wpnonce');
+ WIS_DB::delete_server(intval($_GET['id']));
+ echo '';
+ }
+
+ $servers = WIS_DB::get_servers();
+ ?>
+
+
Server
+
+
+
Neuen Server erstellen
+
+
+
+
+
+
+
+
+
+
Vorhandene Server
+
+
+
+ ID
+ Name
+ Slug
+ Aktionen
+
+
+
+
+ Noch keine Server vorhanden.
+
+
+
+ id); ?>
+ name); ?>
+ slug); ?>
+
+ Löschen
+
+
+
+
+
+
+
+ ✅ Kategorie erstellt!
';
+ }
+
+ if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') {
+ check_admin_referer('wis_category_action', '_wpnonce');
+ WIS_DB::delete_category(intval($_GET['id']));
+ echo '';
+ }
+
+ $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']);
+ WIS_DB::update_coupon(intval($_GET['edit']), $data);
+ echo '';
+ } else {
+ $data['used_count'] = 0;
+ WIS_DB::insert_coupon($data);
+ echo '';
+ }
+ }
+
+ if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') {
+ check_admin_referer('wis_coupon_action', '_wpnonce');
+ WIS_DB::delete_coupon(intval($_GET['id']));
+ echo '';
+ }
+
+ 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');
+ ?>
+
+
+
+
+
+
+
+
+ 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!
';
+ }
+
+ 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 '';
+ }
+
+ 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'
+ ];
+
+ ?>
+
+
Bestellung #id; ?> - Details
+
← Zurück
+
+
+ ID id); ?>
+ Datum created_at))); ?>
+ Spieler player_name); ?>
+ Server server); ?>
+ Zusammenfassung item_title); ?>
+ Preis price); ?>
+ Status status] ?? $order->status; ?>
+
+ Details (JSON)
+ response); ?>
+
+
+
+
+
+
Bestellungen
+
+
+
+
+ Datum
+ Spieler
+ Inhalt
+ Preis
+ Status
+ Aktionen
+
+
+
+
+ Noch keine Bestellungen vorhanden.
+
+
+ 'Warte',
+ 'claimed' => '📡 Abgeholt',
+ 'processing' => 'Geben...',
+ 'completed' => 'Fertig',
+ 'cancelled' => 'Abgebrochen',
+ 'failed' => 'Fehler'
+ ];
+ $status_colors = [
+ 'pending' => '#ffc107',
+ 'claimed' => '#17a2b8',
+ 'processing' => '#0073aa',
+ 'completed' => 'green',
+ 'cancelled' => 'red',
+ 'failed' => 'red'
+ ];
+ ?>
+
+ 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 '
'.esc_textarea($json_output).' ';
+ echo '
💾 Als items.json herunterladen
';
+ echo '';
+ echo '
📤 Nächste Schritte: ';
+ echo '
';
+ echo 'Lade die JSON-Datei herunter ';
+ echo 'Gehe zu deinem Gitea Repository ';
+ echo 'Lade die items.json hoch unter: https://git.viper.ipv64.net/M_Viper/WP-Ingame-Shop-Pro ';
+ echo 'Klicke dann auf den Quick-Import Button unten! ';
+ echo ' ';
+ echo '
';
+ return;
+ }
+
+ $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!
+
+
+
+
+ ⚡ Quick-Import starten
+
+
+
+
+
+
📥 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:
+
+ ❌ Alle Items
+ ❌ Alle Bestellungen
+ ❌ Alle Gutscheine
+ ❌ Alle Server
+ ❌ Alle Kategorien
+
+
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',
+ ]);
+ register_rest_route('wis/v1', '/shop_items', [
+ 'methods' => 'GET',
+ 'callback' => [self::class, 'get_shop_items'],
+ 'permission_callback' => '__return_true',
+ ]);
+ register_rest_route('wis/v1', '/pending_orders', [
+ 'methods' => 'GET',
+ 'callback' => [self::class, 'get_pending_orders'],
+ 'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
+ ]);
+ register_rest_route('wis/v1', '/execute_order', [
+ 'methods' => 'POST',
+ 'callback' => [self::class, 'execute_order'],
+ 'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
+ ]);
+ register_rest_route('wis/v1', '/complete_order', [
+ 'methods' => 'POST',
+ 'callback' => [self::class, 'complete_order'],
+ 'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
+ ]);
+ register_rest_route('wis/v1', '/cancel_order', [
+ 'methods' => 'POST',
+ 'callback' => [self::class, 'cancel_order'],
+ 'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
+ ]);
+ register_rest_route('wis/v1', '/pending_offline', [
+ 'methods' => 'GET',
+ 'callback' => [self::class, 'get_pending_offline'],
+ 'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
+ ]);
+ register_rest_route('wis/v1', '/orders_history', [
+ 'methods' => 'GET',
+ 'callback' => [self::class, 'get_orders_history'],
+ 'permission_callback' => [WIS_Activator::class, 'spigot_permission'],
+ ]);
+ }
+
+ public static function get_shop_items($request) {
+ $page = max(1, intval($request->get_param('page') ?? 1));
+ $per_page = 24;
+ $category = sanitize_text_field($request->get_param('category') ?? '');
+ $search = sanitize_text_field($request->get_param('search') ?? '');
+
+ global $wpdb;
+ $table = $wpdb->prefix . 'wis_items';
+ $where_parts = ["status = 'publish'"];
+
+ if (!empty($category)) {
+ $search_pattern = '%"' . $category . '"%';
+ $where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern);
+ }
+ if (!empty($search)) {
+ $search_like = '%' . $wpdb->esc_like($search) . '%';
+ $where_parts[] = $wpdb->prepare("(name LIKE %s OR item_id LIKE %s)", $search_like, $search_like);
+ }
+
+ $where_sql = implode(" AND ", $where_parts);
+ $total = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table WHERE $where_sql");
+ $offset = ($page - 1) * $per_page;
+ $items = $wpdb->get_results($wpdb->prepare(
+ "SELECT * FROM $table WHERE $where_sql ORDER BY name ASC LIMIT %d OFFSET %d",
+ $per_page, $offset
+ ));
+
+ $img_base = get_option('wis_image_base_url', '');
+ $currency = get_option('wis_currency_name', 'Coins');
+
+ $result = [];
+ foreach ($items as $item) {
+ $img_name = str_replace(':', '_', $item->item_id) . '.png';
+ $result[] = [
+ 'id' => $item->id,
+ 'item_id' => $item->item_id,
+ 'name' => $item->name,
+ 'description' => $item->description,
+ 'price' => intval($item->price),
+ 'offer_price' => intval($item->offer_price),
+ 'is_offer' => (bool) $item->is_offer,
+ '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,
+ ];
+ }
+
+ return new WP_REST_Response([
+ 'items' => $result,
+ 'total' => $total,
+ 'page' => $page,
+ 'per_page' => $per_page,
+ 'total_pages' => max(1, (int) ceil($total / $per_page)),
+ 'currency' => $currency,
+ ]);
+ }
+
+ 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' => []]);
+ }
+
+ $table = $wpdb->prefix . 'wis_orders';
+
+ $results = $wpdb->get_results($wpdb->prepare(
+ "SELECT * FROM $table
+ WHERE player_name = %s AND status = 'pending'
+ ORDER BY created_at ASC LIMIT 5",
+ $player
+ ));
+
+ if (!empty($results)) {
+ $ids = implode(',', array_map(fn($o) => intval($o->id), $results));
+ $wpdb->query("UPDATE $table SET status = 'claimed' WHERE id IN ($ids) AND status = 'pending'");
+ }
+
+ return new WP_REST_Response(['orders' => $results]);
+ }
+
+ public static function get_pending_offline($request) {
+ if (get_option('wis_offline_queue_enabled', '0') !== '1') {
+ return new WP_REST_Response(['orders' => [], 'message' => 'Offline-Queue deaktiviert']);
+ }
+
+ global $wpdb;
+ $player = sanitize_text_field($request->get_param('player'));
+
+ if (!$player) {
+ return new WP_REST_Response(['orders' => []]);
+ }
+
+ $table = $wpdb->prefix . 'wis_orders';
+ $results = $wpdb->get_results($wpdb->prepare(
+ "SELECT * FROM $table
+ WHERE player_name = %s AND status = 'pending'
+ ORDER BY created_at ASC LIMIT 10",
+ $player
+ ));
+
+ if (!empty($results)) {
+ $ids = implode(',', array_map(fn($o) => intval($o->id), $results));
+ $wpdb->query("UPDATE $table SET status = 'claimed' WHERE id IN ($ids) AND status = 'pending'");
+ }
+
+ return new WP_REST_Response(['orders' => $results]);
+ }
+
+ public static function get_orders_history($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 id, item_title, price, status, created_at
+ FROM {$wpdb->prefix}wis_orders
+ WHERE player_name = %s
+ ORDER BY created_at DESC 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->query($wpdb->prepare(
+ "UPDATE {$wpdb->prefix}wis_orders SET status = 'processing'
+ WHERE id = %d AND status IN ('pending','claimed')",
+ $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]);
+ }
+
+ 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,
+ '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_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;
+
+ $items_payload = [];
+ $title_parts = [];
+
+ foreach ($valid_cart as $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] : []
+ ];
+
+ 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();
+ $categories = WIS_DB::get_categories();
+ $currency = get_option('wis_currency_name', 'Coins');
+ $header_text = get_option('wis_header_text', '');
+ $exclude_offers = get_option('wis_coupon_exclude_offers', '0');
+ $first_category = !empty($categories) ? $categories[0]->slug : '';
+
+ ob_start();
+ ?>
+
+
+
+
+
+
+
+
+
+ Alle Server
+
+ name); ?>
+
+
+
+
+ 🛒 Warenkorb
+ 0
+
+
+
+
+
+
+
+
+ name); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
🛒 Dein Warenkorb
+
+
Dein Warenkorb ist leer
+
+
+
+
🎫 Gutscheincode
+
+
+ Einlösen
+
+
+
+
+
+ Gesamt:
+ 0
+
+
+
+ -- Server wählen --
+
+ name); ?>
+
+
+
+
+
+
+ 💰 Kauf abschließen
+ Abbrechen
+
+
+
+
+
+
+
+
+ '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', '');
+
+ $item = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wis_items WHERE is_daily_deal = 1 AND status = 'publish' LIMIT 1");
+
+ 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
+
+
+
+
+
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'] : '';
+ ?>
+
+ Titel:
+
+
+
+ Button Text:
+
+
+
+ Shop URL:
+
+
+