2026-01-31 13:15:13 +01:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Main Plugin class.
|
|
|
|
|
*
|
|
|
|
|
* @package Magdev\WpBnb
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
declare( strict_types=1 );
|
|
|
|
|
|
|
|
|
|
namespace Magdev\WpBnb;
|
|
|
|
|
|
2026-01-31 14:37:48 +01:00
|
|
|
use Magdev\WpBnb\Admin\Calendar as CalendarAdmin;
|
2026-01-31 14:10:30 +01:00
|
|
|
use Magdev\WpBnb\Admin\Seasons as SeasonsAdmin;
|
2026-01-31 14:37:48 +01:00
|
|
|
use Magdev\WpBnb\Booking\Availability;
|
|
|
|
|
use Magdev\WpBnb\Booking\EmailNotifier;
|
2026-01-31 13:15:13 +01:00
|
|
|
use Magdev\WpBnb\License\Manager as LicenseManager;
|
2026-01-31 14:37:48 +01:00
|
|
|
use Magdev\WpBnb\PostTypes\Booking;
|
2026-01-31 13:45:06 +01:00
|
|
|
use Magdev\WpBnb\PostTypes\Building;
|
2026-01-31 14:59:43 +01:00
|
|
|
use Magdev\WpBnb\PostTypes\Guest;
|
2026-01-31 13:45:06 +01:00
|
|
|
use Magdev\WpBnb\PostTypes\Room;
|
2026-01-31 14:59:43 +01:00
|
|
|
use Magdev\WpBnb\Privacy\Manager as PrivacyManager;
|
2026-01-31 14:10:30 +01:00
|
|
|
use Magdev\WpBnb\Pricing\Season;
|
2026-01-31 13:45:06 +01:00
|
|
|
use Magdev\WpBnb\Taxonomies\Amenity;
|
|
|
|
|
use Magdev\WpBnb\Taxonomies\RoomType;
|
2026-01-31 13:15:13 +01:00
|
|
|
use Twig\Environment;
|
|
|
|
|
use Twig\Loader\FilesystemLoader;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Main Plugin singleton class.
|
|
|
|
|
*/
|
|
|
|
|
final class Plugin {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Plugin instance.
|
|
|
|
|
*
|
|
|
|
|
* @var Plugin|null
|
|
|
|
|
*/
|
|
|
|
|
private static ?Plugin $instance = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Twig environment.
|
|
|
|
|
*
|
|
|
|
|
* @var Environment|null
|
|
|
|
|
*/
|
|
|
|
|
private ?Environment $twig = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get plugin instance.
|
|
|
|
|
*
|
|
|
|
|
* @return Plugin
|
|
|
|
|
*/
|
|
|
|
|
public static function get_instance(): Plugin {
|
|
|
|
|
if ( null === self::$instance ) {
|
|
|
|
|
self::$instance = new self();
|
|
|
|
|
}
|
|
|
|
|
return self::$instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Private constructor to enforce singleton.
|
|
|
|
|
*/
|
|
|
|
|
private function __construct() {
|
|
|
|
|
$this->init_hooks();
|
|
|
|
|
$this->init_components();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize WordPress hooks.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function init_hooks(): void {
|
|
|
|
|
// Load text domain.
|
|
|
|
|
add_action( 'init', array( $this, 'load_textdomain' ) );
|
|
|
|
|
|
|
|
|
|
// Register assets.
|
|
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
|
|
|
|
|
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_assets' ) );
|
|
|
|
|
|
|
|
|
|
// Add plugin action links.
|
|
|
|
|
add_filter( 'plugin_action_links_' . WP_BNB_BASENAME, array( $this, 'add_action_links' ) );
|
2026-01-31 13:45:06 +01:00
|
|
|
|
|
|
|
|
// Register custom post types and taxonomies.
|
|
|
|
|
$this->register_post_types();
|
|
|
|
|
$this->register_taxonomies();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register custom post types.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function register_post_types(): void {
|
|
|
|
|
Building::init();
|
|
|
|
|
Room::init();
|
2026-01-31 14:37:48 +01:00
|
|
|
Booking::init();
|
2026-01-31 14:59:43 +01:00
|
|
|
Guest::init();
|
2026-01-31 13:45:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register custom taxonomies.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function register_taxonomies(): void {
|
|
|
|
|
// Taxonomies must be registered before post types that use them.
|
|
|
|
|
Amenity::init();
|
|
|
|
|
RoomType::init();
|
2026-01-31 13:15:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize plugin components.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function init_components(): void {
|
|
|
|
|
// Initialize License Manager (always active for admin).
|
|
|
|
|
LicenseManager::get_instance();
|
|
|
|
|
|
|
|
|
|
// Initialize admin components.
|
|
|
|
|
if ( is_admin() ) {
|
|
|
|
|
$this->init_admin();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize frontend components only if licensed.
|
|
|
|
|
if ( ! is_admin() && LicenseManager::is_license_valid() ) {
|
|
|
|
|
$this->init_frontend();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize admin components.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function init_admin(): void {
|
|
|
|
|
// Admin menu and settings will be added here.
|
|
|
|
|
add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
|
|
|
|
|
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
2026-01-31 14:10:30 +01:00
|
|
|
|
|
|
|
|
// Initialize seasons admin page.
|
|
|
|
|
SeasonsAdmin::init();
|
2026-01-31 14:37:48 +01:00
|
|
|
|
|
|
|
|
// Initialize calendar admin page.
|
|
|
|
|
CalendarAdmin::init();
|
|
|
|
|
|
|
|
|
|
// Initialize email notifier.
|
|
|
|
|
EmailNotifier::init();
|
|
|
|
|
|
2026-01-31 14:59:43 +01:00
|
|
|
// Initialize privacy manager for GDPR compliance.
|
|
|
|
|
PrivacyManager::init();
|
|
|
|
|
|
2026-01-31 14:37:48 +01:00
|
|
|
// Register AJAX handlers.
|
|
|
|
|
add_action( 'wp_ajax_wp_bnb_check_availability', array( $this, 'ajax_check_availability' ) );
|
2026-01-31 14:59:43 +01:00
|
|
|
add_action( 'wp_ajax_wp_bnb_search_guest', array( $this, 'ajax_search_guest' ) );
|
2026-01-31 13:15:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize frontend components.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function init_frontend(): void {
|
|
|
|
|
// Frontend shortcodes, blocks, and widgets will be added here.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load plugin text domain.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function load_textdomain(): void {
|
|
|
|
|
load_plugin_textdomain(
|
|
|
|
|
'wp-bnb',
|
|
|
|
|
false,
|
|
|
|
|
dirname( WP_BNB_BASENAME ) . '/languages'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enqueue admin assets.
|
|
|
|
|
*
|
|
|
|
|
* @param string $hook_suffix Current admin page hook.
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function enqueue_admin_assets( string $hook_suffix ): void {
|
2026-01-31 13:45:06 +01:00
|
|
|
global $post_type;
|
|
|
|
|
|
|
|
|
|
// Check if we're on plugin pages or editing our custom post types.
|
2026-01-31 14:10:30 +01:00
|
|
|
$is_plugin_page = strpos( $hook_suffix, 'wp-bnb' ) !== false;
|
2026-01-31 14:59:43 +01:00
|
|
|
$is_our_post_type = in_array( $post_type, array( Building::POST_TYPE, Room::POST_TYPE, Booking::POST_TYPE, Guest::POST_TYPE ), true );
|
2026-01-31 14:10:30 +01:00
|
|
|
$is_edit_screen = in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true );
|
2026-01-31 13:45:06 +01:00
|
|
|
|
|
|
|
|
if ( ! $is_plugin_page && ! ( $is_our_post_type && $is_edit_screen ) ) {
|
2026-01-31 13:15:13 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wp_enqueue_style(
|
|
|
|
|
'wp-bnb-admin',
|
|
|
|
|
WP_BNB_URL . 'assets/css/admin.css',
|
|
|
|
|
array(),
|
|
|
|
|
WP_BNB_VERSION
|
|
|
|
|
);
|
|
|
|
|
|
2026-01-31 13:45:06 +01:00
|
|
|
$script_deps = array( 'jquery' );
|
|
|
|
|
|
|
|
|
|
// Add media dependencies for room gallery.
|
|
|
|
|
if ( Room::POST_TYPE === $post_type && $is_edit_screen ) {
|
|
|
|
|
wp_enqueue_media();
|
|
|
|
|
$script_deps[] = 'jquery-ui-sortable';
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 13:15:13 +01:00
|
|
|
wp_enqueue_script(
|
|
|
|
|
'wp-bnb-admin',
|
|
|
|
|
WP_BNB_URL . 'assets/js/admin.js',
|
2026-01-31 13:45:06 +01:00
|
|
|
$script_deps,
|
2026-01-31 13:15:13 +01:00
|
|
|
WP_BNB_VERSION,
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
wp_localize_script(
|
|
|
|
|
'wp-bnb-admin',
|
|
|
|
|
'wpBnbAdmin',
|
|
|
|
|
array(
|
2026-01-31 13:45:06 +01:00
|
|
|
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
|
|
|
|
'nonce' => wp_create_nonce( 'wp_bnb_admin_nonce' ),
|
|
|
|
|
'postType' => $post_type,
|
|
|
|
|
'i18n' => array(
|
2026-01-31 14:37:48 +01:00
|
|
|
'validating' => __( 'Validating...', 'wp-bnb' ),
|
|
|
|
|
'activating' => __( 'Activating...', 'wp-bnb' ),
|
|
|
|
|
'error' => __( 'An error occurred. Please try again.', 'wp-bnb' ),
|
|
|
|
|
'selectImages' => __( 'Select Images', 'wp-bnb' ),
|
|
|
|
|
'addToGallery' => __( 'Add to Gallery', 'wp-bnb' ),
|
|
|
|
|
'confirmRemove' => __( 'Are you sure you want to remove this image?', 'wp-bnb' ),
|
|
|
|
|
'increase' => __( 'increase', 'wp-bnb' ),
|
|
|
|
|
'discount' => __( 'discount', 'wp-bnb' ),
|
|
|
|
|
'normalPrice' => __( 'Normal price', 'wp-bnb' ),
|
|
|
|
|
'checking' => __( 'Checking availability...', 'wp-bnb' ),
|
|
|
|
|
'available' => __( 'Available', 'wp-bnb' ),
|
|
|
|
|
'notAvailable' => __( 'Not available - conflicts with existing booking', 'wp-bnb' ),
|
|
|
|
|
'selectRoomAndDates' => __( 'Select room and dates to check availability', 'wp-bnb' ),
|
|
|
|
|
'nights' => __( 'nights', 'wp-bnb' ),
|
|
|
|
|
'night' => __( 'night', 'wp-bnb' ),
|
|
|
|
|
'calculating' => __( 'Calculating price...', 'wp-bnb' ),
|
2026-01-31 14:59:43 +01:00
|
|
|
'searchingGuests' => __( 'Searching...', 'wp-bnb' ),
|
|
|
|
|
'noGuestsFound' => __( 'No guests found', 'wp-bnb' ),
|
|
|
|
|
'selectGuest' => __( 'Select', 'wp-bnb' ),
|
|
|
|
|
'guestBlocked' => __( 'Blocked', 'wp-bnb' ),
|
2026-01-31 13:15:13 +01:00
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enqueue frontend assets.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function enqueue_frontend_assets(): void {
|
|
|
|
|
// Only load if licensed.
|
|
|
|
|
if ( ! LicenseManager::is_license_valid() ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wp_enqueue_style(
|
|
|
|
|
'wp-bnb-frontend',
|
|
|
|
|
WP_BNB_URL . 'assets/css/frontend.css',
|
|
|
|
|
array(),
|
|
|
|
|
WP_BNB_VERSION
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
wp_enqueue_script(
|
|
|
|
|
'wp-bnb-frontend',
|
|
|
|
|
WP_BNB_URL . 'assets/js/frontend.js',
|
|
|
|
|
array(),
|
|
|
|
|
WP_BNB_VERSION,
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add plugin action links.
|
|
|
|
|
*
|
|
|
|
|
* @param array $links Existing plugin links.
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public function add_action_links( array $links ): array {
|
|
|
|
|
$plugin_links = array(
|
|
|
|
|
'<a href="' . esc_url( admin_url( 'admin.php?page=wp-bnb-settings' ) ) . '">' . esc_html__( 'Settings', 'wp-bnb' ) . '</a>',
|
|
|
|
|
);
|
|
|
|
|
return array_merge( $plugin_links, $links );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register admin menu.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function register_admin_menu(): void {
|
|
|
|
|
// Main menu.
|
|
|
|
|
add_menu_page(
|
|
|
|
|
__( 'WP BnB', 'wp-bnb' ),
|
|
|
|
|
__( 'WP BnB', 'wp-bnb' ),
|
|
|
|
|
'manage_options',
|
|
|
|
|
'wp-bnb',
|
|
|
|
|
array( $this, 'render_dashboard_page' ),
|
|
|
|
|
'dashicons-building',
|
|
|
|
|
30
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Dashboard submenu.
|
|
|
|
|
add_submenu_page(
|
|
|
|
|
'wp-bnb',
|
|
|
|
|
__( 'Dashboard', 'wp-bnb' ),
|
|
|
|
|
__( 'Dashboard', 'wp-bnb' ),
|
|
|
|
|
'manage_options',
|
|
|
|
|
'wp-bnb',
|
|
|
|
|
array( $this, 'render_dashboard_page' )
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Settings submenu.
|
|
|
|
|
add_submenu_page(
|
|
|
|
|
'wp-bnb',
|
|
|
|
|
__( 'Settings', 'wp-bnb' ),
|
|
|
|
|
__( 'Settings', 'wp-bnb' ),
|
|
|
|
|
'manage_options',
|
|
|
|
|
'wp-bnb-settings',
|
|
|
|
|
array( $this, 'render_settings_page' )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register plugin settings.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function register_settings(): void {
|
|
|
|
|
// License settings are handled by LicenseManager.
|
|
|
|
|
// Additional settings will be added here.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render dashboard page.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function render_dashboard_page(): void {
|
|
|
|
|
$license_status = LicenseManager::get_cached_status();
|
|
|
|
|
?>
|
|
|
|
|
<div class="wrap">
|
|
|
|
|
<h1><?php esc_html_e( 'WP BnB Dashboard', 'wp-bnb' ); ?></h1>
|
|
|
|
|
|
|
|
|
|
<?php if ( 'valid' !== $license_status ) : ?>
|
|
|
|
|
<div class="notice notice-warning">
|
|
|
|
|
<p>
|
|
|
|
|
<?php
|
|
|
|
|
printf(
|
|
|
|
|
/* translators: %s: Link to settings page */
|
|
|
|
|
esc_html__( 'Your license is not active. Please %s to unlock all features.', 'wp-bnb' ),
|
|
|
|
|
'<a href="' . esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=license' ) ) . '">' . esc_html__( 'activate your license', 'wp-bnb' ) . '</a>'
|
|
|
|
|
);
|
|
|
|
|
?>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
<div class="wp-bnb-dashboard">
|
|
|
|
|
<p><?php esc_html_e( 'Welcome to WP BnB Management. Use the menu on the left to manage your buildings, rooms, bookings, and guests.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render settings page.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function render_settings_page(): void {
|
|
|
|
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Tab switching only.
|
|
|
|
|
$active_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general';
|
|
|
|
|
|
|
|
|
|
// Handle form submission.
|
|
|
|
|
if ( isset( $_POST['wp_bnb_settings_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_bnb_settings_nonce'] ), 'wp_bnb_save_settings' ) ) {
|
|
|
|
|
$this->save_settings( $active_tab );
|
|
|
|
|
}
|
|
|
|
|
?>
|
|
|
|
|
<div class="wrap">
|
|
|
|
|
<h1><?php esc_html_e( 'WP BnB Settings', 'wp-bnb' ); ?></h1>
|
|
|
|
|
|
|
|
|
|
<nav class="nav-tab-wrapper">
|
|
|
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=general' ) ); ?>"
|
|
|
|
|
class="nav-tab <?php echo 'general' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
|
|
|
|
<?php esc_html_e( 'General', 'wp-bnb' ); ?>
|
|
|
|
|
</a>
|
2026-01-31 14:10:30 +01:00
|
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=pricing' ) ); ?>"
|
|
|
|
|
class="nav-tab <?php echo 'pricing' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
|
|
|
|
<?php esc_html_e( 'Pricing', 'wp-bnb' ); ?>
|
|
|
|
|
</a>
|
2026-01-31 13:15:13 +01:00
|
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=license' ) ); ?>"
|
|
|
|
|
class="nav-tab <?php echo 'license' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
|
|
|
|
<?php esc_html_e( 'License', 'wp-bnb' ); ?>
|
|
|
|
|
</a>
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
<div class="tab-content">
|
|
|
|
|
<?php
|
|
|
|
|
switch ( $active_tab ) {
|
2026-01-31 14:10:30 +01:00
|
|
|
case 'pricing':
|
|
|
|
|
$this->render_pricing_settings();
|
|
|
|
|
break;
|
2026-01-31 13:15:13 +01:00
|
|
|
case 'license':
|
|
|
|
|
$this->render_license_settings();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$this->render_general_settings();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
?>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render general settings tab.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function render_general_settings(): void {
|
|
|
|
|
?>
|
|
|
|
|
<form method="post" action="">
|
|
|
|
|
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
|
|
|
|
|
|
|
|
|
<table class="form-table" role="presentation">
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_business_name"><?php esc_html_e( 'Business Name', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="text" name="wp_bnb_business_name" id="wp_bnb_business_name"
|
|
|
|
|
value="<?php echo esc_attr( get_option( 'wp_bnb_business_name', '' ) ); ?>"
|
|
|
|
|
class="regular-text">
|
|
|
|
|
<p class="description"><?php esc_html_e( 'The name of your B&B business.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_currency"><?php esc_html_e( 'Currency', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<select name="wp_bnb_currency" id="wp_bnb_currency">
|
|
|
|
|
<?php
|
|
|
|
|
$currencies = array(
|
|
|
|
|
'CHF' => __( 'Swiss Franc (CHF)', 'wp-bnb' ),
|
|
|
|
|
'EUR' => __( 'Euro (EUR)', 'wp-bnb' ),
|
|
|
|
|
'USD' => __( 'US Dollar (USD)', 'wp-bnb' ),
|
|
|
|
|
'GBP' => __( 'British Pound (GBP)', 'wp-bnb' ),
|
|
|
|
|
);
|
|
|
|
|
$current = get_option( 'wp_bnb_currency', 'CHF' );
|
|
|
|
|
foreach ( $currencies as $code => $label ) :
|
|
|
|
|
?>
|
|
|
|
|
<option value="<?php echo esc_attr( $code ); ?>" <?php selected( $current, $code ); ?>>
|
|
|
|
|
<?php echo esc_html( $label ); ?>
|
|
|
|
|
</option>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</select>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
<?php submit_button( __( 'Save Settings', 'wp-bnb' ) ); ?>
|
|
|
|
|
</form>
|
|
|
|
|
<?php
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 14:10:30 +01:00
|
|
|
/**
|
|
|
|
|
* Render pricing settings tab.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function render_pricing_settings(): void {
|
|
|
|
|
$short_term_max = get_option( 'wp_bnb_short_term_max_nights', 6 );
|
|
|
|
|
$mid_term_max = get_option( 'wp_bnb_mid_term_max_nights', 27 );
|
|
|
|
|
$weekend_days = get_option( 'wp_bnb_weekend_days', '5,6' );
|
|
|
|
|
$seasons = Season::all();
|
|
|
|
|
|
|
|
|
|
$days_of_week = array(
|
|
|
|
|
1 => __( 'Monday', 'wp-bnb' ),
|
|
|
|
|
2 => __( 'Tuesday', 'wp-bnb' ),
|
|
|
|
|
3 => __( 'Wednesday', 'wp-bnb' ),
|
|
|
|
|
4 => __( 'Thursday', 'wp-bnb' ),
|
|
|
|
|
5 => __( 'Friday', 'wp-bnb' ),
|
|
|
|
|
6 => __( 'Saturday', 'wp-bnb' ),
|
|
|
|
|
7 => __( 'Sunday', 'wp-bnb' ),
|
|
|
|
|
);
|
|
|
|
|
$selected_days = array_map( 'intval', explode( ',', $weekend_days ) );
|
|
|
|
|
?>
|
|
|
|
|
<form method="post" action="">
|
|
|
|
|
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
|
|
|
|
|
|
|
|
|
<h2><?php esc_html_e( 'Pricing Tier Thresholds', 'wp-bnb' ); ?></h2>
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Define the number of nights that determine which pricing tier applies.', 'wp-bnb' ); ?></p>
|
|
|
|
|
|
|
|
|
|
<table class="form-table" role="presentation">
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_short_term_max_nights"><?php esc_html_e( 'Short-term (Nightly)', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="number" name="wp_bnb_short_term_max_nights" id="wp_bnb_short_term_max_nights"
|
|
|
|
|
value="<?php echo esc_attr( $short_term_max ); ?>"
|
|
|
|
|
class="small-text" min="1" max="30">
|
|
|
|
|
<?php esc_html_e( 'nights or fewer', 'wp-bnb' ); ?>
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Stays up to this many nights use the nightly rate.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_mid_term_max_nights"><?php esc_html_e( 'Mid-term (Weekly)', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="number" name="wp_bnb_mid_term_max_nights" id="wp_bnb_mid_term_max_nights"
|
|
|
|
|
value="<?php echo esc_attr( $mid_term_max ); ?>"
|
|
|
|
|
class="small-text" min="7" max="90">
|
|
|
|
|
<?php esc_html_e( 'nights or fewer', 'wp-bnb' ); ?>
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Stays longer than short-term but up to this many nights use the weekly rate.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row"><?php esc_html_e( 'Long-term (Monthly)', 'wp-bnb' ); ?></th>
|
|
|
|
|
<td>
|
|
|
|
|
<p class="description">
|
|
|
|
|
<?php
|
|
|
|
|
printf(
|
|
|
|
|
/* translators: %s: number of nights */
|
|
|
|
|
esc_html__( 'Stays longer than %s nights use the monthly rate.', 'wp-bnb' ),
|
|
|
|
|
'<strong id="wp-bnb-long-term-min">' . esc_html( $mid_term_max ) . '</strong>'
|
|
|
|
|
);
|
|
|
|
|
?>
|
|
|
|
|
</p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
<h2><?php esc_html_e( 'Weekend Days', 'wp-bnb' ); ?></h2>
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Select which days are considered weekend days for weekend surcharges.', 'wp-bnb' ); ?></p>
|
|
|
|
|
|
|
|
|
|
<table class="form-table" role="presentation">
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row"><?php esc_html_e( 'Weekend Days', 'wp-bnb' ); ?></th>
|
|
|
|
|
<td>
|
|
|
|
|
<fieldset>
|
|
|
|
|
<?php foreach ( $days_of_week as $day_num => $day_name ) : ?>
|
|
|
|
|
<label style="display: inline-block; margin-right: 15px;">
|
|
|
|
|
<input type="checkbox" name="wp_bnb_weekend_days[]" value="<?php echo esc_attr( $day_num ); ?>"
|
|
|
|
|
<?php checked( in_array( $day_num, $selected_days, true ) ); ?>>
|
|
|
|
|
<?php echo esc_html( $day_name ); ?>
|
|
|
|
|
</label>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</fieldset>
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Weekend surcharges (configured per room) apply to nights starting on these days.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
<h2><?php esc_html_e( 'Seasonal Pricing', 'wp-bnb' ); ?></h2>
|
|
|
|
|
<p class="description">
|
|
|
|
|
<?php
|
|
|
|
|
printf(
|
|
|
|
|
/* translators: %s: Link to seasons page */
|
|
|
|
|
esc_html__( 'Manage seasonal pricing periods in the %s.', 'wp-bnb' ),
|
|
|
|
|
'<a href="' . esc_url( admin_url( 'admin.php?page=wp-bnb-seasons' ) ) . '">' . esc_html__( 'Seasons Manager', 'wp-bnb' ) . '</a>'
|
|
|
|
|
);
|
|
|
|
|
?>
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<?php if ( ! empty( $seasons ) ) : ?>
|
|
|
|
|
<table class="widefat striped" style="max-width: 600px;">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th><?php esc_html_e( 'Season', 'wp-bnb' ); ?></th>
|
|
|
|
|
<th><?php esc_html_e( 'Period', 'wp-bnb' ); ?></th>
|
|
|
|
|
<th><?php esc_html_e( 'Modifier', 'wp-bnb' ); ?></th>
|
|
|
|
|
<th><?php esc_html_e( 'Status', 'wp-bnb' ); ?></th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<?php foreach ( $seasons as $season ) : ?>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><?php echo esc_html( $season->name ); ?></td>
|
|
|
|
|
<td><?php echo esc_html( $season->start_date . ' - ' . $season->end_date ); ?></td>
|
|
|
|
|
<td><?php echo esc_html( $season->getModifierLabel() ); ?></td>
|
|
|
|
|
<td>
|
|
|
|
|
<?php if ( $season->active ) : ?>
|
|
|
|
|
<span class="dashicons dashicons-yes-alt" style="color: #00a32a;"></span>
|
|
|
|
|
<?php else : ?>
|
|
|
|
|
<span class="dashicons dashicons-marker" style="color: #646970;"></span>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
<?php else : ?>
|
|
|
|
|
<p><?php esc_html_e( 'No seasons configured yet.', 'wp-bnb' ); ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
<?php submit_button( __( 'Save Pricing Settings', 'wp-bnb' ) ); ?>
|
|
|
|
|
</form>
|
|
|
|
|
<?php
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 13:15:13 +01:00
|
|
|
/**
|
|
|
|
|
* Render license settings tab.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function render_license_settings(): void {
|
|
|
|
|
$license_key = LicenseManager::get_license_key();
|
|
|
|
|
$server_url = LicenseManager::get_server_url();
|
|
|
|
|
$license_status = LicenseManager::get_cached_status();
|
|
|
|
|
$license_data = LicenseManager::get_cached_data();
|
|
|
|
|
$last_check = LicenseManager::get_last_check();
|
|
|
|
|
?>
|
|
|
|
|
<form method="post" action="">
|
|
|
|
|
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
|
|
|
|
|
|
|
|
|
<h2><?php esc_html_e( 'License Status', 'wp-bnb' ); ?></h2>
|
|
|
|
|
|
|
|
|
|
<table class="form-table" role="presentation">
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row"><?php esc_html_e( 'Status', 'wp-bnb' ); ?></th>
|
|
|
|
|
<td>
|
|
|
|
|
<?php $this->render_license_status_badge( $license_status ); ?>
|
|
|
|
|
<?php if ( $last_check > 0 ) : ?>
|
|
|
|
|
<p class="description">
|
|
|
|
|
<?php
|
|
|
|
|
printf(
|
|
|
|
|
/* translators: %s: Time ago string */
|
|
|
|
|
esc_html__( 'Last checked: %s', 'wp-bnb' ),
|
|
|
|
|
esc_html( human_time_diff( $last_check, time() ) . ' ' . __( 'ago', 'wp-bnb' ) )
|
|
|
|
|
);
|
|
|
|
|
?>
|
|
|
|
|
</p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<?php if ( ! empty( $license_data['expires'] ) ) : ?>
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row"><?php esc_html_e( 'Expires', 'wp-bnb' ); ?></th>
|
|
|
|
|
<td>
|
|
|
|
|
<?php echo esc_html( wp_date( get_option( 'date_format' ), strtotime( $license_data['expires'] ) ) ); ?>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
<h2><?php esc_html_e( 'License Configuration', 'wp-bnb' ); ?></h2>
|
|
|
|
|
|
|
|
|
|
<table class="form-table" role="presentation">
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_license_server_url"><?php esc_html_e( 'License Server URL', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="url" name="wp_bnb_license_server_url" id="wp_bnb_license_server_url"
|
|
|
|
|
value="<?php echo esc_attr( $server_url ); ?>"
|
|
|
|
|
class="regular-text" placeholder="https://example.com">
|
|
|
|
|
<p class="description"><?php esc_html_e( 'The URL of the license server.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_license_key"><?php esc_html_e( 'License Key', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="text" name="wp_bnb_license_key" id="wp_bnb_license_key"
|
|
|
|
|
value="<?php echo esc_attr( $license_key ); ?>"
|
|
|
|
|
class="regular-text" placeholder="XXXX-XXXX-XXXX-XXXX">
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Your license key from the purchase confirmation email.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<th scope="row">
|
|
|
|
|
<label for="wp_bnb_license_server_secret"><?php esc_html_e( 'Server Secret', 'wp-bnb' ); ?></label>
|
|
|
|
|
</th>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="password" name="wp_bnb_license_server_secret" id="wp_bnb_license_server_secret"
|
|
|
|
|
value="" class="regular-text"
|
|
|
|
|
placeholder="<?php echo ! empty( LicenseManager::get_server_secret() ) ? '••••••••••••••••' : ''; ?>">
|
|
|
|
|
<p class="description"><?php esc_html_e( 'Leave empty to keep the current secret. The shared secret for secure communication.', 'wp-bnb' ); ?></p>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
<p class="submit">
|
|
|
|
|
<?php submit_button( __( 'Save License Settings', 'wp-bnb' ), 'primary', 'submit', false ); ?>
|
|
|
|
|
<button type="button" id="wp-bnb-validate-license" class="button button-secondary">
|
|
|
|
|
<?php esc_html_e( 'Validate License', 'wp-bnb' ); ?>
|
|
|
|
|
</button>
|
|
|
|
|
<button type="button" id="wp-bnb-activate-license" class="button button-secondary">
|
|
|
|
|
<?php esc_html_e( 'Activate License', 'wp-bnb' ); ?>
|
|
|
|
|
</button>
|
|
|
|
|
<span class="spinner" id="wp-bnb-license-spinner"></span>
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<div id="wp-bnb-license-message" style="display: none;"></div>
|
|
|
|
|
</form>
|
|
|
|
|
<?php
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render license status badge.
|
|
|
|
|
*
|
|
|
|
|
* @param string $status License status.
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function render_license_status_badge( string $status ): void {
|
|
|
|
|
$badges = array(
|
|
|
|
|
'valid' => array(
|
|
|
|
|
'class' => 'dashicons-yes-alt',
|
|
|
|
|
'color' => '#00a32a',
|
|
|
|
|
'label' => __( 'Valid', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
'invalid' => array(
|
|
|
|
|
'class' => 'dashicons-dismiss',
|
|
|
|
|
'color' => '#d63638',
|
|
|
|
|
'label' => __( 'Invalid', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
'expired' => array(
|
|
|
|
|
'class' => 'dashicons-warning',
|
|
|
|
|
'color' => '#dba617',
|
|
|
|
|
'label' => __( 'Expired', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
'revoked' => array(
|
|
|
|
|
'class' => 'dashicons-dismiss',
|
|
|
|
|
'color' => '#d63638',
|
|
|
|
|
'label' => __( 'Revoked', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
'inactive' => array(
|
|
|
|
|
'class' => 'dashicons-marker',
|
|
|
|
|
'color' => '#72aee6',
|
|
|
|
|
'label' => __( 'Inactive', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
'unchecked' => array(
|
|
|
|
|
'class' => 'dashicons-info',
|
|
|
|
|
'color' => '#72aee6',
|
|
|
|
|
'label' => __( 'Not checked', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
'unconfigured' => array(
|
|
|
|
|
'class' => 'dashicons-admin-generic',
|
|
|
|
|
'color' => '#646970',
|
|
|
|
|
'label' => __( 'Not configured', 'wp-bnb' ),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$badge = $badges[ $status ] ?? $badges['unconfigured'];
|
|
|
|
|
?>
|
|
|
|
|
<span class="wp-bnb-license-status" style="color: <?php echo esc_attr( $badge['color'] ); ?>;">
|
|
|
|
|
<span class="dashicons <?php echo esc_attr( $badge['class'] ); ?>"></span>
|
|
|
|
|
<?php echo esc_html( $badge['label'] ); ?>
|
|
|
|
|
</span>
|
|
|
|
|
<?php
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Save settings based on active tab.
|
|
|
|
|
*
|
|
|
|
|
* @param string $tab Active tab.
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function save_settings( string $tab ): void {
|
|
|
|
|
switch ( $tab ) {
|
2026-01-31 14:10:30 +01:00
|
|
|
case 'pricing':
|
|
|
|
|
$this->save_pricing_settings();
|
|
|
|
|
break;
|
2026-01-31 13:15:13 +01:00
|
|
|
case 'license':
|
|
|
|
|
$this->save_license_settings();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$this->save_general_settings();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Save general settings.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function save_general_settings(): void {
|
|
|
|
|
if ( isset( $_POST['wp_bnb_business_name'] ) ) {
|
|
|
|
|
update_option( 'wp_bnb_business_name', sanitize_text_field( wp_unslash( $_POST['wp_bnb_business_name'] ) ) );
|
|
|
|
|
}
|
|
|
|
|
if ( isset( $_POST['wp_bnb_currency'] ) ) {
|
|
|
|
|
update_option( 'wp_bnb_currency', sanitize_text_field( wp_unslash( $_POST['wp_bnb_currency'] ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'Settings saved.', 'wp-bnb' ), 'success' );
|
|
|
|
|
settings_errors( 'wp_bnb_settings' );
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 14:10:30 +01:00
|
|
|
/**
|
|
|
|
|
* Save pricing settings.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function save_pricing_settings(): void {
|
|
|
|
|
if ( isset( $_POST['wp_bnb_short_term_max_nights'] ) ) {
|
|
|
|
|
$value = absint( $_POST['wp_bnb_short_term_max_nights'] );
|
|
|
|
|
$value = max( 1, min( 30, $value ) );
|
|
|
|
|
update_option( 'wp_bnb_short_term_max_nights', $value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( isset( $_POST['wp_bnb_mid_term_max_nights'] ) ) {
|
|
|
|
|
$value = absint( $_POST['wp_bnb_mid_term_max_nights'] );
|
|
|
|
|
$value = max( 7, min( 90, $value ) );
|
|
|
|
|
update_option( 'wp_bnb_mid_term_max_nights', $value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( isset( $_POST['wp_bnb_weekend_days'] ) && is_array( $_POST['wp_bnb_weekend_days'] ) ) {
|
|
|
|
|
$days = array_map( 'absint', $_POST['wp_bnb_weekend_days'] );
|
|
|
|
|
$days = array_filter( $days, fn( $d ) => $d >= 1 && $d <= 7 );
|
|
|
|
|
update_option( 'wp_bnb_weekend_days', implode( ',', $days ) );
|
|
|
|
|
} else {
|
|
|
|
|
update_option( 'wp_bnb_weekend_days', '' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'Pricing settings saved.', 'wp-bnb' ), 'success' );
|
|
|
|
|
settings_errors( 'wp_bnb_settings' );
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 13:15:13 +01:00
|
|
|
/**
|
|
|
|
|
* Save license settings.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
private function save_license_settings(): void {
|
|
|
|
|
$data = array(
|
|
|
|
|
'license_key' => isset( $_POST['wp_bnb_license_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wp_bnb_license_key'] ) ) : '',
|
|
|
|
|
'server_url' => isset( $_POST['wp_bnb_license_server_url'] ) ? esc_url_raw( wp_unslash( $_POST['wp_bnb_license_server_url'] ) ) : '',
|
|
|
|
|
'server_secret' => isset( $_POST['wp_bnb_license_server_secret'] ) ? sanitize_text_field( wp_unslash( $_POST['wp_bnb_license_server_secret'] ) ) : '',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
LicenseManager::save_settings( $data );
|
|
|
|
|
|
|
|
|
|
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'License settings saved.', 'wp-bnb' ), 'success' );
|
|
|
|
|
settings_errors( 'wp_bnb_settings' );
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 14:37:48 +01:00
|
|
|
/**
|
|
|
|
|
* AJAX handler for checking room availability.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function ajax_check_availability(): void {
|
|
|
|
|
check_ajax_referer( 'wp_bnb_admin_nonce', 'nonce' );
|
|
|
|
|
|
|
|
|
|
if ( ! current_user_can( 'edit_posts' ) ) {
|
|
|
|
|
wp_send_json_error(
|
|
|
|
|
array( 'message' => __( 'You do not have permission to perform this action.', 'wp-bnb' ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$room_id = isset( $_POST['room_id'] ) ? absint( $_POST['room_id'] ) : 0;
|
|
|
|
|
$check_in = isset( $_POST['check_in'] ) ? sanitize_text_field( wp_unslash( $_POST['check_in'] ) ) : '';
|
|
|
|
|
$check_out = isset( $_POST['check_out'] ) ? sanitize_text_field( wp_unslash( $_POST['check_out'] ) ) : '';
|
|
|
|
|
$exclude = isset( $_POST['exclude_booking'] ) ? absint( $_POST['exclude_booking'] ) : null;
|
|
|
|
|
|
|
|
|
|
if ( ! $room_id || ! $check_in || ! $check_out ) {
|
|
|
|
|
wp_send_json_error(
|
|
|
|
|
array( 'message' => __( 'Missing required parameters.', 'wp-bnb' ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate dates.
|
|
|
|
|
if ( strtotime( $check_out ) <= strtotime( $check_in ) ) {
|
|
|
|
|
wp_send_json_error(
|
|
|
|
|
array( 'message' => __( 'Check-out date must be after check-in date.', 'wp-bnb' ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$result = Availability::check_availability_with_price( $room_id, $check_in, $check_out, $exclude );
|
|
|
|
|
|
|
|
|
|
wp_send_json_success( $result );
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 14:59:43 +01:00
|
|
|
/**
|
|
|
|
|
* AJAX handler for searching guests by email.
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function ajax_search_guest(): void {
|
|
|
|
|
check_ajax_referer( 'wp_bnb_admin_nonce', 'nonce' );
|
|
|
|
|
|
|
|
|
|
if ( ! current_user_can( 'edit_posts' ) ) {
|
|
|
|
|
wp_send_json_error(
|
|
|
|
|
array( 'message' => __( 'You do not have permission to perform this action.', 'wp-bnb' ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$search = isset( $_POST['search'] ) ? sanitize_text_field( wp_unslash( $_POST['search'] ) ) : '';
|
|
|
|
|
|
|
|
|
|
if ( strlen( $search ) < 2 ) {
|
|
|
|
|
wp_send_json_success( array( 'guests' => array() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Search by email or name.
|
|
|
|
|
$guests = get_posts(
|
|
|
|
|
array(
|
|
|
|
|
'post_type' => Guest::POST_TYPE,
|
|
|
|
|
'post_status' => 'publish',
|
|
|
|
|
'posts_per_page' => 10,
|
|
|
|
|
'meta_query' => array(
|
|
|
|
|
'relation' => 'OR',
|
|
|
|
|
array(
|
|
|
|
|
'key' => '_bnb_guest_email',
|
|
|
|
|
'value' => $search,
|
|
|
|
|
'compare' => 'LIKE',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'key' => '_bnb_guest_first_name',
|
|
|
|
|
'value' => $search,
|
|
|
|
|
'compare' => 'LIKE',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'key' => '_bnb_guest_last_name',
|
|
|
|
|
'value' => $search,
|
|
|
|
|
'compare' => 'LIKE',
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$results = array();
|
|
|
|
|
foreach ( $guests as $guest ) {
|
|
|
|
|
$status = get_post_meta( $guest->ID, '_bnb_guest_status', true ) ?: 'active';
|
|
|
|
|
$results[] = array(
|
|
|
|
|
'id' => $guest->ID,
|
|
|
|
|
'name' => Guest::get_full_name( $guest->ID ),
|
|
|
|
|
'email' => get_post_meta( $guest->ID, '_bnb_guest_email', true ),
|
|
|
|
|
'phone' => get_post_meta( $guest->ID, '_bnb_guest_phone', true ),
|
|
|
|
|
'status' => $status,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wp_send_json_success( array( 'guests' => $results ) );
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 13:15:13 +01:00
|
|
|
/**
|
|
|
|
|
* Get Twig environment.
|
|
|
|
|
*
|
|
|
|
|
* @return Environment
|
|
|
|
|
*/
|
|
|
|
|
public function get_twig(): Environment {
|
|
|
|
|
if ( null === $this->twig ) {
|
|
|
|
|
$loader = new FilesystemLoader( WP_BNB_PATH . 'templates' );
|
|
|
|
|
$this->twig = new Environment(
|
|
|
|
|
$loader,
|
|
|
|
|
array(
|
|
|
|
|
'cache' => WP_DEBUG ? false : WP_BNB_PATH . 'cache/twig',
|
|
|
|
|
'debug' => WP_DEBUG,
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return $this->twig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render a Twig template.
|
|
|
|
|
*
|
|
|
|
|
* @param string $template Template name.
|
|
|
|
|
* @param array $context Template context.
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function render( string $template, array $context = array() ): string {
|
|
|
|
|
return $this->get_twig()->render( $template, $context );
|
|
|
|
|
}
|
|
|
|
|
}
|