| 1 |
<?php /** |
| 2 |
* @version 1.0 |
| 3 |
* @package Booking Calendar |
| 4 |
* @category Content of Add New Booking |
| 5 |
* @author wpdevelop |
| 6 |
* |
| 7 |
* @web-site https://wpbookingcalendar.com/ |
| 8 |
* @email info@wpbookingcalendar.com |
| 9 |
* |
| 10 |
* @modified 2015-10-31 |
| 11 |
*/ |
| 12 |
|
| 13 |
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly |
| 14 |
|
| 15 |
|
| 16 |
/** |
| 17 |
* Check whether the Add Booking inspector interface is enabled. |
| 18 |
* |
| 19 |
* The interface is part of 11.4.4 and is enabled by default. The filter keeps |
| 20 |
* a narrow emergency fallback to the legacy toolbar for integrations that |
| 21 |
* need additional migration time; it is not connected to the 11.5 flag. |
| 22 |
* |
| 23 |
* @return bool True when the 11.4.4 inspector interface should be used. |
| 24 |
*/ |
| 25 |
function wpbc_add_booking_page_is_inspector_enabled() { |
| 26 |
|
| 27 |
return (bool) apply_filters( 'wpbc_add_booking_page_is_inspector_enabled', true ); |
| 28 |
} |
| 29 |
|
| 30 |
|
| 31 |
/** |
| 32 |
* Check whether the current request is the Add Booking administrator tab. |
| 33 |
* |
| 34 |
* @return bool True on WP Booking Calendar > Add Booking with the inspector UI enabled. |
| 35 |
*/ |
| 36 |
function wpbc_add_booking_page_is_active() { |
| 37 |
|
| 38 |
if ( ! is_admin() || ! wpbc_add_booking_page_is_inspector_enabled() ) { |
| 39 |
return false; |
| 40 |
} |
| 41 |
|
| 42 |
$page = isset( $_GET['page'] ) && ! is_array( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 43 |
$tab = isset( $_GET['tab'] ) && ! is_array( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 44 |
|
| 45 |
return 'wpbc' === $page && 'add-booking' === $tab; |
| 46 |
} |
| 47 |
|
| 48 |
|
| 49 |
/** |
| 50 |
* Build a safe Add Booking URL while preserving the current resource, form, |
| 51 |
* editing context, and calendar layout parameters. |
| 52 |
* |
| 53 |
* @param bool $allow_past Whether the resulting page should allow past dates. |
| 54 |
* |
| 55 |
* @return string Add Booking administrator URL. |
| 56 |
*/ |
| 57 |
function wpbc_add_booking_page_get_allow_past_url( $allow_past ) { |
| 58 |
|
| 59 |
$url = wpbc_get_new_booking_url__base( array( 'allow_past' ) ); |
| 60 |
|
| 61 |
// Match the legacy toolbar when returning from a payment result state. |
| 62 |
if ( ! empty( $_GET['is_show_payment_form'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 63 |
$url = add_query_arg( 'is_show_payment_form', 'Off', $url ); |
| 64 |
} |
| 65 |
|
| 66 |
if ( $allow_past ) { |
| 67 |
$url = add_query_arg( 'allow_past', '1', $url ); |
| 68 |
} |
| 69 |
|
| 70 |
return $url; |
| 71 |
} |
| 72 |
|
| 73 |
|
| 74 |
/** |
| 75 |
* Resolve a generated page asset, with a source fallback for development. |
| 76 |
* |
| 77 |
* Release packages use `_out`. The fallback keeps the page usable immediately |
| 78 |
* after a source checkout and disappears automatically after asset compilation. |
| 79 |
* |
| 80 |
* @param string $file_name Asset file name without a directory. |
| 81 |
* |
| 82 |
* @return string Asset URL. |
| 83 |
*/ |
| 84 |
function wpbc_add_booking_page_get_asset_url( $file_name ) { |
| 85 |
|
| 86 |
$file_name = sanitize_file_name( $file_name ); |
| 87 |
$folder = file_exists( __DIR__ . '/_out/' . $file_name ) ? '_out' : '_src'; |
| 88 |
|
| 89 |
return trailingslashit( plugins_url( '', __FILE__ ) ) . $folder . '/' . $file_name; |
| 90 |
} |
| 91 |
|
| 92 |
|
| 93 |
/** |
| 94 |
* Enqueue source-built styles for the Add Booking inspector page only. |
| 95 |
* |
| 96 |
* @param string $where_to_load Booking Calendar asset context. |
| 97 |
* |
| 98 |
* @return void |
| 99 |
*/ |
| 100 |
function wpbc_add_booking_page_enqueue_css( $where_to_load ) { |
| 101 |
|
| 102 |
if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_add_booking_page_is_active() ) { |
| 103 |
return; |
| 104 |
} |
| 105 |
|
| 106 |
wp_enqueue_style( |
| 107 |
'wpbc-add-booking-page', |
| 108 |
wpbc_add_booking_page_get_asset_url( 'add_booking_page.css' ), |
| 109 |
array( 'wpbc-all-admin' ), |
| 110 |
WP_BK_VERSION_NUM |
| 111 |
); |
| 112 |
} |
| 113 |
add_action( 'wpbc_enqueue_css_files', 'wpbc_add_booking_page_enqueue_css', 73 ); |
| 114 |
|
| 115 |
|
| 116 |
/** |
| 117 |
* Enqueue the inspector tab controller for the Add Booking page only. |
| 118 |
* |
| 119 |
* @param string $where_to_load Booking Calendar asset context. |
| 120 |
* |
| 121 |
* @return void |
| 122 |
*/ |
| 123 |
function wpbc_add_booking_page_enqueue_js( $where_to_load ) { |
| 124 |
|
| 125 |
if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_add_booking_page_is_active() ) { |
| 126 |
return; |
| 127 |
} |
| 128 |
|
| 129 |
wp_enqueue_script( |
| 130 |
'wpbc-add-booking-page', |
| 131 |
wpbc_add_booking_page_get_asset_url( 'add_booking_page.js' ), |
| 132 |
array( 'jquery', 'wpbc_all' ), |
| 133 |
WP_BK_VERSION_NUM, |
| 134 |
array( 'in_footer' => WPBC_JS_IN_FOOTER ) |
| 135 |
); |
| 136 |
} |
| 137 |
add_action( 'wpbc_enqueue_js_files', 'wpbc_add_booking_page_enqueue_js', 73 ); |
| 138 |
|
| 139 |
|
| 140 |
/** |
| 141 |
* Show Content |
| 142 |
* Update Content |
| 143 |
* Define Slug |
| 144 |
* Define where to show |
| 145 |
*/ |
| 146 |
class WPBC_Page_AddNewBooking extends WPBC_Page_Structure { |
| 147 |
|
| 148 |
|
| 149 |
/** |
| 150 |
* Published Booking Forms available to the current user. |
| 151 |
* |
| 152 |
* The value is loaded lazily because both the setup summary and selector use |
| 153 |
* the same list during one page render. |
| 154 |
* |
| 155 |
* @var array<string,array<string,mixed>>|null |
| 156 |
*/ |
| 157 |
private $available_booking_forms = null; |
| 158 |
|
| 159 |
|
| 160 |
/** |
| 161 |
* Place Add Booking under the shared Bookings page. |
| 162 |
* |
| 163 |
* @return string Parent page slug. |
| 164 |
*/ |
| 165 |
public function in_page() { |
| 166 |
return 'wpbc'; |
| 167 |
} |
| 168 |
|
| 169 |
/** |
| 170 |
* Register the page tab and its 11.4.4 inspector shell. |
| 171 |
* |
| 172 |
* @return array<string,array<string,mixed>> Page tab definition. |
| 173 |
*/ |
| 174 |
public function tabs() { |
| 175 |
|
| 176 |
$is_can_add_booking = WPBC_Add_Booking_Component::current_user_can_add_booking(); |
| 177 |
$is_inspector_ui = wpbc_add_booking_page_is_inspector_enabled(); |
| 178 |
|
| 179 |
$tabs = array(); |
| 180 |
$tabs['add-booking'] = array( |
| 181 |
'is_show_top_path' => true, // true | false. By default value is: true. |
| 182 |
'is_show_top_navigation' => true, |
| 183 |
'left_navigation__default_view_mode' => '', // FixIn:11.7.1.1: 'min', // '' | 'min' | 'compact' | 'max' | 'none'. By default value is: ''. |
| 184 |
'right_vertical_sidebar__is_show' => $is_inspector_ui, |
| 185 |
'right_vertical_sidebar__default_view_mode' => '', |
| 186 |
'right_vertical_sidebar_compact__is_show' => $is_inspector_ui, |
| 187 |
'page_title' => __( 'Add New Booking', 'booking' ), // Header - Title. If false, than hidden. |
| 188 |
'page_description' => __( 'Manually add new bookings from the Admin Panel.', 'booking' ), // Header - Title Description. If false, than hidden. |
| 189 |
'title' => __( 'Add booking', 'booking' ), // Title of TAB. |
| 190 |
'hint' => __( 'Add booking', 'booking' ), // Hint. |
| 191 |
'link' => '', // Can be skiped, then generated link based on Page and Tab tags. Or can be extenral link. |
| 192 |
'position' => '', // Can be: 'left' | 'right' | ''. |
| 193 |
'css_classes' => '', // this is CSS class(es). |
| 194 |
'icon' => '', // Icon - link to the real PNG img. |
| 195 |
'font_icon' => 'wpbc-bi-plus', // CSS definition of forn Icon. |
| 196 |
'default' => true, // Is this tab activated by default or not: true || false. |
| 197 |
'disabled' => ! $is_can_add_booking, // Is this tab disbaled: true || false. |
| 198 |
'hided' => ! $is_can_add_booking, // Is this tab hided: true || false. |
| 199 |
'subtabs' => array(), |
| 200 |
); |
| 201 |
|
| 202 |
return $tabs; |
| 203 |
} |
| 204 |
|
| 205 |
|
| 206 |
/** |
| 207 |
* Render the compact Settings and Help controls for the right inspector. |
| 208 |
* |
| 209 |
* @return void |
| 210 |
*/ |
| 211 |
public function right_sidebar_compact_content() { |
| 212 |
|
| 213 |
if ( ! wpbc_add_booking_page_is_inspector_enabled() ) { |
| 214 |
return; |
| 215 |
} |
| 216 |
|
| 217 |
$tabs = array( |
| 218 |
array( |
| 219 |
'id' => 'wpbc_tab_add_booking_settings', |
| 220 |
'panel_id' => 'wpbc_add_booking__inspector_settings', |
| 221 |
'title' => __( 'Settings', 'booking' ), |
| 222 |
'icon' => 'wpbc_icn_tune', |
| 223 |
'selected' => true, |
| 224 |
), |
| 225 |
array( |
| 226 |
'id' => 'wpbc_tab_add_booking_help', |
| 227 |
'panel_id' => 'wpbc_add_booking__inspector_help', |
| 228 |
'title' => __( 'Help', 'booking' ), |
| 229 |
'icon' => 'wpbc-bi-info-circle', |
| 230 |
), |
| 231 |
); |
| 232 |
$tabs = (array) apply_filters( 'wpbc_admin_add_booking_inspector_tabs', $tabs ); |
| 233 |
|
| 234 |
WPBC_UI_Sidebar_Panels::render_rightbar_tabs( |
| 235 |
$tabs, |
| 236 |
array( |
| 237 |
'aria_label' => __( 'Add Booking Panels', 'booking' ), |
| 238 |
'context' => 'add_booking', |
| 239 |
'class' => 'wpbc_add_booking__rightbar_tabs', |
| 240 |
) |
| 241 |
); |
| 242 |
} |
| 243 |
|
| 244 |
|
| 245 |
/** |
| 246 |
* Render the Builder-style right inspector panels. |
| 247 |
* |
| 248 |
* @return void |
| 249 |
*/ |
| 250 |
public function right_sidebar_content() { |
| 251 |
|
| 252 |
if ( ! wpbc_add_booking_page_is_inspector_enabled() ) { |
| 253 |
return; |
| 254 |
} |
| 255 |
?> |
| 256 |
<div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_add_booking__rightbar"> |
| 257 |
<?php |
| 258 |
WPBC_UI_Sidebar_Panels::render_panel( |
| 259 |
array( |
| 260 |
'id' => 'wpbc_add_booking__inspector_settings', |
| 261 |
'labelledby' => 'wpbc_tab_add_booking_settings', |
| 262 |
'class' => 'wpbc_add_booking__inspector_settings', |
| 263 |
), |
| 264 |
array( $this, 'render_settings_panel' ) |
| 265 |
); |
| 266 |
WPBC_UI_Sidebar_Panels::render_panel( |
| 267 |
array( |
| 268 |
'id' => 'wpbc_add_booking__inspector_help', |
| 269 |
'labelledby' => 'wpbc_tab_add_booking_help', |
| 270 |
'class' => 'wpbc_add_booking__inspector_help', |
| 271 |
'hidden' => true, |
| 272 |
), |
| 273 |
array( $this, 'render_help_panel' ) |
| 274 |
); |
| 275 |
do_action( 'wpbc_admin_add_booking_inspector_panels', $this ); |
| 276 |
?> |
| 277 |
</div> |
| 278 |
<?php |
| 279 |
} |
| 280 |
|
| 281 |
|
| 282 |
/** |
| 283 |
* Render all controls formerly shown in the Add Booking top toolbar. |
| 284 |
* |
| 285 |
* Native inspector markup preserves the established IDs, reload URLs, AJAX |
| 286 |
* save endpoint, MultiUser visibility rules, and commercial behavior. |
| 287 |
* |
| 288 |
* @return void |
| 289 |
*/ |
| 290 |
public function render_settings_panel() { |
| 291 |
|
| 292 |
WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Booking Settings', 'booking' ), __( 'Configure this manual Booking and its calendar view.', 'booking' ) ); |
| 293 |
?> |
| 294 |
<div class="wpbc_bfb__inspector__body wpbc_add_booking__inspector_body"> |
| 295 |
<div class="wpbc_add_booking__top_actions wpbc_bfb__inspector__section--content wpbc_ui_el__buttons_group"> |
| 296 |
<?php if ( function_exists( 'wpbc_toolbar_btn__auto_fill' ) ) : ?> |
| 297 |
<?php wpbc_toolbar_btn__auto_fill( array( 'submit_after_fill' => false ) ); ?> |
| 298 |
<?php endif; ?> |
| 299 |
<?php wpbc_toolbar_btn__add_new_booking(); ?> |
| 300 |
<?php do_action( 'wpbc_admin_add_booking_primary_actions', $this ); ?> |
| 301 |
</div> |
| 302 |
<?php $this->render_booking_setup_summary(); ?> |
| 303 |
<?php |
| 304 |
WPBC_UI_Sidebar_Panels::render_collapsible_group( |
| 305 |
array( |
| 306 |
'id' => 'wpbc_add_booking_setup_group', |
| 307 |
'group' => 'add-booking-setup', |
| 308 |
'title' => __( 'Booking setup', 'booking' ), |
| 309 |
'open' => false, |
| 310 |
), |
| 311 |
array( $this, 'render_booking_setup_controls' ) |
| 312 |
); |
| 313 |
WPBC_UI_Sidebar_Panels::render_collapsible_group( |
| 314 |
array( |
| 315 |
'id' => 'wpbc_add_booking_date_selection_group', |
| 316 |
'group' => 'add-booking-date-selection', |
| 317 |
'title' => __( 'Date selection', 'booking' ), |
| 318 |
'open' => false, |
| 319 |
), |
| 320 |
array( $this, 'render_date_selection_controls' ) |
| 321 |
); |
| 322 |
WPBC_UI_Sidebar_Panels::render_collapsible_group( |
| 323 |
array( |
| 324 |
'id' => 'wpbc_add_booking_tools_group', |
| 325 |
'group' => 'add-booking-tools', |
| 326 |
'title' => __( 'Booking tools', 'booking' ), |
| 327 |
'open' => false, |
| 328 |
), |
| 329 |
array( $this, 'render_booking_tools_controls' ) |
| 330 |
); |
| 331 |
WPBC_UI_Sidebar_Panels::render_collapsible_group( |
| 332 |
array( |
| 333 |
'id' => 'wpbc_add_booking_calendar_view_group', |
| 334 |
'group' => 'add-booking-calendar-view', |
| 335 |
'title' => __( 'Calendar view', 'booking' ), |
| 336 |
'open' => false, |
| 337 |
), |
| 338 |
array( $this, 'render_calendar_view_controls' ) |
| 339 |
); |
| 340 |
do_action( 'wpbc_admin_add_booking_settings_panel', $this ); |
| 341 |
?> |
| 342 |
</div> |
| 343 |
<?php |
| 344 |
} |
| 345 |
|
| 346 |
|
| 347 |
/** |
| 348 |
* Render resource and Booking Form selectors. |
| 349 |
* |
| 350 |
* @return void |
| 351 |
*/ |
| 352 |
public function render_booking_setup_controls() { |
| 353 |
|
| 354 |
$is_resource_rendered = $this->render_booking_resource_control(); |
| 355 |
$is_form_rendered = $this->render_booking_form_control(); |
| 356 |
|
| 357 |
if ( ! $is_resource_rendered && ! $is_form_rendered ) { |
| 358 |
?><p class="wpbc_add_booking__empty_setup"><?php esc_html_e( 'This Booking uses the default Booking resource and Standard Booking Form.', 'booking' ); ?></p><?php |
| 359 |
} |
| 360 |
do_action( 'wpbc_admin_add_booking_setup_panel', $this ); |
| 361 |
} |
| 362 |
|
| 363 |
|
| 364 |
/** |
| 365 |
* Render a compact summary of the current manual Booking configuration. |
| 366 |
* |
| 367 |
* Available settings are rendered as links that expand the correct inspector |
| 368 |
* group and move keyboard focus to the corresponding control. |
| 369 |
* |
| 370 |
* @return void |
| 371 |
*/ |
| 372 |
private function render_booking_setup_summary() { |
| 373 |
|
| 374 |
$resource_id = $this->get_selected_booking_resource_id(); |
| 375 |
$resource_title = function_exists( 'wpbc_get_resource_title' ) ? wpbc_get_resource_title( $resource_id ) : ''; |
| 376 |
$form_name = $this->get_selected_booking_form_name( $resource_id ); |
| 377 |
$days_mode = $this->get_current_days_selection_mode(); |
| 378 |
$send_emails = 'On' !== get_bk_option( 'booking_send_emails_off_addbooking' ); |
| 379 |
$allow_past = isset( $_GET['allow_past'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 380 |
$enabled_label = __( 'Enabled', 'booking' ); |
| 381 |
$disabled_label = __( 'Disabled', 'booking' ); |
| 382 |
|
| 383 |
if ( '' === trim( (string) $resource_title ) ) { |
| 384 |
$resource_title = sprintf( __( 'Resource #%d', 'booking' ), $resource_id ); |
| 385 |
} |
| 386 |
|
| 387 |
$form_title = 'standard' === $form_name ? __( 'Standard', 'booking' ) : wpbc_lang( $form_name ); |
| 388 |
?> |
| 389 |
<div class="wpbc_add_booking__setup_summary wpbc_bfb__inspector__section--content" |
| 390 |
data-wpbc-add-booking-enabled-label="<?php echo esc_attr( $enabled_label ); ?>" |
| 391 |
data-wpbc-add-booking-disabled-label="<?php echo esc_attr( $disabled_label ); ?>" |
| 392 |
aria-label="<?php esc_attr_e( 'Current Booking setup', 'booking' ); ?>"> |
| 393 |
<div class="wpbc_add_booking__setup_summary_item"> |
| 394 |
<span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Booking resource', 'booking' ); ?></span> |
| 395 |
<?php if ( $this->is_booking_resource_selector_available() || $this->is_booking_resource_upgrade_visible() ) : ?> |
| 396 |
<a href="#select_booking_resource" class="wpbc_add_booking__setup_summary_link" data-wpbc-add-booking-open-group="add-booking-setup" data-wpbc-add-booking-focus="#select_booking_resource"><?php echo esc_html( $resource_title ); ?></a> |
| 397 |
<?php else : ?> |
| 398 |
<strong><?php echo esc_html( $resource_title ); ?></strong> |
| 399 |
<?php endif; ?> |
| 400 |
</div> |
| 401 |
<div class="wpbc_add_booking__setup_summary_item"> |
| 402 |
<span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Booking Form', 'booking' ); ?></span> |
| 403 |
<?php if ( ! empty( $this->get_available_booking_forms() ) ) : ?> |
| 404 |
<a href="#select_booking_form" class="wpbc_add_booking__setup_summary_link" data-wpbc-add-booking-open-group="add-booking-setup" data-wpbc-add-booking-focus="#select_booking_form"><?php echo esc_html( $form_title ); ?></a> |
| 405 |
<?php else : ?> |
| 406 |
<strong><?php echo esc_html( $form_title ); ?></strong> |
| 407 |
<?php endif; ?> |
| 408 |
</div> |
| 409 |
<div class="wpbc_add_booking__setup_summary_item"> |
| 410 |
<span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Date selection', 'booking' ); ?></span> |
| 411 |
<a href="#wpbc_add_booking_date_selection_group" |
| 412 |
class="wpbc_add_booking__setup_summary_link" |
| 413 |
data-wpbc-add-booking-open-group="add-booking-date-selection" |
| 414 |
data-wpbc-add-booking-focus="input[name='wpbc_add_booking_days_selection_mode']:checked" |
| 415 |
data-wpbc-add-booking-summary="days-selection" |
| 416 |
aria-label="<?php esc_attr_e( 'Change date-selection behavior', 'booking' ); ?>"><?php echo esc_html( $this->get_days_selection_mode_label( $days_mode ) ); ?></a> |
| 417 |
</div> |
| 418 |
<div class="wpbc_add_booking__setup_summary_item"> |
| 419 |
<span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Email notifications', 'booking' ); ?></span> |
| 420 |
<a href="#wpbc_add_booking_tools_group" |
| 421 |
class="wpbc_add_booking__setup_summary_link" |
| 422 |
data-wpbc-add-booking-open-group="add-booking-tools" |
| 423 |
data-wpbc-add-booking-focus="#is_send_email_for_pending" |
| 424 |
data-wpbc-add-booking-summary="emails" |
| 425 |
aria-label="<?php esc_attr_e( 'Change email notification setting', 'booking' ); ?>"><?php echo esc_html( $send_emails ? $enabled_label : $disabled_label ); ?></a> |
| 426 |
</div> |
| 427 |
<div class="wpbc_add_booking__setup_summary_item"> |
| 428 |
<span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Allow booking in the past', 'booking' ); ?></span> |
| 429 |
<a href="#wpbc_add_booking_tools_group" |
| 430 |
class="wpbc_add_booking__setup_summary_link" |
| 431 |
data-wpbc-add-booking-open-group="add-booking-tools" |
| 432 |
data-wpbc-add-booking-focus="#is_allow_bookings_in_past" |
| 433 |
data-wpbc-add-booking-summary="allow-past" |
| 434 |
aria-label="<?php esc_attr_e( 'Change past-date Booking setting', 'booking' ); ?>"><?php echo esc_html( $allow_past ? $enabled_label : $disabled_label ); ?></a> |
| 435 |
</div> |
| 436 |
</div> |
| 437 |
<?php |
| 438 |
} |
| 439 |
|
| 440 |
|
| 441 |
/** |
| 442 |
* Render the page-local date-selection override as Calendar Settings radios. |
| 443 |
* |
| 444 |
* The radio values are not saved and do not reload the page. Add Booking |
| 445 |
* JavaScript applies them directly to the currently rendered calendar. |
| 446 |
* |
| 447 |
* @return void |
| 448 |
*/ |
| 449 |
public function render_date_selection_controls() { |
| 450 |
|
| 451 |
$resource_id = $this->get_selected_booking_resource_id(); |
| 452 |
$days_mode = $this->get_current_days_selection_mode(); |
| 453 |
$range_engine_mode = $this->get_current_range_engine_mode(); |
| 454 |
$single_label = __( 'Single day', 'booking' ); |
| 455 |
$multiple_label = __( 'Multiple days', 'booking' ); |
| 456 |
$range_label = class_exists( 'wpdev_bk_biz_s' ) ? __( 'Range days', 'booking' ) : __( 'Range days - 2 mouse clicks', 'booking' ); |
| 457 |
?> |
| 458 |
<div class="wpbc_calendar_radio_stack wpbc_add_booking__days_radio_stack" |
| 459 |
data-wpbc-add-booking-days-selection="1" |
| 460 |
data-wpbc-resource-id="<?php echo absint( $resource_id ); ?>" |
| 461 |
data-wpbc-range-engine-mode="<?php echo esc_attr( $range_engine_mode ); ?>"> |
| 462 |
<label> |
| 463 |
<input type="radio" name="wpbc_add_booking_days_selection_mode" value="single" data-wpbc-days-selection-label="<?php echo esc_attr( $single_label ); ?>" <?php checked( 'single', $days_mode ); ?> /> |
| 464 |
<span><?php echo esc_html( $single_label ); ?></span> |
| 465 |
</label> |
| 466 |
<label> |
| 467 |
<input type="radio" name="wpbc_add_booking_days_selection_mode" value="multiple" data-wpbc-days-selection-label="<?php echo esc_attr( $multiple_label ); ?>" <?php checked( 'multiple', $days_mode ); ?> /> |
| 468 |
<span><?php echo esc_html( $multiple_label ); ?></span> |
| 469 |
</label> |
| 470 |
<label> |
| 471 |
<input type="radio" name="wpbc_add_booking_days_selection_mode" value="range" data-wpbc-days-selection-label="<?php echo esc_attr( $range_label ); ?>" <?php checked( 'range', $days_mode ); ?> /> |
| 472 |
<span><?php echo esc_html( $range_label ); ?></span> |
| 473 |
</label> |
| 474 |
</div> |
| 475 |
<p class="inspector__help"><?php esc_html_e( 'This temporary override applies immediately to this calendar. Changing the mode clears the currently selected dates but does not reload the page or modify saved Calendar and Booking Form settings.', 'booking' ); ?></p> |
| 476 |
<?php |
| 477 |
/** |
| 478 |
* Fires after the Add Booking date-selection radio controls. |
| 479 |
* |
| 480 |
* @param WPBC_Page_AddNewBooking $page_instance Current Add Booking page object. |
| 481 |
* @param string $days_mode Current normalized mode. |
| 482 |
* @param int $resource_id Current Booking resource ID. |
| 483 |
*/ |
| 484 |
do_action( 'wpbc_admin_add_booking_date_selection_panel', $this, $days_mode, $resource_id ); |
| 485 |
} |
| 486 |
|
| 487 |
|
| 488 |
/** |
| 489 |
* Get the current global calendar mode normalized for the three radio choices. |
| 490 |
* |
| 491 |
* The selected Booking Form may apply its own mode after page initialization; |
| 492 |
* the page JavaScript synchronizes the radios with that effective mode. |
| 493 |
* |
| 494 |
* @return string One of `single`, `multiple`, or `range`. |
| 495 |
*/ |
| 496 |
private function get_current_days_selection_mode() { |
| 497 |
|
| 498 |
$days_selection_mode = function_exists( 'wpbc__calendar__js_params__get_days_selection_arr' ) |
| 499 |
? wpbc__calendar__js_params__get_days_selection_arr() |
| 500 |
: array( 'days_select_mode' => get_bk_option( 'booking_type_of_day_selections' ) ); |
| 501 |
$days_selection_mode = isset( $days_selection_mode['days_select_mode'] ) ? sanitize_key( (string) $days_selection_mode['days_select_mode'] ) : 'multiple'; |
| 502 |
|
| 503 |
if ( in_array( $days_selection_mode, array( 'fixed', 'dynamic', 'range' ), true ) ) { |
| 504 |
return 'range'; |
| 505 |
} |
| 506 |
|
| 507 |
return in_array( $days_selection_mode, array( 'single', 'multiple' ), true ) ? $days_selection_mode : 'multiple'; |
| 508 |
} |
| 509 |
|
| 510 |
|
| 511 |
/** |
| 512 |
* Get the range engine that the page should use when Range days is selected. |
| 513 |
* |
| 514 |
* Business Small and higher retain the configured fixed/dynamic subtype. |
| 515 |
* Free and Personal use their normal unrestricted dynamic range. |
| 516 |
* |
| 517 |
* @return string Either `fixed` or `dynamic`. |
| 518 |
*/ |
| 519 |
private function get_current_range_engine_mode() { |
| 520 |
|
| 521 |
if ( ! class_exists( 'wpdev_bk_biz_s' ) ) { |
| 522 |
return 'dynamic'; |
| 523 |
} |
| 524 |
|
| 525 |
$range_engine_mode = sanitize_key( (string) get_bk_option( 'booking_range_selection_type' ) ); |
| 526 |
|
| 527 |
return in_array( $range_engine_mode, array( 'fixed', 'dynamic' ), true ) ? $range_engine_mode : 'dynamic'; |
| 528 |
} |
| 529 |
|
| 530 |
|
| 531 |
/** |
| 532 |
* Get the translated label for a normalized date-selection mode. |
| 533 |
* |
| 534 |
* @param string $days_mode Normalized date-selection mode. |
| 535 |
* |
| 536 |
* @return string Translated mode label. |
| 537 |
*/ |
| 538 |
private function get_days_selection_mode_label( $days_mode ) { |
| 539 |
|
| 540 |
if ( 'single' === $days_mode ) { |
| 541 |
return __( 'Single day', 'booking' ); |
| 542 |
} |
| 543 |
|
| 544 |
if ( 'range' === $days_mode ) { |
| 545 |
return class_exists( 'wpdev_bk_biz_s' ) ? __( 'Range days', 'booking' ) : __( 'Range days - 2 mouse clicks', 'booking' ); |
| 546 |
} |
| 547 |
|
| 548 |
return __( 'Multiple days', 'booking' ); |
| 549 |
} |
| 550 |
|
| 551 |
/** |
| 552 |
* Get the Booking resource selected for the current Add Booking page. |
| 553 |
* |
| 554 |
* @return int Positive Booking resource ID. |
| 555 |
*/ |
| 556 |
private function get_selected_booking_resource_id() { |
| 557 |
|
| 558 |
if ( isset( $_GET['booking_type'] ) && ! is_array( $_GET['booking_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 559 |
$resource_id = absint( $_GET['booking_type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 560 |
if ( $resource_id > 0 ) { |
| 561 |
return $resource_id; |
| 562 |
} |
| 563 |
} |
| 564 |
|
| 565 |
return 1; |
| 566 |
} |
| 567 |
|
| 568 |
|
| 569 |
/** |
| 570 |
* Get the Booking Form selected explicitly or inherited from the resource. |
| 571 |
* |
| 572 |
* @param int $resource_id Booking resource ID used to resolve its default form. |
| 573 |
* |
| 574 |
* @return string Sanitized Booking Form slug. |
| 575 |
*/ |
| 576 |
private function get_selected_booking_form_name( $resource_id ) { |
| 577 |
|
| 578 |
if ( isset( $_GET['booking_form'] ) && ! is_array( $_GET['booking_form'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 579 |
$form_name = sanitize_text_field( wp_unslash( $_GET['booking_form'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 580 |
if ( '' !== $form_name ) { |
| 581 |
return $form_name; |
| 582 |
} |
| 583 |
} |
| 584 |
|
| 585 |
return WPBC_Add_Booking_Component::get_default_booking_form_for_resource( $resource_id, 'standard' ); |
| 586 |
} |
| 587 |
|
| 588 |
|
| 589 |
/** |
| 590 |
* Check whether the resource selector can be used in the current context. |
| 591 |
* |
| 592 |
* Resource changes remain disabled while editing an existing Booking. |
| 593 |
* |
| 594 |
* @return bool True when the commercial resource selector is available. |
| 595 |
*/ |
| 596 |
private function is_booking_resource_selector_available() { |
| 597 |
|
| 598 |
return empty( $_GET['booking_hash'] ) && class_exists( 'wpdev_bk_personal' ) && function_exists( 'wpbc_toolbar__get_resource_options_for_selection' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 599 |
} |
| 600 |
|
| 601 |
|
| 602 |
/** |
| 603 |
* Check whether the Free-version resource upgrade notice should be shown. |
| 604 |
* |
| 605 |
* The notice replaces the unavailable resource selector only while creating |
| 606 |
* a new Booking. A user may dismiss it without affecting Booking behavior. |
| 607 |
* |
| 608 |
* @return bool True when the upgrade notice should be rendered. |
| 609 |
*/ |
| 610 |
private function is_booking_resource_upgrade_visible() { |
| 611 |
|
| 612 |
if ( class_exists( 'wpdev_bk_personal' ) || ! empty( $_GET['booking_hash'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 613 |
return false; |
| 614 |
} |
| 615 |
|
| 616 |
if ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ) { |
| 617 |
return true; |
| 618 |
} |
| 619 |
|
| 620 |
return ! function_exists( 'wpbc_is_dismissed_panel_visible' ) || wpbc_is_dismissed_panel_visible( 'wpbc_add_booking_resource_upgrade' ); |
| 621 |
} |
| 622 |
|
| 623 |
|
| 624 |
/** |
| 625 |
* Get published Booking Forms visible to the current user. |
| 626 |
* |
| 627 |
* @return array<string,array<string,mixed>> Available custom Booking Forms. |
| 628 |
*/ |
| 629 |
private function get_available_booking_forms() { |
| 630 |
|
| 631 |
if ( null !== $this->available_booking_forms ) { |
| 632 |
return $this->available_booking_forms; |
| 633 |
} |
| 634 |
|
| 635 |
$is_allowed = apply_bk_filter( 'multiuser_is_user_can_be_here', true, 'only_super_admin' ); |
| 636 |
if ( ! $is_allowed && 'On' !== get_bk_option( 'booking_is_custom_forms_for_regular_users' ) ) { |
| 637 |
$this->available_booking_forms = array(); |
| 638 |
return $this->available_booking_forms; |
| 639 |
} |
| 640 |
|
| 641 |
$this->available_booking_forms = WPBC_FE_Custom_Form_Helper::get_custom_booking_forms_list( |
| 642 |
array( |
| 643 |
'include_standard' => false, |
| 644 |
'owner_user_id' => WPBC_FE_Custom_Form_Helper::wpbc_mu__get_current__owner_user_id(), |
| 645 |
'statuses' => array( 'published' ), |
| 646 |
'list_mode' => 'auto', |
| 647 |
) |
| 648 |
); |
| 649 |
|
| 650 |
if ( ! is_array( $this->available_booking_forms ) ) { |
| 651 |
$this->available_booking_forms = array(); |
| 652 |
} |
| 653 |
|
| 654 |
return $this->available_booking_forms; |
| 655 |
} |
| 656 |
|
| 657 |
|
| 658 |
/** |
| 659 |
* Render the commercial Booking resource selector as a native inspector row. |
| 660 |
* |
| 661 |
* The legacy resource option provider remains the source of truth for parent, |
| 662 |
* child, MultiUser, and edition-specific resource visibility. Only its toolbar |
| 663 |
* HTML renderer is bypassed on this page. |
| 664 |
* |
| 665 |
* @return bool True when a resource selector was rendered. |
| 666 |
*/ |
| 667 |
private function render_booking_resource_control() { |
| 668 |
|
| 669 |
if ( $this->is_booking_resource_upgrade_visible() ) { |
| 670 |
return $this->render_booking_resource_upgrade_control(); |
| 671 |
} |
| 672 |
|
| 673 |
// A resource cannot be switched while editing an existing Booking. |
| 674 |
if ( ! $this->is_booking_resource_selector_available() ) { |
| 675 |
return false; |
| 676 |
} |
| 677 |
|
| 678 |
$resource_options = wpbc_toolbar__get_resource_options_for_selection(); |
| 679 |
if ( empty( $resource_options ) || ! is_array( $resource_options ) ) { |
| 680 |
return false; |
| 681 |
} |
| 682 |
|
| 683 |
$link_base = wpbc_get_new_booking_url__base( array( 'booking_type', 'booking_form', 'parent_res' ) ) . '&booking_type='; |
| 684 |
|
| 685 |
$this->render_inspector_select_row( |
| 686 |
array( |
| 687 |
'id' => 'select_booking_resource', |
| 688 |
'name' => 'select_booking_resource', |
| 689 |
'label' => __( 'Booking resource', 'booking' ), |
| 690 |
'options' => $resource_options, |
| 691 |
'on_change' => 'window.location.href = ' . wp_json_encode( $link_base ) . ' + this.value;', |
| 692 |
) |
| 693 |
); |
| 694 |
|
| 695 |
return true; |
| 696 |
} |
| 697 |
|
| 698 |
|
| 699 |
/** |
| 700 |
* Render the Free-version resource explanation in place of the selector. |
| 701 |
* |
| 702 |
* @return bool True after the inspector control has been rendered. |
| 703 |
*/ |
| 704 |
private function render_booking_resource_upgrade_control() { |
| 705 |
|
| 706 |
$dismiss_id = 'wpbc_add_booking_resource_upgrade'; |
| 707 |
$is_demo = function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo(); |
| 708 |
?> |
| 709 |
<div class="inspector__row wpbc_add_booking__resource_upgrade_row" id="<?php echo esc_attr( $dismiss_id ); ?>"> |
| 710 |
<span class="inspector__label"><?php esc_html_e( 'Booking resource', 'booking' ); ?></span> |
| 711 |
<div class="inspector__control" id="select_booking_resource" tabindex="-1"> |
| 712 |
<div class="wpbc_add_booking__resource_upgrade_hint"> |
| 713 |
<a class="wpbc_pro_label" href="<?php echo esc_url( 'https://wpbookingcalendar.com/features/' ); ?>" target="_blank" rel="noopener noreferrer">Pro</a> |
| 714 |
<?php if ( ! $is_demo && function_exists( 'wpbc_is_dismissed' ) ) : ?> |
| 715 |
<span class="wpbc_add_booking__premium_dismiss"> |
| 716 |
<?php |
| 717 |
wpbc_is_dismissed( |
| 718 |
$dismiss_id, |
| 719 |
array( |
| 720 |
'title' => '×', |
| 721 |
'hint' => __( 'Hide this option', 'booking' ), |
| 722 |
'css' => 'float:none;', |
| 723 |
) |
| 724 |
); |
| 725 |
?> |
| 726 |
</span> |
| 727 |
<?php endif; ?> |
| 728 |
<span class="wpbc_add_booking__resource_upgrade_description"><?php esc_html_e( 'The Free version has one default booking resource. To have multiple resources, please upgrade to a premium version.', 'booking' ); ?></span> |
| 729 |
</div> |
| 730 |
</div> |
| 731 |
</div> |
| 732 |
<?php |
| 733 |
|
| 734 |
return true; |
| 735 |
} |
| 736 |
|
| 737 |
|
| 738 |
/** |
| 739 |
* Render the available Booking Forms as a native inspector row. |
| 740 |
* |
| 741 |
* This follows the same MultiUser access rule and resource-default selection |
| 742 |
* used by the legacy toolbar selector without mutating request data. |
| 743 |
* |
| 744 |
* @return bool True when a Booking Form selector was rendered. |
| 745 |
*/ |
| 746 |
private function render_booking_form_control() { |
| 747 |
|
| 748 |
$booking_forms = $this->get_available_booking_forms(); |
| 749 |
|
| 750 |
if ( empty( $booking_forms ) || ! is_array( $booking_forms ) ) { |
| 751 |
return false; |
| 752 |
} |
| 753 |
|
| 754 |
$resource_id = $this->get_selected_booking_resource_id(); |
| 755 |
$form_name = $this->get_selected_booking_form_name( $resource_id ); |
| 756 |
|
| 757 |
$form_options = array( |
| 758 |
'standard' => array( |
| 759 |
'title' => __( 'Standard', 'booking' ), |
| 760 |
'selected' => 'standard' === $form_name, |
| 761 |
), |
| 762 |
'custom_forms_open' => array( |
| 763 |
'optgroup' => true, |
| 764 |
'close' => false, |
| 765 |
'title' => __( 'Custom Forms', 'booking' ), |
| 766 |
), |
| 767 |
); |
| 768 |
|
| 769 |
foreach ( $booking_forms as $booking_form ) { |
| 770 |
$booking_form_name = isset( $booking_form['name'] ) ? sanitize_text_field( (string) $booking_form['name'] ) : ''; |
| 771 |
if ( '' === $booking_form_name ) { |
| 772 |
continue; |
| 773 |
} |
| 774 |
|
| 775 |
$form_options[ $booking_form_name ] = array( |
| 776 |
'title' => wpbc_lang( $booking_form_name ), |
| 777 |
'selected' => $booking_form_name === $form_name, |
| 778 |
); |
| 779 |
} |
| 780 |
|
| 781 |
$form_options['custom_forms_close'] = array( |
| 782 |
'optgroup' => true, |
| 783 |
'close' => true, |
| 784 |
); |
| 785 |
|
| 786 |
$link_base = wpbc_get_new_booking_url__base( array( 'booking_form' ) ) . '&booking_form='; |
| 787 |
|
| 788 |
$this->render_inspector_select_row( |
| 789 |
array( |
| 790 |
'id' => 'select_booking_form', |
| 791 |
'name' => 'select_booking_form', |
| 792 |
'label' => __( 'Booking Form', 'booking' ), |
| 793 |
'options' => $form_options, |
| 794 |
'on_change' => 'window.location.href = ' . wp_json_encode( $link_base ) . ' + this.value;', |
| 795 |
'after' => function () use ( $form_name ) { |
| 796 |
$this->render_booking_form_edit_link( $form_name ); |
| 797 |
}, |
| 798 |
) |
| 799 |
); |
| 800 |
|
| 801 |
return true; |
| 802 |
} |
| 803 |
|
| 804 |
|
| 805 |
/** |
| 806 |
* Render a Forms Builder link for the currently selected Booking Form. |
| 807 |
* |
| 808 |
* @param string $form_name Sanitized Booking Form slug. |
| 809 |
* |
| 810 |
* @return void |
| 811 |
*/ |
| 812 |
private function render_booking_form_edit_link( $form_name ) { |
| 813 |
|
| 814 |
if ( ! function_exists( 'wpbc_get_settings_url' ) ) { |
| 815 |
return; |
| 816 |
} |
| 817 |
|
| 818 |
$base_url = add_query_arg( 'tab', 'builder_booking_form', wpbc_get_settings_url() ); |
| 819 |
$edit_url = add_query_arg( 'form_name', $form_name, $base_url ); |
| 820 |
?> |
| 821 |
<a href="<?php echo esc_url( $edit_url ); ?>" |
| 822 |
class="wpbc_modal__add_booking__edit_form_link wpbc_add_booking__edit_form_link" |
| 823 |
data-wpbc-add-booking-form-builder-url="<?php echo esc_url( $base_url ); ?>" |
| 824 |
target="_blank" |
| 825 |
rel="noopener noreferrer" |
| 826 |
title="<?php esc_attr_e( 'Edit selected booking form', 'booking' ); ?>"> |
| 827 |
<i class="menu_icon icon-1x wpbc_icn_draw" aria-hidden="true"></i> |
| 828 |
<span><?php esc_html_e( 'Edit form', 'booking' ); ?></span> |
| 829 |
</a> |
| 830 |
<?php |
| 831 |
} |
| 832 |
|
| 833 |
|
| 834 |
/** |
| 835 |
* Render one select field using the shared Builder-style inspector markup. |
| 836 |
* |
| 837 |
* Option arrays may contain the Booking Calendar toolbar option keys |
| 838 |
* `title`, `class`, `disabled`, `selected`, and `optgroup`. |
| 839 |
* An optional `after` callback renders related controls beneath the select. |
| 840 |
* |
| 841 |
* @param array $args Select field arguments. |
| 842 |
* |
| 843 |
* @return void |
| 844 |
*/ |
| 845 |
private function render_inspector_select_row( $args ) { |
| 846 |
|
| 847 |
$args = wp_parse_args( |
| 848 |
$args, |
| 849 |
array( |
| 850 |
'id' => '', |
| 851 |
'name' => '', |
| 852 |
'label' => '', |
| 853 |
'options' => array(), |
| 854 |
'value' => null, |
| 855 |
'on_change' => '', |
| 856 |
'after' => null, |
| 857 |
) |
| 858 |
); |
| 859 |
?> |
| 860 |
<div class="inspector__row"> |
| 861 |
<label for="<?php echo esc_attr( $args['id'] ); ?>" class="inspector__label"><?php echo esc_html( $args['label'] ); ?></label> |
| 862 |
<div class="inspector__control"> |
| 863 |
<select id="<?php echo esc_attr( $args['id'] ); ?>" |
| 864 |
name="<?php echo esc_attr( $args['name'] ); ?>" |
| 865 |
class="inspector__input" |
| 866 |
<?php echo '' !== $args['on_change'] ? 'onchange="' . esc_attr( $args['on_change'] ) . '"' : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> |
| 867 |
autocomplete="off"> |
| 868 |
<?php $this->render_inspector_select_options( $args['options'], $args['value'] ); ?> |
| 869 |
</select> |
| 870 |
<?php |
| 871 |
if ( is_callable( $args['after'] ) ) { |
| 872 |
call_user_func( $args['after'] ); |
| 873 |
} |
| 874 |
?> |
| 875 |
</div> |
| 876 |
</div> |
| 877 |
<?php |
| 878 |
} |
| 879 |
|
| 880 |
|
| 881 |
/** |
| 882 |
* Render select options and optgroups from Booking Calendar option arrays. |
| 883 |
* |
| 884 |
* @param array $options Option definitions keyed by submitted value. |
| 885 |
* @param string|int|null $selected_value Explicit selected value, or null to use each option's selected flag. |
| 886 |
* |
| 887 |
* @return void |
| 888 |
*/ |
| 889 |
private function render_inspector_select_options( $options, $selected_value = null ) { |
| 890 |
|
| 891 |
foreach ( (array) $options as $option_value => $option_definition ) { |
| 892 |
$option_definition = is_array( $option_definition ) ? $option_definition : array( 'title' => $option_definition ); |
| 893 |
|
| 894 |
if ( ! empty( $option_definition['optgroup'] ) ) { |
| 895 |
if ( ! empty( $option_definition['close'] ) ) { |
| 896 |
?></optgroup><?php |
| 897 |
} else { |
| 898 |
?><optgroup label="<?php echo esc_attr( isset( $option_definition['title'] ) ? $option_definition['title'] : '' ); ?>"><?php |
| 899 |
} |
| 900 |
continue; |
| 901 |
} |
| 902 |
|
| 903 |
$option_title = isset( $option_definition['title'] ) ? wp_strip_all_tags( html_entity_decode( (string) $option_definition['title'], ENT_QUOTES, get_bloginfo( 'charset' ) ) ) : ''; |
| 904 |
$is_selected = null === $selected_value ? ! empty( $option_definition['selected'] ) : (string) $selected_value === (string) $option_value; |
| 905 |
?> |
| 906 |
<option value="<?php echo esc_attr( $option_value ); ?>" |
| 907 |
class="<?php echo esc_attr( isset( $option_definition['class'] ) ? $option_definition['class'] : '' ); ?>" |
| 908 |
<?php selected( $is_selected ); ?> |
| 909 |
<?php disabled( ! empty( $option_definition['disabled'] ) ); ?>><?php echo esc_html( $option_title ); ?></option> |
| 910 |
<?php |
| 911 |
} |
| 912 |
} |
| 913 |
|
| 914 |
|
| 915 |
/** |
| 916 |
* Render email and past-date controls. |
| 917 |
* |
| 918 |
* @return void |
| 919 |
*/ |
| 920 |
public function render_booking_tools_controls() { |
| 921 |
|
| 922 |
$allow_past = isset( $_GET['allow_past'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 923 |
$allow_past_url = esc_url_raw( wpbc_add_booking_page_get_allow_past_url( true ) ); |
| 924 |
$normal_url = esc_url_raw( wpbc_add_booking_page_get_allow_past_url( false ) ); |
| 925 |
$send_emails = 'On' !== get_bk_option( 'booking_send_emails_off_addbooking' ); |
| 926 |
?> |
| 927 |
<?php |
| 928 |
wpbc_render_admin_cost_correction_control( |
| 929 |
array( |
| 930 |
'input_id' => 'wpbc_add_booking_cost_correction', |
| 931 |
'resource_id' => $this->get_selected_booking_resource_id(), |
| 932 |
'wrapper_class' => 'inspector__row wpbc_add_booking__cost_correction', |
| 933 |
'label_class' => 'inspector__label', |
| 934 |
'control_class' => 'inspector__control', |
| 935 |
'help_class' => 'description wpbc_bfb__help', |
| 936 |
'help' => __( 'Leave the number empty to use the calculated Booking cost. Enter an exact total to replace the final cost for this Booking.', 'booking' ), |
| 937 |
) |
| 938 |
); |
| 939 |
?> |
| 940 |
<div class="inspector__row inspector__row--toggle"> |
| 941 |
<div class="inspector__control"> |
| 942 |
<?php |
| 943 |
wpbc_flex_toggle( |
| 944 |
array( |
| 945 |
'id' => 'is_send_email_for_pending', |
| 946 |
'name' => 'is_send_email_for_pending', |
| 947 |
'label' => array( 'title' => __( 'Emails sending', 'booking' ) ), |
| 948 |
'value' => 'On', |
| 949 |
'selected' => $send_emails, |
| 950 |
'legend' => __( 'Send email notifications for this Booking', 'booking' ), |
| 951 |
) |
| 952 |
); |
| 953 |
?> |
| 954 |
<p class="inspector__help"><?php esc_html_e( 'Send the normal Booking Calendar notifications when this Booking is created.', 'booking' ); ?></p> |
| 955 |
</div> |
| 956 |
</div> |
| 957 |
<div class="inspector__row inspector__row--toggle"> |
| 958 |
<div class="inspector__control"> |
| 959 |
<?php |
| 960 |
wpbc_flex_toggle( |
| 961 |
array( |
| 962 |
'id' => 'is_allow_bookings_in_past', |
| 963 |
'name' => 'is_allow_bookings_in_past', |
| 964 |
'label' => array( 'title' => __( 'Allow booking in the past', 'booking' ) ), |
| 965 |
'value' => 'On', |
| 966 |
'selected' => $allow_past, |
| 967 |
'legend' => __( 'Allow booking in the past', 'booking' ), |
| 968 |
'onchange' => 'window.location.href = this.checked ? ' . wp_json_encode( $allow_past_url ) . ' : ' . wp_json_encode( $normal_url ) . ';', |
| 969 |
) |
| 970 |
); |
| 971 |
?> |
| 972 |
<p class="inspector__help"><?php esc_html_e( 'Use this only for historical or manually entered Bookings.', 'booking' ); ?></p> |
| 973 |
</div> |
| 974 |
</div> |
| 975 |
<?php do_action( 'wpbc_admin_add_booking_tools_panel', $this ); ?> |
| 976 |
<?php |
| 977 |
} |
| 978 |
|
| 979 |
/** |
| 980 |
* Render per-user calendar sizing controls and their existing AJAX actions. |
| 981 |
* |
| 982 |
* @return void |
| 983 |
*/ |
| 984 |
public function render_calendar_view_controls() { |
| 985 |
|
| 986 |
$user_calendar_options = $this->get_saved_user_calendar_settings(); |
| 987 |
$month_options = array_combine( range( 1, 12 ), range( 1, 12 ) ); |
| 988 |
$months_per_row = array( 0 => __( 'All', 'booking' ) ) + $month_options; |
| 989 |
|
| 990 |
$this->render_inspector_select_row( |
| 991 |
array( |
| 992 |
'id' => 'calendar_months_count', |
| 993 |
'name' => 'calendar_months_count', |
| 994 |
'label' => __( 'Visible months', 'booking' ), |
| 995 |
'options' => $month_options, |
| 996 |
'value' => isset( $user_calendar_options['calendar_months_count'] ) ? absint( $user_calendar_options['calendar_months_count'] ) : 1, |
| 997 |
) |
| 998 |
); |
| 999 |
$this->render_inspector_select_row( |
| 1000 |
array( |
| 1001 |
'id' => 'calendar_months_num_in_1_row', |
| 1002 |
'name' => 'calendar_months_num_in_1_row', |
| 1003 |
'label' => __( 'Number of months in one row', 'booking' ), |
| 1004 |
'options' => $months_per_row, |
| 1005 |
'value' => isset( $user_calendar_options['calendar_months_num_in_1_row'] ) ? absint( $user_calendar_options['calendar_months_num_in_1_row'] ) : 0, |
| 1006 |
) |
| 1007 |
); |
| 1008 |
|
| 1009 |
$this->render_inspector_measurement_row( |
| 1010 |
'calendar_width', |
| 1011 |
__( 'Maximum width of calendar', 'booking' ), |
| 1012 |
isset( $user_calendar_options['calendar_width'] ) ? $user_calendar_options['calendar_width'] : '', |
| 1013 |
isset( $user_calendar_options['calendar_widthunits'] ) ? $user_calendar_options['calendar_widthunits'] : 'px', |
| 1014 |
'100%' |
| 1015 |
); |
| 1016 |
$this->render_inspector_measurement_row( |
| 1017 |
'calendar_cell_height', |
| 1018 |
__( 'Calendar cell height', 'booking' ), |
| 1019 |
isset( $user_calendar_options['calendar_cell_height'] ) ? $user_calendar_options['calendar_cell_height'] : '', |
| 1020 |
isset( $user_calendar_options['calendar_cell_heightunits'] ) ? $user_calendar_options['calendar_cell_heightunits'] : 'px', |
| 1021 |
'48px' |
| 1022 |
); |
| 1023 |
?> |
| 1024 |
<div class="wpbc_add_booking__panel_actions"> |
| 1025 |
<button type="button" |
| 1026 |
id="toolbar_btn__calendar_options_save" |
| 1027 |
class="button button-primary" |
| 1028 |
onclick="var wpbc_calendar_options = { calendar_months_count: jQuery( '#calendar_months_count' ).val(), calendar_months_num_in_1_row: jQuery( '#calendar_months_num_in_1_row' ).val(), calendar_width: jQuery( '#calendar_width' ).val(), calendar_widthunits: jQuery( '#calendar_widthunits' ).val(), calendar_cell_height: jQuery( '#calendar_cell_height' ).val(), calendar_cell_heightunits: jQuery( '#calendar_cell_heightunits' ).val() }; wpbc_save_custom_user_data( <?php echo absint( wpbc_get_current_user_id() ); ?>, 'add_booking_calendar_options', jQuery.param( wpbc_calendar_options ), 1 );"><?php esc_html_e( 'Save', 'booking' ); ?></button> |
| 1029 |
<button type="button" |
| 1030 |
class="button button-secondary" |
| 1031 |
onclick="jQuery( '#calendar_months_count' ).val( '1' ); jQuery( '#calendar_months_num_in_1_row' ).val( '0' ); jQuery( '#calendar_width' ).val( '0' ); jQuery( '#calendar_widthunits' ).val( 'px' ); jQuery( '#calendar_cell_height' ).val( '0' ); jQuery( '#calendar_cell_heightunits' ).val( 'px' ); jQuery( '#toolbar_btn__calendar_options_save' ).trigger( 'click' );"><?php esc_html_e( 'Reset', 'booking' ); ?></button> |
| 1032 |
</div> |
| 1033 |
<?php do_action( 'wpbc_admin_add_booking_calendar_view_panel', $this, $user_calendar_options ); ?> |
| 1034 |
<?php |
| 1035 |
} |
| 1036 |
|
| 1037 |
|
| 1038 |
/** |
| 1039 |
* Render a numeric calendar measurement and its unit selector. |
| 1040 |
* |
| 1041 |
* @param string $field_id Base HTML id and name. |
| 1042 |
* @param string $label Visible field label. |
| 1043 |
* @param string|int $value Saved numeric value. |
| 1044 |
* @param string $unit Saved unit: `px` or `percent`. |
| 1045 |
* @param string $placeholder Example value shown when empty. |
| 1046 |
* |
| 1047 |
* @return void |
| 1048 |
*/ |
| 1049 |
private function render_inspector_measurement_row( $field_id, $label, $value, $unit, $placeholder ) { |
| 1050 |
|
| 1051 |
$unit = in_array( $unit, array( 'px', 'percent' ), true ) ? $unit : 'px'; |
| 1052 |
?> |
| 1053 |
<div class="inspector__row"> |
| 1054 |
<label for="<?php echo esc_attr( $field_id ); ?>" class="inspector__label"><?php echo esc_html( $label ); ?></label> |
| 1055 |
<div class="inspector__control inspector__control--inline"> |
| 1056 |
<input id="<?php echo esc_attr( $field_id ); ?>" name="<?php echo esc_attr( $field_id ); ?>" type="number" min="0" step="1" value="<?php echo esc_attr( $value ); ?>" placeholder="<?php echo esc_attr( $placeholder ); ?>" class="inspector__input"> |
| 1057 |
<select id="<?php echo esc_attr( $field_id . 'units' ); ?>" name="<?php echo esc_attr( $field_id . 'units' ); ?>" class="inspector__input inspector__input--unit" autocomplete="off"> |
| 1058 |
<option value="px" <?php selected( 'px', $unit ); ?>>px</option> |
| 1059 |
<option value="percent" <?php selected( 'percent', $unit ); ?>>%</option> |
| 1060 |
</select> |
| 1061 |
</div> |
| 1062 |
</div> |
| 1063 |
<?php |
| 1064 |
} |
| 1065 |
|
| 1066 |
|
| 1067 |
/** |
| 1068 |
* Render contextual help in place of the legacy toolbar Help dropdown. |
| 1069 |
* |
| 1070 |
* @return void |
| 1071 |
*/ |
| 1072 |
public function render_help_panel() { |
| 1073 |
|
| 1074 |
WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Add Booking Help', 'booking' ), __( 'Create a Booking directly from the WordPress Admin Panel.', 'booking' ) ); |
| 1075 |
?> |
| 1076 |
<div class="wpbc_bfb__inspector__body wpbc_bfb__inspector__body--content wpbc_add_booking__help_body"> |
| 1077 |
<div class="wpbc_add_booking__hint"> |
| 1078 |
<span class="wpbc_icn_info_outline" aria-hidden="true"></span> |
| 1079 |
<p><?php esc_html_e( 'Choose the Booking resource and form first. Changing either selector reloads this page so every field and calendar keeps the correct resource ID.', 'booking' ); ?></p> |
| 1080 |
</div> |
| 1081 |
<div class="wpbc_add_booking__help_section"> |
| 1082 |
<h4><?php esc_html_e( 'Recommended workflow', 'booking' ); ?></h4> |
| 1083 |
<ol> |
| 1084 |
<li><?php esc_html_e( 'Select the Booking resource and Booking Form.', 'booking' ); ?></li> |
| 1085 |
<li><?php esc_html_e( 'Choose an available date or time and complete the customer fields.', 'booking' ); ?></li> |
| 1086 |
<li><?php esc_html_e( 'Review email sending, then click Add booking.', 'booking' ); ?></li> |
| 1087 |
</ol> |
| 1088 |
</div> |
| 1089 |
<div class="wpbc_add_booking__help_actions"> |
| 1090 |
<a class="button" href="https://wpbookingcalendar.com/faq/" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'FAQ', 'booking' ); ?></a> |
| 1091 |
<a class="button" href="https://wpbookingcalendar.com/support/" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Support', 'booking' ); ?></a> |
| 1092 |
</div> |
| 1093 |
<?php do_action( 'wpbc_admin_add_booking_help_panel', $this ); ?> |
| 1094 |
</div> |
| 1095 |
<?php |
| 1096 |
} |
| 1097 |
|
| 1098 |
|
| 1099 |
/** |
| 1100 |
* Render the legacy page or the released inspector presentation. |
| 1101 |
* |
| 1102 |
* Both presentations delegate the actual Booking Form to the same reusable |
| 1103 |
* component, so calendar and submission behavior cannot diverge. |
| 1104 |
* |
| 1105 |
* @return void|false False when the current user cannot use the page. |
| 1106 |
*/ |
| 1107 |
public function content() { |
| 1108 |
|
| 1109 |
do_action( 'wpbc_hook_add_booking_page_header', 'add_booking' ); // Define Notices Section and show some static messages, if needed. |
| 1110 |
|
| 1111 |
if ( ! wpbc_is_mu_user_can_be_here( 'activated_user' ) ) { |
| 1112 |
return false; // Check if MU user activated, otherwise show Warning message. |
| 1113 |
} |
| 1114 |
|
| 1115 |
if ( ! WPBC_Add_Booking_Component::current_user_can_add_booking() ) { |
| 1116 |
return false; |
| 1117 |
} |
| 1118 |
|
| 1119 |
if ( ! wpbc_set_default_resource_to__get() ) { |
| 1120 |
return false; // Define default booking resources for $_ GET and check if booking resource belong to user. |
| 1121 |
} |
| 1122 |
|
| 1123 |
if ( wpbc_add_booking_page_is_inspector_enabled() ) { |
| 1124 |
?> |
| 1125 |
<div class="wpbc_add_booking_page" data-wpbc-add-booking-page="1"> |
| 1126 |
<div class="wpbc_add_booking__canvas"> |
| 1127 |
<?php |
| 1128 |
WPBC_Add_Booking_Component::render( |
| 1129 |
array( |
| 1130 |
'is_toolbar_visible' => false, |
| 1131 |
'is_show_before_content_spacer' => false, |
| 1132 |
'is_show_footer_email_toggle' => false, |
| 1133 |
'content_css_class' => 'add_booking_page_content wpbc_add_booking__form_content', |
| 1134 |
'content_style' => '', |
| 1135 |
) |
| 1136 |
); |
| 1137 |
?> |
| 1138 |
</div> |
| 1139 |
</div> |
| 1140 |
<?php |
| 1141 |
} else { |
| 1142 |
WPBC_Add_Booking_Component::render(); |
| 1143 |
} |
| 1144 |
|
| 1145 |
do_action( 'wpbc_hook_add_booking_page_footer', 'add_booking' ); |
| 1146 |
} |
| 1147 |
|
| 1148 |
|
| 1149 |
/** |
| 1150 |
* Get Calendar Options of specific User |
| 1151 |
* |
| 1152 |
* @return array<string,mixed> Normalized calendar display options. |
| 1153 |
*/ |
| 1154 |
public function get_saved_user_calendar_options() { |
| 1155 |
|
| 1156 |
return WPBC_Add_Booking_Component::get_saved_user_calendar_options(); |
| 1157 |
} |
| 1158 |
|
| 1159 |
|
| 1160 |
/** |
| 1161 |
* Get raw saved calendar fields used by the Add Booking inspector. |
| 1162 |
* |
| 1163 |
* @return array<string,mixed> Raw per-user calendar settings. |
| 1164 |
*/ |
| 1165 |
private function get_saved_user_calendar_settings() { |
| 1166 |
|
| 1167 |
return WPBC_Add_Booking_Component::get_saved_user_calendar_settings(); |
| 1168 |
} |
| 1169 |
|
| 1170 |
} |
| 1171 |
add_action('wpbc_menu_created', array( new WPBC_Page_AddNewBooking() , '__construct') ); // Executed after creation of Menu |
| 1172 |
|
| 1173 |
/** |
| 1174 |
* Redirect legacy/main-menu Add Booking page to the Add Booking tab under Bookings. |
| 1175 |
* |
| 1176 |
* @param string $page_tag Current menu page tag. |
| 1177 |
* |
| 1178 |
* @return void |
| 1179 |
*/ |
| 1180 |
function wpbc_add_booking_menu_page__redirect_to_add_booking_tab( $page_tag ) { |
| 1181 |
|
| 1182 |
if ( 'wpbc-new' !== $page_tag ) { |
| 1183 |
return; |
| 1184 |
} |
| 1185 |
|
| 1186 |
wpbc_redirect( wpbc_get_new_booking_url() ); |
| 1187 |
} |
| 1188 |
add_action( 'wpbc_page_structure_show', 'wpbc_add_booking_menu_page__redirect_to_add_booking_tab', 0 ); |
| 1189 |
|