From a2f3260854b805c29887b0c7ec2c6de53faaaba4 Mon Sep 17 00:00:00 2001 From: M_Viper Date: Sun, 15 Feb 2026 10:00:44 +0000 Subject: [PATCH] wp-ingame-shop/wp-ingame-shop.php aktualisiert --- wp-ingame-shop/wp-ingame-shop.php | 3746 +++++++++++++++++------------ 1 file changed, 2155 insertions(+), 1591 deletions(-) diff --git a/wp-ingame-shop/wp-ingame-shop.php b/wp-ingame-shop/wp-ingame-shop.php index 915f41a..e809d36 100644 --- a/wp-ingame-shop/wp-ingame-shop.php +++ b/wp-ingame-shop/wp-ingame-shop.php @@ -1,153 +1,38 @@ 10] - ); - - if ( ! is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response) ) { - $body = wp_remote_retrieve_body($response); - $data = json_decode($body, true); - - if ( $data && isset($data['tag_name']) ) { - $tag = ltrim( $data['tag_name'], 'vV' ); - - $release_info = [ - 'version' => $tag, - 'download_url' => $data['zipball_url'] ?? '', - 'notes' => $data['body'] ?? '', - 'published_at' => $data['published_at'] ?? '', - ]; - - set_transient( $transient_key, $release_info, 6 * HOUR_IN_SECONDS ); - } else { - set_transient( $transient_key, [], HOUR_IN_SECONDS ); - } - } else { - set_transient( $transient_key, [], HOUR_IN_SECONDS ); - } - } - - return $release_info; -} - -// Admin-Update-Hinweis anzeigen -function wis_show_update_notice() { - if ( ! current_user_can('manage_options') ) { - return; - } - - $current_version = wis_get_plugin_version(); - $latest_release = wis_get_latest_release_info(); - - if ( ! empty($latest_release['version']) && version_compare($current_version, $latest_release['version'], '<') ) { - - $refresh_url = wp_nonce_url( - admin_url('plugins.php?wis_clear_cache=1'), - 'wis_clear_cache_action' - ); - ?> -
-

WP Ingame Shop Pro – Update verfügbar

-

- Installiert:
- Neueste Version: -

-

- - Update herunterladen - - - Release Notes - - - Jetzt neu prüfen - -

-
- prefix . 'wis_orders'; - $coupon_table_name = $wpdb->prefix . 'wis_coupons'; $charset_collate = $wpdb->get_charset_collate(); - $sql = "CREATE TABLE $table_name ( + $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, @@ -172,567 +78,1377 @@ class WIS_Activator { quantity int(11) DEFAULT 1, status varchar(20) DEFAULT 'pending', response text, - created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL, - PRIMARY KEY (id) + created_at datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id), + KEY player_name (player_name), + KEY status (status) ) $charset_collate;"; - $sql2 = "CREATE TABLE $coupon_table_name ( + // 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', + 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 NOT NULL, - PRIMARY KEY (id) + 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'); - dbDelta($sql); - dbDelta($sql2); - - // Alte Installationen updaten (type Spalte hinzufügen) - $existing_columns = $wpdb->get_col_info("SELECT * FROM $coupon_table_name LIMIT 1"); - if(!in_array('type', $existing_columns)) { - $wpdb->query("ALTER TABLE $coupon_table_name ADD COLUMN type varchar(10) DEFAULT 'fixed'"); + foreach ($tables as $sql) { + dbDelta($sql); } } - public static function setup_daily_deal() { - // Initial setup beim ersten Aktivieren + 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') === '0') return; + if (get_option('wis_daily_deal_enabled') !== '1') return; global $wpdb; - $discount_percent = intval(get_option('wis_daily_deal_discount', 20)); + $table = $wpdb->prefix . 'wis_items'; + $discount = intval(get_option('wis_daily_deal_discount', 20)); - // 1. Aktuellen Daily Deal deaktivieren - $wpdb->update( - $wpdb->prefix.'postmeta', - ['meta_value' => 0], - ['meta_key' => '_wis_daily_deal', 'meta_value' => 1] + // 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] ); - - // 2. Zufälliges Item auswählen - $args = [ - 'post_type' => 'wis_item', - 'post_status' => 'publish', - 'posts_per_page' => 1, - 'meta_query' => [ - 'relation' => 'AND', - ['key' => '_wis_price', 'value' => 0, 'compare' => '>'], - ['key' => '_wis_daily_deal', 'compare' => 'NOT EXISTS'] // Eines holen, das noch kein Daily Deal ist - ] - ]; - $items = get_posts($args); - - if(!empty($items)) { - $item_id = $items[0]->ID; - $price = intval(get_post_meta($item_id, '_wis_price', true)); - - // Rabatt berechnen - $offer_price = max(0, floor($price - ($price * ($discount_percent / 100)))); - - // Flags setzen - update_post_meta($item_id, '_wis_daily_deal', 1); - update_post_meta($item_id, '_wis_is_offer', 1); - update_post_meta($item_id, '_wis_offer_price', $offer_price); - } + } + + public static function delete_order($id) { + global $wpdb; + return $wpdb->delete($wpdb->prefix . 'wis_orders', ['id' => $id]); } } // =========================================================== -// 2. ADMIN & CPT -// =========================================================== -class WIS_CPT { - public static function register_post_types() { - register_post_type('wis_item', [ - 'labels' => ['name' => 'Shop Items', 'singular_name' => 'Shop Item'], - 'public' => false, - 'show_ui' => true, - 'show_in_menu' => false, - 'show_in_admin_all_list' => true, - 'capability_type' => 'post', - 'capabilities' => [ - 'edit_post' => 'manage_options', - 'read_post' => 'manage_options', - 'delete_post' => 'manage_options', - 'edit_posts' => 'manage_options', - 'delete_posts' => 'manage_options', - 'delete_others_posts' => 'manage_options' - ], - 'supports' => ['title', 'editor'], - 'taxonomies' => ['wis_category'] - ]); - register_post_type('wis_server', [ - 'labels' => ['name' => 'Servers', 'singular_name' => 'Server'], - 'public' => false, - 'show_ui' => true, - 'show_in_menu' => false, - 'capability_type' => 'post', - 'supports' => ['title'] - ]); - register_post_type('wis_coupon', [ - 'labels' => ['name' => 'Gutscheine', 'singular_name' => 'Gutschein'], - 'public' => false, - 'show_ui' => true, - 'show_in_menu' => false, - 'capability_type' => 'post', - 'supports' => ['title'] - ]); - - // NEU: Kategorien Taxonomie - $labels = [ - 'name' => 'Kategorien', - 'singular_name' => 'Kategorie', - 'search_items' => 'Kategorien suchen', - 'all_items' => 'Alle Kategorien', - 'parent_item' => 'Übergeordnete Kategorie', - 'edit_item' => 'Kategorie bearbeiten', - 'update_item' => 'Kategorie aktualisieren', - 'add_new_item' => 'Neue Kategorie', - 'new_item_name' => 'Kategorie Name', - 'menu_name' => 'Kategorien', - 'popular_items' => 'Beliebte Kategorien', - 'separate_items_with_commas' => "Kategorien mit Kommas trennen", - 'add_or_remove_items' => 'Kategorien hinzufügen oder entfernen', - 'choose_from_most_used' => 'Häufigste Kategorien auswählen', - 'not_found' => 'Keine Kategorien gefunden' - ]; - $args = [ - 'hierarchical' => true, - 'labels' => $labels, - 'show_ui' => true, - 'show_in_menu' => true, // Erscheint als Menüpunkt - 'show_in_nav_menus' => false, - 'show_admin_column' => true, - 'public' => false, - 'rewrite' => false, - ]; - register_taxonomy('wis_category', 'wis_item', $args); - } - - public static function add_meta_boxes() { - add_meta_box('wis_item_meta', 'Item Einstellungen', [self::class, 'render_item_meta'], 'wis_item', 'normal', 'high'); - add_meta_box('wis_server_meta', 'Server Einstellungen', [self::class, 'render_server_meta'], 'wis_server', 'normal', 'high'); - add_meta_box('wis_coupon_meta', 'Gutschein Einstellungen', [self::class, 'render_coupon_meta'], 'wis_coupon', 'normal', 'high'); - } - - public static function render_item_meta($post) { - wp_nonce_field('wis_save_item', 'wis_item_nonce'); - $price = get_post_meta($post->ID,'_wis_price',true); - $item_id = get_post_meta($post->ID,'_wis_item_id',true); - $servers = get_post_meta($post->ID,'_wis_servers',true); - if(!is_array($servers)) $servers = []; - - $is_offer = get_post_meta($post->ID,'_wis_is_offer',true); - $is_daily_deal = get_post_meta($post->ID,'_wis_daily_deal',true); - $offer_price = get_post_meta($post->ID,'_wis_offer_price',true); - $manual_daily = get_post_meta($post->ID,'_wis_manual_daily_deal',true); - - $all_servers = get_posts(['post_type'=>'wis_server','numberposts'=>-1]); - $currency = get_option('wis_currency_name', 'Coins'); - $exclude_offers = get_option('wis_coupon_exclude_offers'); - - // NEU: Kategorien - $cats = wp_get_object_terms($post->ID, 'wis_category'); - $cat_ids = array_map(function($t) { return $t->term_id; }, $cats); - - $current_status = get_post_status($post->ID); - $is_active = ($current_status === 'publish') && ($price > 0); - $status_msg = $is_active ? '✅ Aktiv im Shop' : '⏸️ Inaktiv (Kein Preis oder Entwurf)'; - - echo '

'.$status_msg.'

'; - echo '

'; - echo '

Wird automatisch aus dem Post-Titel übernommen

'; - - echo '

'; - echo '

Wenn du hier einen Preis einträgst (>0), wird das Item automatisch aktiv.

'; - - echo '

'; - echo '

✅ Daraus wird automatisch das Bild generiert.

'; - - // NEU: Kategorie Auswahl - echo '

'; - $terms = get_terms([ - 'taxonomy' => 'wis_category', - 'hide_empty' => false, - ]); - echo '

'; - if(!empty($terms)) { - foreach($terms as $term) { - $selected = in_array($term->term_id, $cat_ids) ? 'checked' : ''; - echo ''; - } - } else { - echo 'Noch keine Kategorien erstellt.'; - } - echo '

'; - - echo '
'; - echo '

'; - echo '

'; - echo '
Überschreibt die Automatik bis Mitternacht. Praktisch zum Testen.'; - if($is_daily_deal) { - echo '
ℹ️ Info: Dieses Item ist aktuell das Angebot des Tages. '; - echo 'Der Rabatt wurde automatisch berechnet.'; - } - echo '

'; - - echo '
'; - echo '

'; - echo '

'; - - echo '
Hervorgehobenes Item im Shop (rot/gold Badge).'; - - if($exclude_offers) { - echo '
Hinweis: Gutscheine sind aktuell global für Angebote deaktiviert.'; - } - - echo '

'; - echo '

'; - echo ''; - echo '
Wenn ausgefüllt, wird der normale Preis durchgestrichen und dieser angezeigt.

'; - echo '
'; - - echo '

'; - echo '

Dies ist der lange Text, der unter dem Titel im Shop angezeigt wird.

'; - - echo '

'; - echo '

'; - if(empty($all_servers)) echo 'Noch keine Server erstellt.'; - foreach($all_servers as $s){ - $checked = in_array($s->post_name, $servers) ? 'checked' : ''; - echo ''; - } - echo '

'; - } - - public static function render_server_meta($post){ - echo '

'; - echo 'Info: Da keine RCON-Verbindung benötigt wird (Vault/Plugin bestätigt), sind hier keine weiteren Einstellungen nötig.
'; - echo 'Der Servername dient nur zur Identifikat im Shop-Frontend.'; - echo '

'; - } - - public static function render_coupon_meta($post) { - wp_nonce_field('wis_save_coupon', 'wis_coupon_nonce'); - $code = get_post_meta($post->ID,'_wis_code',true); - $value = get_post_meta($post->ID,'_wis_value',true); - $limit = get_post_meta($post->ID,'_wis_usage_limit',true); - $expiry = get_post_meta($post->ID,'_wis_expiry',true); - $type = get_post_meta($post->ID,'_wis_type',true); - $exclude_offers = get_option('wis_coupon_exclude_offers'); - - if(empty($type)) $type = 'fixed'; - - echo '

'; - echo ''; - - echo '

'; - echo ''; - - echo '

'; - echo ''; - - if($exclude_offers) { - echo '

'; - echo '⚠️ Achtung: In den Shop-Einstellungen ist aktiviert, dass Gutscheine nicht auf Angebot-Items (Sale) angewendet werden. Dieser Gutschein wirkt nur auf reguläre Items.'; - echo '

'; - } - - echo '

'; - echo ''; - - echo '

'; - echo ''; - } - - public static function save_meta($post_id){ - if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return; - - if(get_post_type($post_id)==='wis_item' && isset($_POST['wis_item_nonce']) && wp_verify_nonce($_POST['wis_item_nonce'],'wis_save_item')){ - update_post_meta($post_id,'_wis_price',intval($_POST['wis_price'])); - update_post_meta($post_id,'_wis_item_id',sanitize_text_field($_POST['wis_item_id'])); - - $is_offer = isset($_POST['wis_is_offer']) ? 1 : 0; - update_post_meta($post_id,'_wis_is_offer', $is_offer); - update_post_meta($post_id,'_wis_offer_price', intval($_POST['wis_offer_price'])); - - // NEU: Manual Daily Deal Logic - $manual_daily = isset($_POST['wis_manual_daily_deal']) ? 1 : 0; - if($manual_daily) { - update_post_meta($post_id,'_wis_daily_deal', 1); - update_post_meta($post_id,'_wis_is_offer', 1); - } else { - // Wenn manuell abgewählt, löschen wir das Flag, damit der Cron ran darf - // update_post_meta($post_id,'_wis_daily_deal', 0); // Optional: Reset flag - } - - $servers = isset($_POST['wis_servers']) && is_array($_POST['wis_servers']) ? array_map('sanitize_text_field', $_POST['wis_servers']) : []; - update_post_meta($post_id,'_wis_servers', $servers); - - $cats = isset($_POST['wis_cats']) ? array_map('intval', $_POST['wis_cats']) : []; - wp_set_object_terms($post_id, $cats, 'wis_category'); - } - if(get_post_type($post_id)==='wis_server' && isset($_POST['wis_server_nonce']) && wp_verify_nonce($_POST['wis_server_nonce'],'wis_save_server')){ - // Nichts zu tun - } - if(get_post_type($post_id)==='wis_coupon' && isset($_POST['wis_coupon_nonce']) && wp_verify_nonce($_POST['wis_coupon_nonce'],'wis_save_coupon')){ - $code = sanitize_text_field(strtoupper($_POST['wis_code'])); - $value = intval($_POST['wis_value']); - $limit = intval($_POST['wis_usage_limit']); - $expiry = sanitize_text_field($_POST['wis_expiry']); - $type = sanitize_text_field($_POST['wis_type']); - if(!in_array($type, ['fixed', 'percent'])) $type = 'fixed'; - - update_post_meta($post_id,'_wis_code', $code); - update_post_meta($post_id,'_wis_value', $value); - update_post_meta($post_id,'_wis_type', $type); - update_post_meta($post_id,'_wis_usage_limit', $limit); - update_post_meta($post_id,'_wis_expiry', $expiry); - - global $wpdb; - $table_name = $wpdb->prefix . 'wis_coupons'; - - $data = ['code' => $code, 'value' => $value, 'type' => $type, 'usage_limit' => $limit, 'expiry' => $expiry]; - - $existing = $wpdb->get_row($wpdb->prepare("SELECT id FROM $table_name WHERE code = %s", $code)); - - if($existing) { - $wpdb->update($table_name, $data, ['id' => $existing->id]); - } else { - $wpdb->insert($table_name, $data); - } - - $db_coupon = $wpdb->get_row($wpdb->prepare("SELECT used_count FROM $table_name WHERE code = %s", $code)); - if($db_coupon) { - update_post_meta($post_id, '_wis_used_count', $db_coupon->used_count); - } - } - } - - public static function auto_update_status($post_id) { - static $processing = []; - if (isset($processing[$post_id])) return; - $processing[$post_id] = true; - if (get_post_type($post_id) != 'wis_item') { - unset($processing[$post_id]); - return; - } - $price = get_post_meta($post_id, '_wis_price', true); - $current_status = get_post_status($post_id); - $new_status = ($price > 0) ? 'publish' : 'draft'; - if ($current_status !== $new_status) { - remove_action('save_post', [__CLASS__, 'auto_update_status'], 10); - wp_update_post(['ID' => $post_id, 'post_status' => $new_status]); - add_action('save_post', [__CLASS__, 'auto_update_status'], 10); - } - unset($processing[$post_id]); - } - - public static function delete_coupon_from_table($post_id) { - if(get_post_type($post_id) != 'wis_coupon') return; - $code = get_post_meta($post_id, '_wis_code', true); - if($code) { - global $wpdb; - $wpdb->delete($wpdb->prefix . 'wis_coupons', ['code' => $code]); - } - } -} - -// =========================================================== -// Bulk Delete Funktionalität -// =========================================================== -class WIS_Bulk_Actions { - public static function register_bulk_actions($bulk_actions) { - $bulk_actions['delete'] = __('Löschen', 'wis'); - return $bulk_actions; - } - public static function handle_bulk_actions($redirect_to, $action, $post_ids) { - if ($action !== 'delete') return $redirect_to; - $deleted = 0; - foreach ($post_ids as $post_id) { - if (current_user_can('delete_post', $post_id)) { - wp_delete_post($post_id, true); - $deleted++; - } - } - if ($deleted > 0) { - $redirect_to = add_query_arg([ - 'bulk_deleted' => $deleted, - 'post_type' => get_post_type($post_ids[0] ?? 0) - ], $redirect_to); - } - return $redirect_to; - } - public static function admin_notices() { - if (!empty($_GET['bulk_deleted'])) { - $count = intval($_GET['bulk_deleted']); - $msg = sprintf(_n('%d Eintrag gelöscht.', '%d Einträge gelöscht.', $count, 'wis'), $count); - echo '

✅ ' . esc_html($msg) . '

'; - } - } -} - -// =========================================================== -// 3. ADMIN MENU +// 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_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']); - add_submenu_page('wis_shop', 'Items', 'Items', 'manage_options', 'edit.php?post_type=wis_item'); - add_submenu_page('wis_shop', 'Kategorien', 'Kategorien', 'manage_options', 'edit-tags.php?taxonomy=wis_category'); - add_submenu_page('wis_shop', 'Servers', 'Servers', 'manage_options', 'edit.php?post_type=wis_server'); - add_submenu_page('wis_shop', 'Gutscheine', 'Gutscheine', 'manage_options', 'edit.php?post_type=wis_coupon'); } - + public static function page_overview() { - if(isset($_POST['wis_save_settings']) && check_admin_referer('wis_settings_nonce')) { + // 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', sanitize_text_field($_POST['wis_image_base_url'])); + 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'); - - // NEU: Daily Deal Settings 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!

'; } - $currency = get_option('wis_currency_name', 'Coins'); - $img_base = get_option('wis_image_base_url', 'https://assets.minecraft-ids.com/1_21_10/'); - $header_text = get_option('wis_header_text', '✅ Auto-Bilder | 💰 Sicherer Checkout'); - $exclude_offers = get_option('wis_coupon_exclude_offers', '0'); - // NEU: Daily Deal Settings - $daily_deal_enabled = get_option('wis_daily_deal_enabled', '0'); - $daily_deal_discount = get_option('wis_daily_deal_discount', '20'); - - echo '

🛒 Ingame Shop Pro v1.0.0

'; - - echo '

✅ Feature Übersicht

    '; - echo '
  • 🛒 Warenkorb: Kauf mehrerer Items auf einmal.
  • '; - echo '
  • 🔗 Einzelne Bestellung: Alles wird in einer einzigen Datenbankzeile gespeichert.
  • '; - echo '
  • 📋 Detail-Anzeige: Im Backend siehst du genau "1x Diamant, 64x Stein" etc. & Gutschein.
  • '; - echo '
  • Sauberer Prozess: Alle Items werden sofort nach einer Bestätigung ausgegeben.
  • '; - echo '
  • 🔥 Angebote: Items können hervorgehoben werden.
  • '; - echo '
  • 🎁 Daily Deal: Automatisches Angebot des Tages.
  • '; - echo '
  • 🎫 Smart Coupons: Gutscheine (Festbetrag & Prozent) werden korrekt bei reinen Angeboten ignoriert.
  • '; - echo '
  • 🏷️ Kategorien: Items können in Kategorien gruppiert werden.
  • '; - echo '
  • 🏆 Top Spender: Statistiken im Backend.
  • '; - echo '
'; + 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") + ]; - echo '
'; - echo '

⚙️ Globale Einstellungen

'; - echo '
'; - wp_nonce_field('wis_settings_nonce'); - echo ''; - - echo ''; - echo ''; - - echo ''; - echo ''; - - echo ''; - echo ''; - - echo ''; - echo ''; - - // NEU: Daily Deal Settings - echo ''; - echo ''; - - echo ''; - echo ''; - - echo '
'; - echo '

Der Text, der ganz oben im Shop angezeigt wird.
Hinweis: Wenn dieses Feld leer ist, wird auch kein grüner Balken im Shop angezeigt.

'; - echo '

Wird für die Bildgenerierung verwendet.

'; - echo '

Wenn aktiv, wird der Rabatt nur auf den Warenkorbwert der regulären Items berechnet. Angebote werden vollgezahlt.

'; - echo '

Wenn aktiv, wird jeden Tag um Mitternacht ein zufälliges Item als "Angebot des Tages" markiert mit einem Rabatt.

'; - echo '
'; - echo '

Der Prozentsatz, um den der Preis gesenkt wird (z.B. 20 für 20%).

'; - echo '

'; - echo '
'; - echo '
'; - - echo '
'; - echo '

🚀 Bulk Import

'; - echo '

Smart Import: Lädt Items in Paketen (20 pro Durchlauf). Vorhandene Items werden übersprungen.

'; - echo '
'; - echo ''; - echo ''; - echo '
'; - echo ''; - echo ''; - echo '
'; - echo ''; - echo '
'; ?> - '; + } + + public static function page_servers() { + // Handle add + if (isset($_POST['wis_add_server'])) { + check_admin_referer('wis_server_form'); + WIS_DB::insert_server($_POST['slug'], $_POST['name']); + echo '

✅ 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

+ + + + + + + + + + + + + + + + + + + + + + + +
IDNameSlugAktionen
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

+ + + + + + + + + + + + + + + + + + + + + + + +
IDNameSlugAktionen
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

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeRabattGenutztGültig bisAktionen
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' + ]; + ?> + + + + + + + + + + + +
DatumSpielerInhaltPreisStatusAktionen
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:

+
    +
  • ❌ 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' OR status = 'cancelled' + WHERE status = 'completed' GROUP BY player_name ORDER BY total_spent DESC LIMIT 50 "); - echo '

🏆 Top Spender

'; - echo '

Hier siehst du die Spieler, die insgesamt am meisten in deinem Shop ausgegeben haben.

'; - - echo ''; - echo ''; - - if(empty($results)) { - echo ''; - } else { - $rank = 1; - foreach($results as $row) { - $total = intval($row->total_spent); - $count = intval($row->order_count); - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - } - - echo '
RangSpielerAusgegeben (Total)Anzahl Bestellungen
Noch keine Statistiken vorhanden.
#' . esc_html($rank++) . '' . esc_html($row->player_name) . '' . esc_html($total) . ' ' . esc_html($currency) . '' . esc_html($count) . '
'; - echo '
'; - } - - public static function page_orders() { - global $wpdb; - $currency = get_option('wis_currency_name', 'Coins'); - - if(isset($_GET['action']) && isset($_GET['order_id']) && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'wis_order_action')) { - $action = sanitize_text_field($_GET['action']); - $id = intval($_GET['order_id']); - if($action === 'delete') { $wpdb->delete($wpdb->prefix.'wis_orders', ['id' => $id]); echo '

✓ Bestellung gelöscht.

'; } - elseif($action === 'complete') { $wpdb->update($wpdb->prefix.'wis_orders', ['status' => 'completed'], ['id' => $id]); echo '

✓ Manuell erledigt.

'; } - } - - if(isset($_GET['order_id'])) { - $order = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wis_orders WHERE id = %d", intval($_GET['order_id']))); - if($order) { - $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']; - $status_label = $status_labels[$order->status] ?? $order->status; - $status_color = $status_colors[$order->status] ?? 'red'; - - $items_list = 'Keine Daten'; - $coupon_row = 'Kein Gutschein'; - $json_data = $order->response; - $decoded = json_decode($json_data, true); - - if(is_array($decoded)) { - if(isset($decoded['items']) && is_array($decoded['items'])) { - $items_list = ''; - - if(isset($decoded['coupon']) && !empty($decoded['coupon']['code'])) { - $code = esc_html($decoded['coupon']['code']); - $disc = intval($decoded['coupon']['discount']); - $coupon_row = "{$code} (-{$disc} {$currency})"; - } - } elseif(!empty($decoded)) { - $items_list = ''; - } - } - - echo '

Bestellung #'.$order->id.' - Details

'; - echo '← Zurück

'; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
ID'.$order->id.'
Datum'.date('d.m.Y H:i', strtotime($order->created_at)).'
Spieler'.$order->player_name.'
Server'.$order->server.'
Zusammenfassung'.esc_html($order->item_title).'
Gutschein'.$coupon_row.'
Gekaufte Items'.$items_list.'
Gesamtpreis'.$order->price.' '.esc_html($currency).'
Status'.esc_html($status_label).'
JSON (Debug)'.esc_html($json_data).'
'; - echo '
'; - return; - } - } - - $orders = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_orders ORDER BY created_at DESC LIMIT 100"); - echo '

Bestellungen

'; - echo ''; - - if(empty($orders)) { echo ''; } - - foreach($orders as $o){ - $status_map = ['pending' => 'Warte', 'processing' => 'Geben...', 'completed' => 'Fertig', 'cancelled' => 'Abgebrochen', 'failed' => 'Fehler']; - $status_label = $status_map[$o->status] ?? $o->status; - $status_colors = ['pending' => '#ffc107', 'processing' => '#0073aa', 'completed' => 'green', 'cancelled' => 'red', 'failed' => 'red']; - $status_color = $status_colors[$o->status] ?? 'red'; - - $delete_url = wp_nonce_url(admin_url('admin.php?page=wis_orders&action=delete&order_id='.$o->id), 'wis_order_action'); - $details_url = admin_url('admin.php?page=wis_orders&order_id='.$o->id); + ?> +
+

🏆 Top Spender

+

Spieler mit den höchsten Gesamtausgaben

- $item_label = strlen($o->item_title) > 50 ? substr($o->item_title, 0, 50).'...' : $o->item_title; - - echo '
'; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - echo '
DatumSpielerInhaltPreisStatusAktion
Noch keine Bestellungen vorhanden.
'.esc_html(date('d.m.Y H:i', strtotime($o->created_at))).''.esc_html($o->player_name).''.esc_html($item_label).''.esc_html($o->price).' '.esc_html($currency).''.esc_html($status_label).''; - echo '👁️ Details '; - echo '🗑️ Löschen'; - echo '
'; + + + + + + + + + + + + + + + + + + + + + + + +
RangSpielerAusgegebenBestellungen
Noch keine Statistiken vorhanden.
#player_name); ?>total_spent)); ?> order_count); ?>
+ + 'POST','callback'=>[self::class,'create_order'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/pending_orders', ['methods'=>'GET','callback'=>[self::class,'get_pending_orders'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/execute_order', ['methods'=>'POST','callback'=>[self::class,'execute_order'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/complete_order', ['methods'=>'POST','callback'=>[self::class,'complete_order'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/cancel_order', ['methods'=>'POST','callback'=>[self::class,'cancel_order'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/fetch_remote_data', ['methods'=>'POST','callback'=>[self::class,'fetch_remote_data'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/import_batch', ['methods'=>'POST','callback'=>[self::class,'import_batch'],'permission_callback'=> '__return_true']); - register_rest_route('wis/v1','/validate_coupon', ['methods'=>'POST','callback'=>[self::class,'validate_coupon'],'permission_callback'=> '__return_true']); - } - - public static function create_order($request) { - global $wpdb; - $data = $request->get_json_params(); - $player = sanitize_text_field($data['player'] ?? ''); - $cart = $data['cart'] ?? []; - $server_slug = sanitize_text_field($data['server'] ?? ''); - $coupon_code = isset($data['coupon_code']) ? sanitize_text_field(strtoupper($data['coupon_code'])) : ''; - - if(!$player || empty($cart) || !$server_slug) { return new WP_REST_Response(['success'=>false,'message'=>'Fehlende Eingabedaten'], 400); } - - $exclude_offers_setting = get_option('wis_coupon_exclude_offers', '0'); - - $valid_cart = []; - $total_normal = 0; - $total_offer = 0; - - foreach($cart as $item) { - $post_id = intval($item['id'] ?? 0); - $qty = intval($item['quantity'] ?? 1); - if($post_id <= 0 || $qty <= 0) continue; - - $price = intval(get_post_meta($post_id, '_wis_price', true)); - $item_servers = get_post_meta($post_id, '_wis_servers', true); - $is_offer = get_post_meta($post_id, '_wis_is_offer', true); - - if(!is_array($item_servers)) $item_servers = []; - if($price <= 0) continue; - if(!in_array($server_slug, $item_servers)) continue; - - $offer_price = intval(get_post_meta($post_id, '_wis_offer_price', true)); - $display_price = ($offer_price > 0) ? $offer_price : $price; - - $real_item_id = get_post_meta($post_id, '_wis_item_id', true); - - $valid_cart[] = [ - 'id' => $post_id, - 'title' => get_the_title($post_id), - 'price' => $display_price, - 'qty' => $qty, - 'is_offer' => $is_offer, - 'real_item_id' => $real_item_id - ]; - - $item_total = $display_price * $qty; - - if($is_offer && $exclude_offers_setting) { - $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 im Warenkorb.'], 400); - - // Gutschein Logik - $coupon_discount = 0; - $coupon_msg = ''; - $coupon_applied = false; - $currency = get_option('wis_currency_name', 'Coins'); - - if(!empty($coupon_code)) { - $coupon = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wis_coupons WHERE code = %s", $coupon_code)); - - if($coupon) { - // Basis Checks - if($coupon->expiry && date('Y-m-d') > $coupon->expiry) { - $coupon_msg = 'Gutschein abgelaufen.'; - } elseif($coupon->used_count >= $coupon->usage_limit) { - $coupon_msg = 'Gutschein wurde zu oft verwendet.'; - } else { - // Prüfen ob Gutschein angewendet werden darf - $apply_coupon = false; - $calculate_discount = false; - - if($exclude_offers_setting === '1') { - if($total_normal > 0) { - $apply_coupon = true; - } - } else { - if($total_normal > 0 || $total_offer > 0) { - $apply_coupon = true; - } - } - - if($apply_coupon) { - $calculate_discount = true; - } - } - } else { - $coupon_msg = 'Ungültiger Gutscheincode.'; - } - } - - // Wenn angewendet, berechnen - if($calculate_discount) { - $coupon_type = $coupon->type; - if($coupon_type === 'percent') { - $coupon_discount = $total_normal * ($coupon->value / 100); - $coupon_msg = "Gutschein eingelöst: -{$coupon->value}% (-{$coupon_discount} {$currency})"; - } else { - $coupon_discount = $coupon->value; - $coupon_msg = "Gutschein eingelöst: -{$coupon_discount} {$currency}"; - } - - // Aufrunden - $coupon_discount = floor($coupon_discount); - - $wpdb->update($wpdb->prefix.'wis_coupons', ['used_count' => $coupon->used_count + 1], ['id' => $coupon->id]); - $coupon_applied = true; - } - - $final_normal = max(0, $total_normal - $coupon_discount); - $final_price = $final_normal + $total_offer; - - // Speichern in DB - $items_payload = []; - $title_parts = []; - - foreach($valid_cart as $item) { - $items_payload[] = [ - 'id' => $item['real_item_id'], - 'amount' => $item['qty'] - ]; - $title_parts[] = $item['qty'] . 'x ' . $item['title']; - } - - $readable_title = "Warenkorb: " . implode(', ', $title_parts); - if (strlen($readable_title) > 240) $readable_title = substr($readable_title, 0, 237) . '...'; - - $coupon_data = []; - if($coupon_applied) { - $coupon_data = [ - 'code' => $coupon_code, - 'discount' => $coupon_discount - ]; - } - - $json_payload = json_encode([ - 'items' => $items_payload, - 'coupon' => $coupon_data + register_rest_route('wis/v1', '/import_json', [ + 'methods' => 'POST', + 'callback' => [self::class, 'import_json'], + 'permission_callback' => '__return_true' ]); - $inserted = $wpdb->insert($wpdb->prefix.'wis_orders', [ - 'player_name' => $player, - 'server' => $server_slug, - 'item_id' => 'multi_item_cart', - 'item_title' => $readable_title, - 'price' => $final_price, - 'quantity' => count($valid_cart), - 'status' => 'pending', - 'response' => $json_payload, - 'created_at' => current_time('mysql') + 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' ]); - - if($inserted) { - $msg = '✅ Bestellung erfolgreich erstellt!'; - if($coupon_msg) $msg .= ' ('.$coupon_msg.')'; - return new WP_REST_Response(['success'=>true,'message'=>$msg], 200); - } else { - return new WP_REST_Response(['success'=>false,'message'=>'Fehler beim Speichern.'], 500); - } } - - public static function validate_coupon($request) { - global $wpdb; - $data = $request->get_json_params(); - $code = sanitize_text_field(strtoupper($data['code'] ?? '')); - $cart = $data['cart'] ?? []; - $currency = get_option('wis_currency_name', 'Coins'); - - if(!$code) { - return new WP_REST_Response(['success'=>false, 'message'=>'Kein Code angegeben']); - } - $coupon = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wis_coupons WHERE code = %s", $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'=>'Dieser Gutschein wurde bereits maximal eingelöst']); - } - - $exclude_offers_setting = get_option('wis_coupon_exclude_offers', '0'); - - if($exclude_offers_setting === '1' && !empty($cart)) { - $has_normal_items = false; - foreach($cart as $item) { - $post_id = intval($item['id'] ?? 0); - $is_offer = get_post_meta($post_id, '_wis_is_offer', true); - if(empty($is_offer) || $is_offer == 0) { - $has_normal_items = true; - break; - } - } - - if(!$has_normal_items) { - return new WP_REST_Response(['success'=>false, 'message'=>'⚠️ Dieser Gutschein gilt nicht für Angebote.']); - } - } - - $message = ''; - if($coupon->type === 'percent') { - $message = "Gutschein gültig (-{$coupon->value}%)"; - } else { - $message = "Gutschein gültig (-{$coupon->value} {$currency})"; - } - - return new WP_REST_Response(['success'=>true, 'type'=>$coupon->type, 'value'=>$coupon->value, 'message'=>$message]); - } - + + // --- 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)); + + 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]); } @@ -1116,580 +1574,786 @@ class WIS_API { global $wpdb; $data = $request->get_json_params(); $id = intval($data['id'] ?? 0); - if(!$id) return new WP_REST_Response(['success'=>false], 400); - $order = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wis_orders WHERE id = %d", $id)); - if($order) { - $wpdb->update($wpdb->prefix.'wis_orders', ['status' => 'processing'], ['id' => $id]); - return new WP_REST_Response(['success'=>true]); - } - return new WP_REST_Response(['success'=>false], 400); + 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]); + 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); - $updated = $wpdb->update($wpdb->prefix.'wis_orders', ['status' => 'cancelled'], ['id' => $id]); + if (!$id) return new WP_REST_Response(['success' => false], 400); - if($updated !== false) { - return new WP_REST_Response(['success'=>true]); - } - 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 fetch_remote_data($request) { - $url = esc_url_raw($request->get_json_params()['url']); + + // --- 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); - $data = json_decode($body, true); - $import_data = []; - if (isset($data['items']) && is_array($data['items'])) { $import_data = $data['items']; } elseif (is_array($data)) { $import_data = $data; } - if(empty($import_data)) return new WP_REST_Response(['success'=>false, 'message'=>'Keine gültigen Daten gefunden'], 400); - return new WP_REST_Response(['success'=>true, 'items' => $import_data]); - } - - public static function import_batch($request) { - $items = $request->get_json_params()['items'] ?? []; - if(!is_array($items) || empty($items)) return new WP_REST_Response(['success'=>false], 400); - set_time_limit(300); - $processed = 0; $skipped = 0; - foreach($items as $item) { - $item_id_val = $item['id'] ?? ''; $title_val = $item['name'] ?? 'Unbekannt'; - if(empty($item_id_val)) continue; - $exists = get_posts(['post_type' => 'wis_item', 'meta_key' => '_wis_item_id', 'meta_value' => $item_id_val, 'posts_per_page' => 1]); - if($exists) { $skipped++; continue; } - $new_post_id = wp_insert_post(['post_title' => $title_val, 'post_content' => '', 'post_type' => 'wis_item', 'post_status' => 'draft', 'meta_input' => ['_wis_item_id' => $item_id_val, '_wis_price' => 0]]); - if(!is_wp_error($new_post_id)) $processed++; + + if (is_wp_error($response)) { + return new WP_REST_Response(['success' => false, 'message' => $response->get_error_message()], 400); } - return new WP_REST_Response(['success'=>true, 'processed' => $processed, 'skipped' => $skipped]); + + $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 + ]); } } // =========================================================== -// 5. SHORTCODE +// SHORTCODE - FRONTEND SHOP // =========================================================== class WIS_Shortcode { - public static function register_shortcode() { - add_shortcode('ingame_shop_form', [self::class, 'render_form']); + public static function register() { + add_shortcode('ingame_shop_form', [self::class, 'render']); } - - public static function render_form() { - $servers = get_posts(['post_type'=>'wis_server','numberposts'=>-1]); - $items = get_posts(['post_type'=>'wis_item','numberposts'=>-1]); + + 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', 'https://assets.minecraft-ids.com/1_21_10/'); - $header_text = get_option('wis_header_text', '✅ Auto-Bilder | 💰 Sicherer Checkout'); + $img_base = get_option('wis_image_base_url', ''); + $header_text = get_option('wis_header_text', ''); $exclude_offers = get_option('wis_coupon_exclude_offers', '0'); - // NEU: Kategorien - $categories = get_terms(['taxonomy'=>'wis_category', 'hide_empty'=>true]); - ob_start(); ?> -
+ +
-

🛒 Ingame Shop Pro

- -
+

🛒 Ingame Shop

+ +
- +
-
- -
-
- -
+ + - + +
- - -
+ + +
- - + +
- -
- -
Keine Items im Shop verfügbar.
- - ID, '_wis_servers', true); - if(!is_array($item_servers)) $item_servers = []; - $price = get_post_meta($item->ID, '_wis_price', true); - $item_id_code = get_post_meta($item->ID, '_wis_item_id', true); - $item_desc = $item->post_content; - - $is_offer = get_post_meta($item->ID, '_wis_is_offer', true); - $is_daily_deal = get_post_meta($item->ID, '_wis_daily_deal', true); - $offer_price = get_post_meta($item->ID, '_wis_offer_price', true); - $display_price = ($offer_price > 0) ? $offer_price : $price; - $show_old_price = ($offer_price > 0 && $offer_price != $price); - - // NEU: Kategorien - $item_cats = wp_get_post_terms($item->ID, 'wis_category'); - $cat_ids = array_map(function($t) { return $t->term_id; }, $item_cats); - $cat_data = json_encode($cat_ids); - - $img_name = str_replace(':', '_', $item_id_code) . '.png'; - $full_img_url = $img_base . $img_name; - - $server_names = []; - foreach($item_servers as $slug) { - $srv = get_page_by_path($slug, OBJECT, 'wis_server'); - if($srv) $server_names[] = $srv->post_title; - } - $servers_display = !empty($server_names) ? implode(', ', $server_names) : 'Kein Server'; - $servers_data = json_encode($item_servers); - ?> -
- -
🎁 Angebot des Tages
-
🔥 Angebot
- -
- <?=esc_attr($item->post_title)?> -
-
-

post_title)?>

- -
-
-
-
- -
📡
- - -
⚠️ Gutschein ungültig
- - -
- - - -
- - -
+ + +
+ +
+ 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
+
Dein Warenkorb ist leer
- + 'Zeigt das aktuelle Angebot oder Daily Deal an mit anpassbarem Link.' ) // Args + 'wis_sidebar_offer', + 'WIS Shop Angebot', + ['description' => 'Zeigt Daily Deal oder Angebot an'] ); } - - // Backend: Formular im Widget-Bereich - public function form( $instance ) { - // Standardwerte definieren - $defaults = [ - 'title' => '🔥 Angebot des Tages', - 'btn_text' => 'Zum Shop', - 'shop_url' => '' - ]; - // Werte mergen (falls noch nichts gespeichert wurde) - $instance = wp_parse_args( (array) $instance, $defaults ); - - ?> -

- - -

- -

- - - Standard: "Zum Shop" -

- -

- - - Wenn leer, wird zur Startseite verlinkt. -

- '🔥 Angebot des Tages', - 'btn_text' => 'Zum Shop', - 'shop_url' => '' - ]; - $instance = wp_parse_args( (array) $instance, $defaults ); - - if ( ! empty( $instance['title'] ) ) { - echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title']; - } - - $currency = get_option('wis_currency_name', 'Coins'); - $img_base = get_option('wis_image_base_url', 'https://assets.minecraft-ids.com/1_21.10/'); - // 1. Suche Daily Deal (Prio 1) - $daily_deal = get_posts([ - 'post_type' => 'wis_item', - 'posts_per_page' => 1, - 'meta_key' => '_wis_daily_deal', - 'meta_value' => 1 - ]); - - $item = null; - $is_daily = false; - - if (!empty($daily_deal)) { - $item = $daily_deal[0]; - $is_daily = true; - } else { - // 2. Fallback: Suche normales Angebot (Prio 2) - $offers = get_posts([ - 'post_type' => 'wis_item', - 'posts_per_page' => 1, - 'meta_key' => '_wis_is_offer', - 'meta_value' => 1, - 'orderby' => 'modified', - 'order' => 'DESC' - ]); - if (!empty($offers)) { - $item = $offers[0]; - } + if (!empty($instance['title'])) { + echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title']; } - - // Ziel-URL für den Button bestimmen - $target_url = !empty($instance['shop_url']) ? $instance['shop_url'] : home_url(); - + + 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 = get_post_meta($item->ID, '_wis_price', true); - $offer_price = get_post_meta($item->ID, '_wis_offer_price', true); - $item_id_code = get_post_meta($item->ID, '_wis_item_id', 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; + $target_url = !empty($instance['shop_url']) ? $instance['shop_url'] : home_url(); - $final_price = ($offer_price > 0) ? $offer_price : $price; - $show_old_price = ($offer_price > 0 && $offer_price < $price); - - // Bild URL generieren - $img_name = str_replace(':', '_', $item_id_code) . '.png'; - $full_img_url = $img_base . $img_name; - - // Modernes Card Design ?> -
- - +
- -
🎁 DAILY DEAL
- 0): ?> -
🔥 ANGEBOT
+ is_daily_deal): ?> +
🎁 DAILY DEAL
+ is_offer): ?> +
🔥 ANGEBOT
- - <?php echo esc_attr($item->post_title); ?> + <?php echo esc_attr($item->name); ?>
- -
-

post_title); ?>

- -
- - +

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

+ + +

+

+ + +

+

+ + +

+ +add_action('wis_daily_deal_event', [WIS_Activator::class, 'run_daily_deal']); \ No newline at end of file