🏨 Hotel Booking Enhancements: - Implemented Eagle Booking Advanced Pricing add-on - Added Booking.com-style rate management system - Created professional calendar interface for pricing - Integrated deals and discounts functionality 💰 Advanced Pricing Features: - Dynamic pricing models (per room, per person, per adult) - Base rates, adult rates, and child rates management - Length of stay discounts and early bird deals - Mobile rates and secret deals implementation - Seasonal promotions and flash sales 📅 Availability Management: - Real-time availability tracking - Stop sell and restriction controls - Closed to arrival/departure functionality - Minimum/maximum stay requirements - Automatic sold-out management 💳 Payment Integration: - Maintained Redsys payment gateway integration - Seamless integration with existing Eagle Booking - No modifications to core Eagle Booking plugin 🛠️ Technical Implementation: - Custom database tables for advanced pricing - WordPress hooks and filters integration - AJAX-powered admin interface - Data migration from existing Eagle Booking - Professional calendar view for revenue management 📊 Admin Interface: - Booking.com-style management dashboard - Visual rate and availability calendar - Bulk operations for date ranges - Statistics and analytics dashboard - Modal dialogs for quick editing 🔧 Code Quality: - WordPress coding standards compliance - Secure database operations with prepared statements - Proper input validation and sanitization - Error handling and logging - Responsive admin interface 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
578 lines
19 KiB
PHP
578 lines
19 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: Eagle Booking Advanced Pricing
|
|
* Plugin URI: https://informatiq.services
|
|
* Description: Booking.com-style advanced pricing and availability management for Eagle Booking
|
|
* Version: 1.0.0
|
|
* Author: Mălin Cenușă
|
|
* Author URI: https://mălin.ro
|
|
* Text Domain: eb-advanced-pricing
|
|
* Domain Path: /languages
|
|
* Requires at least: 5.0
|
|
* Requires PHP: 7.4
|
|
* License: GPL v2 or later
|
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Main plugin class
|
|
*/
|
|
final class EB_Advanced_Pricing {
|
|
|
|
/**
|
|
* Plugin version
|
|
*/
|
|
const VERSION = '1.0.0';
|
|
|
|
/**
|
|
* Minimum Eagle Booking version required
|
|
*/
|
|
const MIN_EB_VERSION = '1.3.0';
|
|
|
|
/**
|
|
* Single instance of the plugin
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Get single instance
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$instance)) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
$this->define_constants();
|
|
$this->init_hooks();
|
|
}
|
|
|
|
/**
|
|
* Define plugin constants
|
|
*/
|
|
private function define_constants() {
|
|
define('EB_AP_VERSION', self::VERSION);
|
|
define('EB_AP_FILE', __FILE__);
|
|
define('EB_AP_PATH', plugin_dir_path(__FILE__));
|
|
define('EB_AP_URL', plugin_dir_url(__FILE__));
|
|
define('EB_AP_BASENAME', plugin_basename(__FILE__));
|
|
define('EB_AP_SLUG', 'eb-advanced-pricing');
|
|
|
|
// Database table names
|
|
global $wpdb;
|
|
define('EB_AP_TABLE_RATES', $wpdb->prefix . 'eb_ap_rates');
|
|
define('EB_AP_TABLE_AVAILABILITY', $wpdb->prefix . 'eb_ap_availability');
|
|
define('EB_AP_TABLE_DEALS', $wpdb->prefix . 'eb_ap_deals');
|
|
define('EB_AP_TABLE_RESTRICTIONS', $wpdb->prefix . 'eb_ap_restrictions');
|
|
}
|
|
|
|
/**
|
|
* Initialize hooks
|
|
*/
|
|
private function init_hooks() {
|
|
add_action('plugins_loaded', array($this, 'init'), 0);
|
|
add_action('init', array($this, 'init_textdomain'));
|
|
|
|
// Activation and deactivation
|
|
register_activation_hook(__FILE__, array($this, 'activate'));
|
|
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
|
|
|
|
// Admin
|
|
add_action('admin_menu', array($this, 'admin_menu'));
|
|
add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
|
|
|
|
// Ajax handlers
|
|
add_action('wp_ajax_eb_ap_update_rates', array($this, 'ajax_update_rates'));
|
|
add_action('wp_ajax_eb_ap_update_availability', array($this, 'ajax_update_availability'));
|
|
add_action('wp_ajax_eb_ap_create_deal', array($this, 'ajax_create_deal'));
|
|
add_action('wp_ajax_eb_ap_get_calendar_data', array($this, 'ajax_get_calendar_data'));
|
|
|
|
// Frontend hooks
|
|
add_filter('eb_room_price_calculation', array($this, 'calculate_room_price'), 10, 4);
|
|
add_filter('eb_room_availability_check', array($this, 'check_availability'), 10, 3);
|
|
add_filter('eb_search_results', array($this, 'apply_deals_to_results'), 10, 2);
|
|
}
|
|
|
|
/**
|
|
* Initialize plugin
|
|
*/
|
|
public function init() {
|
|
if (!$this->check_requirements()) {
|
|
return;
|
|
}
|
|
|
|
$this->includes();
|
|
$this->init_classes();
|
|
}
|
|
|
|
/**
|
|
* Check plugin requirements
|
|
*/
|
|
private function check_requirements() {
|
|
if (!class_exists('Eagle_Booking')) {
|
|
add_action('admin_notices', array($this, 'missing_eagle_booking_notice'));
|
|
return false;
|
|
}
|
|
|
|
if (defined('EB_VERSION') && version_compare(EB_VERSION, self::MIN_EB_VERSION, '<')) {
|
|
add_action('admin_notices', array($this, 'eagle_booking_version_notice'));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Include required files
|
|
*/
|
|
private function includes() {
|
|
// Core classes
|
|
require_once EB_AP_PATH . 'includes/class-eb-ap-database.php';
|
|
require_once EB_AP_PATH . 'includes/class-eb-ap-rates.php';
|
|
require_once EB_AP_PATH . 'includes/class-eb-ap-availability.php';
|
|
require_once EB_AP_PATH . 'includes/class-eb-ap-deals.php';
|
|
require_once EB_AP_PATH . 'includes/class-eb-ap-restrictions.php';
|
|
require_once EB_AP_PATH . 'includes/class-eb-ap-calendar.php';
|
|
|
|
// Admin classes
|
|
if (is_admin()) {
|
|
require_once EB_AP_PATH . 'includes/admin/class-eb-ap-admin.php';
|
|
require_once EB_AP_PATH . 'includes/admin/class-eb-ap-settings.php';
|
|
require_once EB_AP_PATH . 'includes/admin/class-eb-ap-metaboxes.php';
|
|
}
|
|
|
|
// Frontend classes
|
|
require_once EB_AP_PATH . 'includes/frontend/class-eb-ap-frontend.php';
|
|
require_once EB_AP_PATH . 'includes/frontend/class-eb-ap-pricing.php';
|
|
|
|
// API classes
|
|
require_once EB_AP_PATH . 'includes/api/class-eb-ap-api.php';
|
|
|
|
// Helper functions
|
|
require_once EB_AP_PATH . 'includes/functions.php';
|
|
}
|
|
|
|
/**
|
|
* Initialize classes
|
|
*/
|
|
private function init_classes() {
|
|
// Core classes
|
|
EB_AP_Database::instance();
|
|
EB_AP_Rates::instance();
|
|
EB_AP_Availability::instance();
|
|
EB_AP_Deals::instance();
|
|
EB_AP_Restrictions::instance();
|
|
EB_AP_Calendar::instance();
|
|
|
|
// Admin classes
|
|
if (is_admin()) {
|
|
EB_AP_Admin::instance();
|
|
EB_AP_Settings::instance();
|
|
EB_AP_Metaboxes::instance();
|
|
}
|
|
|
|
// Frontend classes
|
|
if (!is_admin()) {
|
|
EB_AP_Frontend::instance();
|
|
EB_AP_Pricing::instance();
|
|
}
|
|
|
|
// API
|
|
EB_AP_API::instance();
|
|
}
|
|
|
|
/**
|
|
* Initialize text domain
|
|
*/
|
|
public function init_textdomain() {
|
|
load_plugin_textdomain(
|
|
'eb-advanced-pricing',
|
|
false,
|
|
dirname(plugin_basename(__FILE__)) . '/languages/'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Plugin activation
|
|
*/
|
|
public function activate() {
|
|
if (!class_exists('Eagle_Booking')) {
|
|
deactivate_plugins(plugin_basename(__FILE__));
|
|
wp_die(
|
|
__('Eagle Booking Advanced Pricing requires Eagle Booking plugin to be installed and activated.', 'eb-advanced-pricing'),
|
|
'Plugin dependency check',
|
|
array('back_link' => true)
|
|
);
|
|
}
|
|
|
|
// Create database tables
|
|
$this->create_tables();
|
|
|
|
// Set default options
|
|
$this->set_default_options();
|
|
|
|
// Flush rewrite rules
|
|
flush_rewrite_rules();
|
|
|
|
// Set activation flag
|
|
update_option('eb_ap_activated', true);
|
|
}
|
|
|
|
/**
|
|
* Plugin deactivation
|
|
*/
|
|
public function deactivate() {
|
|
// Remove activation flag
|
|
delete_option('eb_ap_activated');
|
|
|
|
// Flush rewrite rules
|
|
flush_rewrite_rules();
|
|
}
|
|
|
|
/**
|
|
* Create database tables
|
|
*/
|
|
private function create_tables() {
|
|
global $wpdb;
|
|
|
|
$charset_collate = $wpdb->get_charset_collate();
|
|
|
|
// Rates table
|
|
$sql_rates = "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;";
|
|
|
|
// Availability table
|
|
$sql_availability = "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;";
|
|
|
|
// Deals table
|
|
$sql_deals = "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;";
|
|
|
|
// Restrictions table
|
|
$sql_restrictions = "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;";
|
|
|
|
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
|
dbDelta($sql_rates);
|
|
dbDelta($sql_availability);
|
|
dbDelta($sql_deals);
|
|
dbDelta($sql_restrictions);
|
|
}
|
|
|
|
/**
|
|
* Set default options
|
|
*/
|
|
private function set_default_options() {
|
|
$defaults = array(
|
|
'eb_ap_enabled' => 'yes',
|
|
'eb_ap_calendar_view' => 'month',
|
|
'eb_ap_default_availability' => 10,
|
|
'eb_ap_pricing_model' => 'per_room',
|
|
'eb_ap_allow_overbooking' => 'no',
|
|
'eb_ap_auto_close_sold_out' => 'yes',
|
|
'eb_ap_deal_priority' => 'highest_discount',
|
|
'eb_ap_currency_display' => 'symbol',
|
|
'eb_ap_date_format' => 'Y-m-d',
|
|
'eb_ap_time_format' => 'H:i',
|
|
);
|
|
|
|
foreach ($defaults as $key => $value) {
|
|
if (!get_option($key)) {
|
|
update_option($key, $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add admin menu
|
|
*/
|
|
public function admin_menu() {
|
|
add_submenu_page(
|
|
'eagle-booking',
|
|
__('Advanced Pricing', 'eb-advanced-pricing'),
|
|
__('Advanced Pricing', 'eb-advanced-pricing'),
|
|
'manage_options',
|
|
'eb-advanced-pricing',
|
|
array($this, 'admin_page')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Admin page callback
|
|
*/
|
|
public function admin_page() {
|
|
include EB_AP_PATH . 'includes/admin/views/main.php';
|
|
}
|
|
|
|
/**
|
|
* Enqueue admin scripts
|
|
*/
|
|
public function admin_enqueue_scripts($hook) {
|
|
if (strpos($hook, 'eb-advanced-pricing') === false) {
|
|
return;
|
|
}
|
|
|
|
wp_enqueue_script('jquery');
|
|
wp_enqueue_script('jquery-ui-core');
|
|
wp_enqueue_script('jquery-ui-datepicker');
|
|
wp_enqueue_script('jquery-ui-draggable');
|
|
wp_enqueue_script('jquery-ui-resizable');
|
|
|
|
wp_enqueue_script(
|
|
'eb-ap-admin',
|
|
EB_AP_URL . 'assets/js/admin.js',
|
|
array('jquery', 'jquery-ui-datepicker'),
|
|
EB_AP_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_enqueue_style(
|
|
'eb-ap-admin',
|
|
EB_AP_URL . 'assets/css/admin.css',
|
|
array(),
|
|
EB_AP_VERSION
|
|
);
|
|
|
|
wp_localize_script('eb-ap-admin', 'eb_ap_ajax', array(
|
|
'ajax_url' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('eb_ap_nonce'),
|
|
'strings' => array(
|
|
'save_success' => __('Settings saved successfully!', 'eb-advanced-pricing'),
|
|
'save_error' => __('Error saving settings. Please try again.', 'eb-advanced-pricing'),
|
|
'confirm_delete' => __('Are you sure you want to delete this item?', 'eb-advanced-pricing'),
|
|
'loading' => __('Loading...', 'eb-advanced-pricing'),
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* AJAX: Update rates
|
|
*/
|
|
public function ajax_update_rates() {
|
|
check_ajax_referer('eb_ap_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions', 'eb-advanced-pricing'));
|
|
}
|
|
|
|
$room_id = intval($_POST['room_id']);
|
|
$date = sanitize_text_field($_POST['date']);
|
|
$rates = array_map('floatval', $_POST['rates']);
|
|
|
|
$result = EB_AP_Rates::instance()->update_rates($room_id, $date, $rates);
|
|
|
|
if ($result) {
|
|
wp_send_json_success(array('message' => __('Rates updated successfully', 'eb-advanced-pricing')));
|
|
} else {
|
|
wp_send_json_error(array('message' => __('Failed to update rates', 'eb-advanced-pricing')));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AJAX: Update availability
|
|
*/
|
|
public function ajax_update_availability() {
|
|
check_ajax_referer('eb_ap_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions', 'eb-advanced-pricing'));
|
|
}
|
|
|
|
$room_id = intval($_POST['room_id']);
|
|
$date = sanitize_text_field($_POST['date']);
|
|
$availability = array_map('intval', $_POST['availability']);
|
|
|
|
$result = EB_AP_Availability::instance()->update_availability($room_id, $date, $availability);
|
|
|
|
if ($result) {
|
|
wp_send_json_success(array('message' => __('Availability updated successfully', 'eb-advanced-pricing')));
|
|
} else {
|
|
wp_send_json_error(array('message' => __('Failed to update availability', 'eb-advanced-pricing')));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AJAX: Create deal
|
|
*/
|
|
public function ajax_create_deal() {
|
|
check_ajax_referer('eb_ap_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions', 'eb-advanced-pricing'));
|
|
}
|
|
|
|
$deal_data = array(
|
|
'room_id' => intval($_POST['room_id']),
|
|
'deal_type' => sanitize_text_field($_POST['deal_type']),
|
|
'deal_name' => sanitize_text_field($_POST['deal_name']),
|
|
'discount_type' => sanitize_text_field($_POST['discount_type']),
|
|
'discount_value' => floatval($_POST['discount_value']),
|
|
'date_from' => sanitize_text_field($_POST['date_from']),
|
|
'date_to' => sanitize_text_field($_POST['date_to']),
|
|
'min_stay' => intval($_POST['min_stay']),
|
|
'max_stay' => intval($_POST['max_stay']),
|
|
'advance_booking_days' => intval($_POST['advance_booking_days']),
|
|
);
|
|
|
|
$result = EB_AP_Deals::instance()->create_deal($deal_data);
|
|
|
|
if ($result) {
|
|
wp_send_json_success(array('message' => __('Deal created successfully', 'eb-advanced-pricing')));
|
|
} else {
|
|
wp_send_json_error(array('message' => __('Failed to create deal', 'eb-advanced-pricing')));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AJAX: Get calendar data
|
|
*/
|
|
public function ajax_get_calendar_data() {
|
|
check_ajax_referer('eb_ap_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions', 'eb-advanced-pricing'));
|
|
}
|
|
|
|
$room_id = intval($_POST['room_id']);
|
|
$start_date = sanitize_text_field($_POST['start_date']);
|
|
$end_date = sanitize_text_field($_POST['end_date']);
|
|
|
|
$calendar_data = EB_AP_Calendar::instance()->get_calendar_data($room_id, $start_date, $end_date);
|
|
|
|
wp_send_json_success($calendar_data);
|
|
}
|
|
|
|
/**
|
|
* Filter room price calculation
|
|
*/
|
|
public function calculate_room_price($price, $room_id, $date, $guests) {
|
|
return EB_AP_Pricing::instance()->calculate_price($room_id, $date, $guests);
|
|
}
|
|
|
|
/**
|
|
* Filter availability check
|
|
*/
|
|
public function check_availability($available, $room_id, $date) {
|
|
return EB_AP_Availability::instance()->is_available($room_id, $date);
|
|
}
|
|
|
|
/**
|
|
* Apply deals to search results
|
|
*/
|
|
public function apply_deals_to_results($results, $search_params) {
|
|
return EB_AP_Deals::instance()->apply_deals_to_results($results, $search_params);
|
|
}
|
|
|
|
/**
|
|
* Missing Eagle Booking notice
|
|
*/
|
|
public function missing_eagle_booking_notice() {
|
|
?>
|
|
<div class="notice notice-error">
|
|
<p>
|
|
<?php _e('Eagle Booking Advanced Pricing requires Eagle Booking plugin to be installed and activated.', 'eb-advanced-pricing'); ?>
|
|
</p>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Eagle Booking version notice
|
|
*/
|
|
public function eagle_booking_version_notice() {
|
|
?>
|
|
<div class="notice notice-warning">
|
|
<p>
|
|
<?php printf(
|
|
__('Eagle Booking Advanced Pricing requires Eagle Booking version %s or higher. Please update Eagle Booking.', 'eb-advanced-pricing'),
|
|
self::MIN_EB_VERSION
|
|
); ?>
|
|
</p>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main instance of plugin
|
|
*/
|
|
function EB_Advanced_Pricing() {
|
|
return EB_Advanced_Pricing::instance();
|
|
}
|
|
|
|
// Initialize the plugin
|
|
EB_Advanced_Pricing();
|