update_database($current_version, $plugin_version); } } /** * Update database schema * * @param string $from_version * @param string $to_version */ private function update_database($from_version, $to_version) { global $wpdb; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); // Create or update tables $this->create_rates_table(); $this->create_availability_table(); $this->create_deals_table(); $this->create_restrictions_table(); // Run version-specific updates if (version_compare($from_version, '1.0.0', '<')) { $this->upgrade_to_1_0_0(); } // Update database version update_option('eb_ap_db_version', $to_version); eb_ap_log("Database updated from version {$from_version} to {$to_version}"); } /** * Create rates table */ private function create_rates_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE " . EB_AP_TABLE_RATES . " ( id int(11) NOT NULL AUTO_INCREMENT, room_id int(11) NOT NULL, rate_date date NOT NULL, base_rate decimal(10,2) NOT NULL DEFAULT 0.00, adult_rate decimal(10,2) NOT NULL DEFAULT 0.00, child_rate decimal(10,2) NOT NULL DEFAULT 0.00, min_guests int(11) NOT NULL DEFAULT 1, max_guests int(11) NOT NULL DEFAULT 10, min_stay int(11) NOT NULL DEFAULT 1, max_stay int(11) NOT NULL DEFAULT 0, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY room_date (room_id, rate_date), KEY room_id (room_id), KEY rate_date (rate_date) ) $charset_collate;"; dbDelta($sql); } /** * Create availability table */ private function create_availability_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE " . EB_AP_TABLE_AVAILABILITY . " ( id int(11) NOT NULL AUTO_INCREMENT, room_id int(11) NOT NULL, availability_date date NOT NULL, available_rooms int(11) NOT NULL DEFAULT 0, stop_sell tinyint(1) NOT NULL DEFAULT 0, closed_to_arrival tinyint(1) NOT NULL DEFAULT 0, closed_to_departure tinyint(1) NOT NULL DEFAULT 0, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY room_date (room_id, availability_date), KEY room_id (room_id), KEY availability_date (availability_date) ) $charset_collate;"; dbDelta($sql); } /** * Create deals table */ private function create_deals_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE " . EB_AP_TABLE_DEALS . " ( id int(11) NOT NULL AUTO_INCREMENT, room_id int(11) NOT NULL, deal_type varchar(50) NOT NULL, deal_name varchar(255) NOT NULL, discount_type varchar(20) NOT NULL, discount_value decimal(10,2) NOT NULL, date_from date NOT NULL, date_to date NOT NULL, min_stay int(11) NOT NULL DEFAULT 1, max_stay int(11) NOT NULL DEFAULT 0, advance_booking_days int(11) NOT NULL DEFAULT 0, is_active tinyint(1) NOT NULL DEFAULT 1, priority int(11) NOT NULL DEFAULT 0, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY room_id (room_id), KEY deal_type (deal_type), KEY date_from (date_from), KEY date_to (date_to), KEY is_active (is_active) ) $charset_collate;"; dbDelta($sql); } /** * Create restrictions table */ private function create_restrictions_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE " . EB_AP_TABLE_RESTRICTIONS . " ( id int(11) NOT NULL AUTO_INCREMENT, room_id int(11) NOT NULL, restriction_date date NOT NULL, restriction_type varchar(50) NOT NULL, restriction_value text, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY room_id (room_id), KEY restriction_date (restriction_date), KEY restriction_type (restriction_type) ) $charset_collate;"; dbDelta($sql); } /** * Upgrade to version 1.0.0 */ private function upgrade_to_1_0_0() { // Initial setup - migrate existing Eagle Booking data if needed $this->migrate_existing_data(); } /** * Migrate existing Eagle Booking data */ private function migrate_existing_data() { // Get all rooms $rooms = get_posts(array( 'post_type' => 'eagle_rooms', 'posts_per_page' => -1, 'post_status' => 'publish' )); foreach ($rooms as $room) { $this->migrate_room_data($room->ID); } eb_ap_log('Migrated existing Eagle Booking data for ' . count($rooms) . ' rooms'); } /** * Migrate data for a specific room * * @param int $room_id */ private function migrate_room_data($room_id) { // Get existing room data $base_price = get_post_meta($room_id, 'eagle_booking_mtb_room_price', true); $quantity = get_post_meta($room_id, 'eagle_booking_mtb_room_quantity', true); $min_guests = get_post_meta($room_id, 'eagle_booking_mtb_room_min_guests', true); $max_guests = get_post_meta($room_id, 'eagle_booking_mtb_room_max_guests', true); // Set default values if empty $base_price = $base_price ? floatval($base_price) : 0; $quantity = $quantity ? intval($quantity) : 1; $min_guests = $min_guests ? intval($min_guests) : 1; $max_guests = $max_guests ? intval($max_guests) : 10; // Create default availability for the next 365 days $start_date = new DateTime(); $end_date = new DateTime(); $end_date->add(new DateInterval('P365D')); $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date); foreach ($period as $date) { $date_str = $date->format('Y-m-d'); // Set default rates $rates = array( 'base_rate' => $base_price, 'adult_rate' => $base_price, 'child_rate' => $base_price * 0.5, // 50% for children 'min_guests' => $min_guests, 'max_guests' => $max_guests, 'min_stay' => 1, 'max_stay' => 0 ); // Set default availability $availability = array( 'available_rooms' => $quantity, 'stop_sell' => 0, 'closed_to_arrival' => 0, 'closed_to_departure' => 0 ); // Only insert if not already exists if (!$this->rate_exists($room_id, $date_str)) { EB_AP_Rates::instance()->update_rates($room_id, $date_str, $rates); } if (!$this->availability_exists($room_id, $date_str)) { EB_AP_Availability::instance()->update_availability($room_id, $date_str, $availability); } } } /** * Check if rate exists for room and date * * @param int $room_id * @param string $date * @return bool */ private function rate_exists($room_id, $date) { global $wpdb; $count = $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM " . EB_AP_TABLE_RATES . " WHERE room_id = %d AND rate_date = %s", $room_id, $date )); return $count > 0; } /** * Check if availability exists for room and date * * @param int $room_id * @param string $date * @return bool */ private function availability_exists($room_id, $date) { global $wpdb; $count = $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM " . EB_AP_TABLE_AVAILABILITY . " WHERE room_id = %d AND availability_date = %s", $room_id, $date )); return $count > 0; } /** * Clean up old data * * @param int $days_old */ public function cleanup_old_data($days_old = 365) { global $wpdb; $cutoff_date = date('Y-m-d', strtotime("-{$days_old} days")); // Clean old rates $wpdb->query($wpdb->prepare( "DELETE FROM " . EB_AP_TABLE_RATES . " WHERE rate_date < %s", $cutoff_date )); // Clean old availability $wpdb->query($wpdb->prepare( "DELETE FROM " . EB_AP_TABLE_AVAILABILITY . " WHERE availability_date < %s", $cutoff_date )); // Clean expired deals $wpdb->query($wpdb->prepare( "DELETE FROM " . EB_AP_TABLE_DEALS . " WHERE date_to < %s", $cutoff_date )); eb_ap_log("Cleaned up data older than {$days_old} days"); } /** * Backup tables * * @return array */ public function backup_tables() { global $wpdb; $tables = array( EB_AP_TABLE_RATES, EB_AP_TABLE_AVAILABILITY, EB_AP_TABLE_DEALS, EB_AP_TABLE_RESTRICTIONS ); $backup_data = array(); foreach ($tables as $table) { $data = $wpdb->get_results("SELECT * FROM {$table}", ARRAY_A); $backup_data[basename($table)] = $data; } return $backup_data; } /** * Get database statistics * * @return array */ public function get_statistics() { global $wpdb; $stats = array(); // Rates statistics $stats['rates'] = $wpdb->get_row( "SELECT COUNT(*) as total, MIN(rate_date) as earliest_date, MAX(rate_date) as latest_date, AVG(base_rate) as avg_rate FROM " . EB_AP_TABLE_RATES, ARRAY_A ); // Availability statistics $stats['availability'] = $wpdb->get_row( "SELECT COUNT(*) as total, SUM(available_rooms) as total_rooms, SUM(stop_sell) as stop_sell_days, SUM(closed_to_arrival) as cta_days, SUM(closed_to_departure) as ctd_days FROM " . EB_AP_TABLE_AVAILABILITY, ARRAY_A ); // Deals statistics $stats['deals'] = $wpdb->get_row( "SELECT COUNT(*) as total, SUM(is_active) as active_deals, AVG(discount_value) as avg_discount FROM " . EB_AP_TABLE_DEALS, ARRAY_A ); return $stats; } /** * Drop all tables (for uninstall) */ public function drop_tables() { global $wpdb; $tables = array( EB_AP_TABLE_RATES, EB_AP_TABLE_AVAILABILITY, EB_AP_TABLE_DEALS, EB_AP_TABLE_RESTRICTIONS ); foreach ($tables as $table) { $wpdb->query("DROP TABLE IF EXISTS {$table}"); } // Delete options delete_option('eb_ap_db_version'); delete_option('eb_ap_activated'); // Delete all plugin options $options = $wpdb->get_results( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE 'eb_ap_%'" ); foreach ($options as $option) { delete_option($option->option_name); } eb_ap_log('All Eagle Booking Advanced Pricing data removed'); } }