diff --git a/wp-ingame-shop/wp-ingame-shop-pro.php b/wp-ingame-shop/wp-ingame-shop-pro.php index 304e2e3..12914fa 100644 --- a/wp-ingame-shop/wp-ingame-shop-pro.php +++ b/wp-ingame-shop/wp-ingame-shop-pro.php @@ -266,11 +266,18 @@ class WIS_Activator { if (!wp_next_scheduled('wis_daily_deal_event')) { wp_schedule_event(time(), 'daily', 'wis_daily_deal_event'); } + // Fly-Abo Renewal: täglich prüfen (läuft nur durch am 1. des Monats) + if (!wp_next_scheduled('wis_abo_renewal_event')) { + // Nächsten Mitternacht-Zeitstempel berechnen + $midnight = strtotime('tomorrow midnight'); + wp_schedule_event($midnight, 'daily', 'wis_abo_renewal_event'); + } flush_rewrite_rules(); } public static function deactivate() { wp_clear_scheduled_hook('wis_daily_deal_event'); + wp_clear_scheduled_hook('wis_abo_renewal_event'); flush_rewrite_rules(); } @@ -442,6 +449,92 @@ class WIS_Activator { ], ['id' => $item->id]); } } + + /** + * Fly-Abo Renewal – läuft täglich, handelt aber nur am 1. des Monats. + * Verlängert alle aktiven (nicht gekündigten) Abos automatisch um 30 Tage + * und legt je einen Order-Eintrag als Buchungsnachweis an. + * Gekündigte Abos laufen bis zum letzten Tag des laufenden Monats und werden dann entfernt. + */ + public static function run_abo_renewal() { + // Nur am 1. des Monats ausführen + if (date('j') !== '1') return; + + global $wpdb; + $subs_table = $wpdb->prefix . 'wis_fly_abo_subs'; + $orders_table = $wpdb->prefix . 'wis_orders'; + + // Tabelle anlegen falls noch nicht vorhanden (Migration) + self::create_abo_subs_table(); + + // Alle aktiven, nicht gekündigten Abos verlängern + $active = $wpdb->get_results( + "SELECT * FROM {$subs_table} WHERE cancelled = 0 AND status = 'active'" + ); + + foreach ($active as $sub) { + // expires_at um 30 Tage verlängern + $wpdb->query($wpdb->prepare( + "UPDATE {$subs_table} + SET expires_at = DATE_ADD(expires_at, INTERVAL 30 DAY), + renewed_at = NOW(), + renewal_count = renewal_count + 1 + WHERE id = %d", + $sub->id + )); + + // Buchungsnachweis als Order anlegen (status: completed) + $wpdb->insert($orders_table, [ + 'player_name' => $sub->player_name, + 'server' => $sub->server, + 'item_id' => 'fly_abo_renewal', + 'item_title' => '✈ Fly-Abo Verlängerung: ' . $sub->label, + 'price' => $sub->price, + 'quantity' => 1, + 'status' => 'completed', + 'response' => json_encode([ + 'commands' => [[ + 'type' => 'fly_abo', + 'days' => 30, + 'label' => $sub->label, + ]], + ]), + ]); + } + + // Gekündigte Abos die abgelaufen sind deaktivieren + $wpdb->query( + "UPDATE {$subs_table} + SET status = 'expired' + WHERE cancelled = 1 + AND expires_at < NOW() + AND status = 'active'" + ); + + // Log + $count = count($active); + error_log("[WIS] Fly-Abo Renewal: {$count} Abo(s) verlängert am " . date('d.m.Y')); + } + + public static function create_abo_subs_table() { + global $wpdb; + $table = $wpdb->prefix . 'wis_fly_abo_subs'; + $wpdb->query("CREATE TABLE IF NOT EXISTS {$table} ( + id INT AUTO_INCREMENT PRIMARY KEY, + player_name VARCHAR(64) NOT NULL, + server VARCHAR(64) NOT NULL DEFAULT '', + label VARCHAR(128) NOT NULL, + price INT NOT NULL DEFAULT 0, + status VARCHAR(20) NOT NULL DEFAULT 'active', + cancelled TINYINT(1) NOT NULL DEFAULT 0, + cancelled_at DATETIME DEFAULT NULL, + expires_at DATETIME NOT NULL, + renewed_at DATETIME DEFAULT NULL, + renewal_count INT NOT NULL DEFAULT 0, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY uq_player_server (player_name, server) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); + } public static function reset_shop() { global $wpdb; @@ -1041,8 +1134,7 @@ class WIS_Admin { if (empty($default_group)) $default_group = 'default'; $resolved_item_id = 'rank_' . $rank_id . '_' . $lp_group . '_' . $default_group . '_' . $rank_days; } elseif ($item_type === 'fly_abo') { - $abo_days = max(1, intval($_POST['abo_days'] ?? 30)); - $resolved_item_id = 'fly_abo_' . $abo_days; + $resolved_item_id = 'fly_abo'; } else { $resolved_item_id = sanitize_text_field($_POST['item_id'] ?? ''); } @@ -1725,8 +1817,8 @@ class WIS_Admin { // Format: rank_{rank_id}_{lp_group}_{default_group}_{days} // Fallback für altes Format rank_{rank_id}_{days} $is_rank_old = !$is_rank && $item && preg_match('/^rank_(.+)_(\d+)$/', $item->item_id, $rm_old); - $is_fly_abo = $item && preg_match('/^fly_abo_(\d+)$/', $item->item_id, $abo_m); - $cur_abo_days = $is_fly_abo ? intval($abo_m[1]) : 30; + $is_fly_abo = $item && ($item->item_id === 'fly_abo' || preg_match('/^fly_abo_\d+$/', $item->item_id)); + $cur_abo_days = 0; // nicht mehr relevant $cur_rank_id = $is_rank ? $rm[1] : ($is_rank_old ? $rm_old[1] : 'vip'); $cur_lp_group = $is_rank ? $rm[2] : $cur_rank_id; $cur_default_group = $is_rank ? $rm[3] : 'default'; @@ -1790,21 +1882,15 @@ class WIS_Admin {
@@ -2135,8 +2221,8 @@ class WIS_Admin { } elseif (preg_match('/^rank_(.+)_(\d+)$/', $item->item_id, $rm2)) { $rd = intval($rm2[2]); echo '👑' . esc_html($rm2[1]) . ' — ' . ($rd === 0 ? 'dauerhaft' : esc_html($rd) . ' Tage') . '';
- } elseif (preg_match('/^fly_abo_(\d+)$/', $item->item_id, $abo_m2)) {
- echo '✈ Fly-Abo — ' . esc_html($abo_m2[1]) . ' Tage';
+ } elseif ($item->item_id === 'fly_abo' || preg_match('/^fly_abo_/', $item->item_id)) {
+ echo '✈ Fly-Abo — monatlich';
} else {
echo '' . esc_html($item->item_id) . '';
}
@@ -3441,16 +3527,14 @@ class WIS_API {
];
}
$title_parts[] = $item['qty'] . 'x ' . $item['title'];
- } elseif (preg_match('/^fly_abo_(\d+)$/', $item_id, $abo_m)) {
- // Fly-Abo: qty > 1 verlängert das Abo (addiert Tage)
- $abo_days = intval($abo_m[1]);
- $total_days = $abo_days * intval($item['qty']);
+ } elseif (preg_match('/^fly_abo$/', $item_id) || preg_match('/^fly_abo_\d*$/', $item_id)) {
+ // Fly-Abo: monatlich abonniert, Preis = Monatsbeitrag
+ // qty > 1 wird ignoriert (nur 1 Abo pro Spieler möglich, Mehrfachkauf = keine Wirkung)
$commands_payload[] = [
'type' => 'fly_abo',
- 'days' => $total_days,
'label' => $item['title'],
];
- $title_parts[] = $item['qty'] . 'x ' . $item['title'];
+ $title_parts[] = $item['title'];
} else {
// Normales Item
$items_payload[] = [
@@ -3480,7 +3564,53 @@ class WIS_API {
'status' => 'pending',
'response' => json_encode($payload)
]);
-
+
+ // Fly-Abo Abonnements registrieren / verlängern
+ foreach ($commands_payload as $cmd) {
+ if (($cmd['type'] ?? '') !== 'fly_abo') continue;
+ $abo_days = intval($cmd['days'] ?? 30);
+ $abo_label = sanitize_text_field($cmd['label'] ?? 'Fly-Abo');
+ $abo_price = 0;
+ // Preis aus dem Warenkorb ermitteln (erstes passendes fly_abo Item)
+ foreach ($valid_cart as $ci) {
+ if (preg_match('/^fly_abo_\d+$/', $ci['id'])) {
+ $abo_price = intval($ci['price'] ?? 0);
+ break;
+ }
+ }
+ global $wpdb;
+ WIS_Activator::create_abo_subs_table();
+ $subs_table = $wpdb->prefix . 'wis_fly_abo_subs';
+ $existing = $wpdb->get_row($wpdb->prepare(
+ "SELECT * FROM {$subs_table} WHERE player_name = %s AND server = %s",
+ $player, $server
+ ));
+ if ($existing && $existing->status === 'active') {
+ // Bestehendes aktives Abo verlängern (kumulativ)
+ $wpdb->query($wpdb->prepare(
+ "UPDATE {$subs_table}
+ SET expires_at = DATE_ADD(IF(expires_at > NOW(), expires_at, NOW()), INTERVAL %d DAY),
+ cancelled = 0,
+ cancelled_at = NULL,
+ label = %s,
+ price = %d
+ WHERE id = %d",
+ $abo_days, $abo_label, $abo_price, $existing->id
+ ));
+ } else {
+ // Neues Abo anlegen
+ $wpdb->replace($subs_table, [
+ 'player_name' => $player,
+ 'server' => $server,
+ 'label' => $abo_label,
+ 'price' => $abo_price,
+ 'status' => 'active',
+ 'cancelled' => 0,
+ 'expires_at' => date('Y-m-d H:i:s', strtotime("+{$abo_days} days")),
+ ]);
+ }
+ }
+
$msg = '✅ Bestellung erfolgreich!';
if ($coupon_msg) $msg .= ' (' . $coupon_msg . ')';
@@ -4265,4 +4395,5 @@ add_action('init', [WIS_Shortcode::class, 'register']);
add_action('widgets_init', function() {
register_widget('WIS_Sidebar_Widget');
});
-add_action('wis_daily_deal_event', [WIS_Activator::class, 'run_daily_deal']);
\ No newline at end of file
+add_action('wis_daily_deal_event', [WIS_Activator::class, 'run_daily_deal']);
+add_action('wis_abo_renewal_event', [WIS_Activator::class, 'run_abo_renewal']);
\ No newline at end of file