Hotel Raxa - Advanced Booking System Implementation

🏨 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>
This commit is contained in:
Hotel Raxa Dev
2025-07-11 07:43:22 +02:00
commit 5b1e2453c7
9816 changed files with 2784509 additions and 0 deletions

View File

@@ -0,0 +1,273 @@
<?php
/**
* Widget Name: About Hotel
* Description: Widget that adds all info of the hotel.
* Author: Eagle-Themes (Jomin Muskaj)
* Author URI: http://eagle-themes.com/
* Version: 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) exit;
class Himara_About_Footer_Widget extends WP_Widget {
function __construct() {
parent::__construct(
'himara_about_footer_widget',
__( 'Himara About (Footer)', 'eagle' ),
array(
'description' => __( 'A widget that displays an about logo, description and contact info', 'eagle' ),
'classname' => 'about-footer'
)
);
}
public function widget( $args, $instance ) {
extract( $args );
if(empty($instance)){
$instance = array(
'image' => '',
'height' => '30',
'description' => '',
'address' => '',
'phone' => '',
'email' => '',
'web' => '',
'social_media_label' => '',
'facebook' => '',
'instagram' => '',
'twitter' => '',
'youtube' => '',
'airbnb' => '',
'tripadvisor' => '',
'social_media_new_tab' => ''
);
}
$image = $instance['image'] ?? '' ;
$height = $instance['height'] ?? '';
$description = $instance['description'] ?? '';
$address = $instance['address'] ?? '';
$phone = $instance['phone'] ?? '';
$email = $instance['email'] ?? '';
$web = $instance['web'] ?? '';
$web = $instance['web'] ?? '';
$facebook = $instance['facebook'] ?? '';
$social_media_label = $instance['social_media_label'] ?? '';
$instagram = $instance['instagram'] ?? '';
$twitter = $instance['twitter'] ?? '';
$youtube = $instance['youtube'] ?? '';
$airbnb = $instance['airbnb'] ?? '';
$tripadvisor = $instance['tripadvisor'] ?? '';
$social_media_new_tab = $instance['social_media_new_tab'] ?? '';
echo wp_kses_post($args['before_widget']);
if ( $social_media_new_tab == true ) {
$target = '_blank';
} else {
$target = '_self';
}
$image_full = wp_get_attachment_image_src( $image, 'full' );
$title = get_bloginfo( 'name' );
if ( $image_full != '' ) :
?>
<img src="<?php echo esc_url($image_full[0]); ?>" alt="<?php echo esc_attr($title); ?>" class="footer-logo" <?php if( $height != '' ) : ?>style="height: <?php echo esc_html($height) ?>px" <?php endif ?>>
<?php endif; ?>
<div class="inner">
<p><?php echo wp_kses($description, wp_kses_allowed_html( 'post' )); ?></p>
<ul class="contact-info">
<li><?php echo wp_kses( $address, wp_kses_allowed_html( 'post' )); ?></li>
<li><?php echo wp_kses( $phone, wp_kses_allowed_html( 'post' )); ?></li>
<li><?php echo wp_kses( $email, wp_kses_allowed_html( 'post' )); ?></li>
<li><?php echo wp_kses( $web, wp_kses_allowed_html( 'post' )); ?></li>
</ul>
</div>
<?php if ( $facebook != '' || $instagram != '' || $twitter != '' || $youtube != '' || $airbnb != '' || $tripadvisor != '' ) : ?>
<div><strong><?php echo wp_kses( $social_media_label, wp_kses_allowed_html( 'post' ) ) ?></strong></div>
<div class="eth-social-media mt10">
<?php if ( $facebook != '') : ?> <a href="<?php echo esc_url( $facebook ) ?>" class="facebook" target="<?php echo esc_attr( $target ) ?>"><i class="fa-brands fa-facebook-f"></i></a> <?php endif ?>
<?php if ( $instagram != '' ) : ?> <a href="<?php echo esc_url( $instagram ) ?>" class="instagram" target="<?php echo esc_attr( $target ) ?>"><i class="fa-brands fa-instagram"></i></a> <?php endif ?>
<?php if ( $twitter != '' ) : ?><a href="<?php echo esc_url( $twitter ) ?>" class="twitter" target="<?php echo esc_attr( $target ) ?>"><i class="fa-brands fa-twitter"></i></a><?php endif ?>
<?php if ( $youtube != '' ) : ?><a href="<?php echo esc_url( $youtube ) ?>" class="youtube" target="<?php echo esc_attr( $target ) ?>"><i class="fa-brands fa-youtube"></i></a><?php endif ?>
<?php if ( $airbnb != '' ) : ?><a href="<?php echo esc_url( $airbnb ) ?>" class="airbnb" target="<?php echo esc_attr( $target ) ?>"><i class="fa-brands fa-airbnb"></i></a><?php endif ?>
<?php if ( $tripadvisor != '' ) : ?><a href="<?php echo esc_url( $tripadvisor ) ?>" class="tripadvisor" target="<?php echo esc_attr( $target ) ?>"><i class="fa fa-tripadvisor"></i></a><?php endif ?>
</div>
<?php
endif;
echo wp_kses($after_widget, wp_kses_allowed_html( 'post' ));
}
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['image'] = strip_tags( $new_instance['image'] );
$instance['height'] = $new_instance['height'];
$instance['description'] = $new_instance['description'];
$instance['address'] = $new_instance['address'];
$instance['phone'] = $new_instance['phone'];
$instance['email'] = $new_instance['email'];
$instance['web'] = $new_instance['web'];
$instance['social_media_label'] = $new_instance['social_media_label'];
$instance['facebook'] = $new_instance['facebook'];
$instance['instagram'] = $new_instance['instagram'];
$instance['twitter'] = $new_instance['twitter'];
$instance['youtube'] = $new_instance['youtube'];
$instance['airbnb'] = $new_instance['airbnb'];
$instance['tripadvisor'] = $new_instance['tripadvisor'];
$instance['social_media_new_tab'] = $new_instance['social_media_new_tab'];
return $instance;
}
public function form( $instance ) {
$defaults = array(
'image' => '',
'height' => '',
'description' => '',
'address' => '',
'phone' => '',
'email' => '',
'web' => '',
'social_media_label' => '',
'facebook' => '',
'instagram' => '',
'twitter' => '',
'youtube' => '',
'airbnb' => '',
'tripadvisor' => '',
'social_media_new_tab' => '',
);
$instance = wp_parse_args( (array) $instance, $defaults );
$image_full = wp_get_attachment_image_src($instance['image'], 'full');
?>
<!-- Hotel Info -->
<h5><?php echo __('Hotel Info', 'eagle') ?></h5>
<p class="upload-item">
<label for="<?php echo esc_attr($this->get_field_id('image')) ?>"><?php echo __('Logo', 'eagle') ?></label><br />
<img class="custom_media_image" src="<?php echo esc_url($image_full[0]) ?>" style="display:block; max-width:100%; height:auto; margin-bottom:8px;" />
<input type="hidden" class="widefat custom_media_id" name="<?php echo esc_attr($this->get_field_name('image')); ?>" id="<?php echo esc_attr($this->get_field_id('image')) ?>" value="<?php echo esc_attr($instance['image']); ?>">
<input type="button" value="<?php echo __( 'Upload Image', 'eagle' ) ?>" class="button custom_media_upload" id="custom_image_uploader" />
<input type="button" value="<?php echo __( 'Remove', 'eagle' ) ?>" class="button custom_media_upload_remove" /></p>
</p>
<p><label for="<?php echo esc_attr($this->get_field_id( 'height' )) ?>"><?php echo __('Logo Height', 'eagle') ?>:</label>
<input id="<?php echo esc_attr($this->get_field_id( 'height' )) ?>" name="<?php echo esc_attr($this->get_field_name( 'height' )) ?>" value="<?php echo esc_attr($instance['height']) ?>" style="width:100%;" /></p>
<p><label for="<?php echo esc_attr($this->get_field_id( 'description' )) ?>"><?php echo __('About', 'eagle') ?></label>
<textarea id="<?php echo esc_attr($this->get_field_id( 'description' )) ?>" name="<?php echo esc_attr($this->get_field_name( 'description' )) ?>" style="width:100%;" rows="4"><?php echo wp_kses($instance['description'], wp_kses_allowed_html( 'post' )) ?></textarea></p>
<!-- Contact Info -->
<h5><?php echo __('Contact Info', 'eagle') ?></h5>
<p style="width: 100%">
<label><?php echo __('Address', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'address' )) ?>" value="<?php echo esc_attr($instance['address']) ?>" style="width:100%;" />
</p>
<p style="width: 100%">
<label><?php echo __('Phone', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'phone' )) ?>" value="<?php echo esc_attr($instance['phone']) ?>" style="width:100%;" />
</p>
<p style="width: 100%">
<label><?php echo __('Email', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'email' )) ?>" value="<?php echo esc_attr($instance['email']) ?>" style="width:100%;" />
</p>
<p style="width: 100%">
<label><?php echo __('Web', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'web' )) ?>" value="<?php echo esc_attr($instance['web']) ?>" style="width:100%;" />
</p>
<!-- Soacial Media -->
<h5><?php echo __('Social Media', 'eagle') ?></h5>
<p>
<label><?php echo __('Social Media Label', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'social_media_label' )) ?>" value="<?php echo esc_attr($instance['social_media_label']) ?>" style="width:100%;" />
</p>
<p>
<label><?php echo __('Facebook URL', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'facebook' )) ?>" value="<?php echo esc_attr($instance['facebook']) ?>" style="width:100%;" />
</p>
<p>
<label><?php echo __('Instagram URL', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'instagram' )) ?>" value="<?php echo esc_attr($instance['instagram']) ?>" style="width:100%;" />
</p>
<p>
<label><?php echo __('Twitter URL', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'twitter' )) ?>" value="<?php echo esc_attr($instance['twitter']) ?>" style="width:100%;" />
</p>
<p>
<label><?php echo __('Youtube URL', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'youtube' )) ?>" value="<?php echo esc_attr($instance['youtube']) ?>" style="width:100%;" />
</p>
<p>
<label><?php echo __('Airbnb URL', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'airbnb' )) ?>" value="<?php echo esc_attr($instance['airbnb']) ?>" style="width:100%;" />
</p>
<p>
<label><?php echo __('Tripadvisor URL', 'eagle') ?></label>
<input name="<?php echo esc_attr($this->get_field_name( 'tripadvisor' )) ?>" value="<?php echo esc_attr($instance['tripadvisor']) ?>" style="width:100%;" />
</p>
<p>
<input id="<?php echo esc_attr($this->get_field_name( 'social_media_new_tab' )) ?>" type="checkbox" name="<?php echo esc_attr($this->get_field_name( 'social_media_new_tab' )) ?>">
<label for="<?php echo esc_attr($this->get_field_name( 'social_media_new_tab' )) ?>"><?php echo __('Open social media links in a new tab', 'eagle') ?></label>
</p>
<?php
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Category widget class
*
* @since 1.0
*/
class himara_Category_Widget extends WP_Widget {
var $defaults;
function __construct() {
$widget_ops = array( 'classname' => 'himara_category_widget', 'description' => esc_html__( 'Display your category list with this widget', 'eagle' ) );
$control_ops = array( 'id_base' => 'himara_category_widget' );
parent::__construct( 'himara_category_widget', esc_html__( 'Categories', 'eagle' ), $widget_ops, $control_ops );
$this->defaults = array(
'title' => esc_html__( 'himara Categories', 'eagle' ),
'categories' => array(),
'count' => 1,
'class' => 'categories'
);
}
function widget( $args, $instance ) {
extract( $args );
$instance = wp_parse_args( (array) $instance, $this->defaults );
echo wp_kses_post($before_widget);
$title = apply_filters( 'widget_title', $instance['title'] );
if ( !empty($title) ) {
echo wp_kses_post($before_title . $title . $after_title);
}
?>
<div class="inner">
<ul class="categories">
<?php //$cats = get_categories( array( 'include' => $instance['categories'])); ?>
<?php $cats = get_categories(); ?>
<?php foreach($cats as $cat): ?>
<li>
<a href="<?php echo esc_url( get_category_link( $cat ) ); ?>" class=""><?php echo esc_html( $cat->name ); ?>
<?php if(!empty($instance['count'])): ?>
<span class="num_posts">
<?php echo wp_kses_post($cat->count); ?>
</span>
<?php endif; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php
echo wp_kses_post($after_widget);
}
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags( $new_instance['title'] );
$instance['categories'] = !empty($new_instance['categories']) ? $new_instance['categories'] : array();
$instance['count'] = isset($new_instance['count']) ? 1 : 0;
$instance['type'] = $new_instance['type'];
return $instance;
}
function form( $instance ) {
$instance = wp_parse_args( (array) $instance, $this->defaults ); ?>
<p>
<label for="<?php echo esc_attr($this->get_field_id( 'title' )); ?>"><?php echo esc_html__( 'Title', 'eagle' ); ?>:</label>
<input id="<?php echo esc_attr($this->get_field_id( 'title' )); ?>" type="text" name="<?php echo esc_attr($this->get_field_name( 'title' )); ?>" value="<?php echo esc_attr( $instance['title'] ); ?>" class="widefat" />
</p>
<?php $cats = get_categories( array( 'hide_empty' => false, 'number' => 0 ) ); ?>
<?php //$cats = himara_sort_option_items( $cats, $instance['categories']); ?>
<p>
<label><?php echo esc_html__( 'Choose (re-order) categories:', 'eagle' ); ?></label><br/>
<div class="himara-widget-content-sortable">
<?php foreach ( $cats as $cat ) : ?>
<?php $checked = in_array( $cat->term_id, $instance['categories'] ) ? 'checked' : ''; ?>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name( 'categories' )); ?>[]" value="<?php echo esc_attr($cat->term_id); ?>" <?php echo esc_attr($checked); ?> /><?php echo esc_html( $cat->name );?></label>
<?php endforeach; ?>
</div>
<small class="howto"><?php echo esc_html__( 'Note: Leave empty to display all categories', 'eagle' ); ?></small>
</p>
<p>
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name( 'count' )); ?>" value="1" <?php echo esc_attr( checked($instance['count'], 1, true) ); ?> /><?php echo esc_html__( 'Show post count?', 'eagle' ); ?></label>
</p>
<?php
}
}

View File

@@ -0,0 +1,23 @@
<?php
/* --------------------------------------------------------------------------
* Register Widgets
* @since 1.0.0
---------------------------------------------------------------------------*/
add_action( 'widgets_init', 'himara_register_widgets' );
if ( !function_exists( 'himara_register_widgets' ) ) :
function himara_register_widgets() {
// Include all required files
foreach ( glob ( plugin_dir_path( __FILE__ ) . "*/*.php" ) as $file ){
include_once $file;
}
register_widget( 'Himara_About_Footer_Widget' );
// register_widget( 'Himara_Contact_Footer_Widget' );
register_widget( 'Himara_Category_Widget' );
register_widget( 'Himara_Recent_Posts_Widget' );
}
endif;

View File

@@ -0,0 +1,114 @@
<?php
/**
* @ Recent posts widget extended.
* @ since 1.0.0
* @ author Eagle-Themes (Jomin Muskaj)
* @ Author URI: http://eagle-themes.com
*/
class himara_Recent_Posts_Widget extends WP_Widget {
function __construct() {
$widget_ops = array( 'classname' => 'himara_recent_posts_widget', 'description' => esc_html__( 'Display your category list with this widget', 'eagle' ) );
$control_ops = array( 'id_base' => 'himara_recent_posts_widget' );
parent::__construct( 'himara_recent_posts_widget', esc_html__( 'Recent Posts', 'eagle' ), $widget_ops, $control_ops );
$this->defaults = array(
'title' => esc_html__( 'himara Recent Posts', 'eagle' ),
'categories' => array(),
'count' => 1,
'class' => 'categories'
);
}
// WIDGET CONFIGURATION
public function widget( $args, $instance ) {
if ( ! isset( $args['widget_id'] ) ) {
$args['widget_id'] = $this->id;
}
$title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'himara - Recent Posts', 'eagle' );
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
$number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5;
if ( ! $number ) {
$number = 5;
}
$show_date = isset( $instance['show_date'] ) ? $instance['show_date'] : false;
// WIDGET OUTPUT
$r = new WP_Query( apply_filters( 'widget_posts_args', array(
'posts_per_page' => $number,
'no_found_rows' => true,
'post_status' => 'publish',
'ignore_sticky_posts' => true,
), $instance ) );
if ( ! $r->have_posts() ) {
return;
}
?>
<?php echo wp_kses_post($args['before_widget']); ?>
<?php
if ( $title ) {
echo wp_kses_post($args['before_title'] . $title . $args['after_title']);
}
?>
<?php while ( $r->have_posts() ) : $r->the_post(); ?>
<?php if (has_post_thumbnail()) : ?>
<!-- ITEM -->
<div class="recent-post-item">
<div class="row">
<!-- IMAGE -->
<div class="col-md-6 col-sm-6 col-xs-6">
<figure class="slide-right-hover">
<a href="<?php esc_url( the_permalink() ) ?>">
<img src="<?php echo the_post_thumbnail_url('himara_image_size_720_520') ?>" class="img-responsive" alt="<?php echo the_title_attribute() ?>">
</a>
</figure>
</div>
<!-- DETAILS -->
<div class="col-md-6 col-sm-6 col-xs-6">
<div class="details">
<h6 class="title"><a href="<?php the_permalink(); ?>"><?php get_the_title() ? the_title() : the_ID(); ?></a></h6>
<?php if ( $show_date ) : ?>
<span class="post-date"><i class="fa fa-clock-o"></i> <?php echo esc_html( get_the_date() ); ?></span>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php endif ?>
<?php endwhile; ?>
<?php
echo wp_kses_post($args['after_widget']);
}
// UPDATE
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['number'] = (int) $new_instance['number'];
$instance['show_date'] = isset( $new_instance['show_date'] ) ? (bool) $new_instance['show_date'] : false;
return $instance;
}
// FORMS
public function form( $instance ) {
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
$number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$show_date = isset( $instance['show_date'] ) ? (bool) $instance['show_date'] : false;
?>
<p><label for="<?php echo esc_attr($this->get_field_id( 'title' )); ?>"><?php echo esc_html__('Title', 'eagle'); ?>:</label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id( 'title' )); ?>" name="<?php echo esc_attr($this->get_field_name( 'title' )); ?>" type="text" value="<?php echo esc_html($title); ?>" /></p>
<p><label for="<?php echo esc_attr($this->get_field_id( 'number' )); ?>"><?php echo esc_html__( 'Number of posts to show', 'eagle' ); ?>:</label>
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id( 'number' )); ?>" name="<?php echo esc_attr($this->get_field_name( 'number' )); ?>" type="number" step="1" min="1" value="<?php echo esc_html($number); ?>" size="3" /></p>
<p><input class="checkbox" type="checkbox"<?php checked( $show_date ); ?> id="<?php echo esc_attr($this->get_field_id( 'show_date' )); ?>" name="<?php echo esc_attr($this->get_field_name( 'show_date' )); ?>" />
<label for="<?php echo esc_attr($this->get_field_id( 'show_date' )); ?>"><?php echo esc_html__( 'Display post date?', 'eagle' ); ?></label></p>
<?php
}
}