← All changes
|
includes/page-add-booking/add_booking__component.php
+141
-31
11.1
→
11.9
View file →
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | <?php /** |
| 2 | 2 | * @version 1.0 |
| 3 | 3 | * @package Booking Calendar |
| 4 | 4 | * @category Reusable Add Booking component |
| @@ -18,9 +18,9 @@ | ||
| 18 | 18 | * Check if current user can access the Add Booking workflow. |
| 19 | 19 | * |
| 20 | 20 | * @return bool |
| 21 | 21 | */ |
| 22 | - public static function current_user_can_add_booking() { | |
| 22 | + public static function current_user_can_add_booking() { | |
| 23 | 23 | |
| 24 | 24 | $user_role = get_bk_option( 'booking_user_role_addbooking' ); |
| 25 | 25 | $cap = 'read'; |
| 26 | 26 | |
| @@ -29,10 +29,35 @@ | ||
| 29 | 29 | } elseif ( class_exists( 'WPBC_Admin_Menus' ) && isset( WPBC_Admin_Menus::$capability['subscriber'] ) ) { |
| 30 | 30 | $cap = WPBC_Admin_Menus::$capability['subscriber']; |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | - return current_user_can( $cap ); | |
| 34 | - } | |
| 33 | + return current_user_can( $cap ); | |
| 34 | + } | |
| 35 | + | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * Create the administrator booking nonce for an authorized page context. | |
| 39 | + * | |
| 40 | + * The public booking endpoint accepts signed-out requests, so administrator | |
| 41 | + * behavior must be enabled by a user-bound nonce and the same capability and | |
| 42 | + * MultiUser checks that the server repeats during booking creation. | |
| 43 | + * | |
| 44 | + * @return string Administrator booking nonce, or an empty string when the | |
| 45 | + * current user cannot use the administrator booking workflow. | |
| 46 | + */ | |
| 47 | + public static function get_admin_booking_nonce() { | |
| 48 | + | |
| 49 | + if ( | |
| 50 | + ! is_user_logged_in() | |
| 51 | + || ! self::current_user_can_add_booking() | |
| 52 | + || ! function_exists( 'wpbc_is_mu_user_can_be_here' ) | |
| 53 | + || ! wpbc_is_mu_user_can_be_here( 'activated_user' ) | |
| 54 | + ) { | |
| 55 | + return ''; | |
| 56 | + } | |
| 57 | + | |
| 58 | + return wp_create_nonce( 'wpbc_admin_booking_create' ); | |
| 59 | + } | |
| 35 | 60 | |
| 36 | 61 | /** |
| 37 | 62 | * Render the component and echo by default. |
| 38 | 63 | * |
| @@ -134,8 +159,9 @@ | ||
| 134 | 159 | 'calendar_dates_start' => '', |
| 135 | 160 | 'calendar_dates_end' => '', |
| 136 | 161 | 'booking_hash' => '', |
| 137 | 162 | 'allow_past' => null, |
| 163 | + 'selected_dates' => '', | |
| 138 | 164 | 'selected_date' => '', |
| 139 | 165 | 'selected_time' => '', |
| 140 | 166 | 'time_override_enabled' => 0, |
| 141 | 167 | 'time_override_source' => '', |
| @@ -157,9 +183,9 @@ | ||
| 157 | 183 | $args['_is_explicit_booking_form'] = ( ( null !== $args['custom_booking_form'] ) && ( '' !== (string) $args['custom_booking_form'] ) ) |
| 158 | 184 | || ( ( null !== $args['booking_form'] ) && ( '' !== (string) $args['booking_form'] ) ); |
| 159 | 185 | |
| 160 | 186 | $resource_id = self::get_explicit_or_get_resource_id( $args ); |
| 161 | - $form_name = self::get_explicit_or_get_booking_form( $args ); | |
| 187 | + $form_name = self::get_explicit_or_get_booking_form( $args, $resource_id ); | |
| 162 | 188 | |
| 163 | 189 | $calendar_params = self::get_calendar_params( $args ); |
| 164 | 190 | |
| 165 | 191 | $args['resource_id'] = $resource_id; |
| @@ -171,8 +197,9 @@ | ||
| 171 | 197 | $args['calendar_dates_start'] = (string) $args['calendar_dates_start']; |
| 172 | 198 | $args['calendar_dates_end'] = (string) $args['calendar_dates_end']; |
| 173 | 199 | $args['booking_hash'] = ( '' !== (string) $args['booking_hash'] ) ? sanitize_text_field( wp_unslash( (string) $args['booking_hash'] ) ) : ( isset( $_GET['booking_hash'] ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 174 | 200 | $args['allow_past'] = ( null !== $args['allow_past'] ) ? ( ! empty( $args['allow_past'] ) ? 1 : 0 ) : ( isset( $_GET['allow_past'] ) ? 1 : 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 201 | + $args['selected_dates'] = sanitize_text_field( wp_unslash( (string) $args['selected_dates'] ) ); | |
| 175 | 202 | $args['selected_date'] = sanitize_text_field( wp_unslash( (string) $args['selected_date'] ) ); |
| 176 | 203 | $args['selected_time'] = sanitize_text_field( wp_unslash( (string) $args['selected_time'] ) ); |
| 177 | 204 | $args['time_override_enabled'] = ! empty( $args['time_override_enabled'] ) ? 1 : 0; |
| 178 | 205 | $args['time_override_source'] = sanitize_key( wp_unslash( (string) $args['time_override_source'] ) ); |
| @@ -189,15 +216,17 @@ | ||
| 189 | 216 | * @param array $args Component options. |
| 190 | 217 | * |
| 191 | 218 | * @return void |
| 192 | 219 | */ |
| 193 | - private static function print_context_js( $args ) { | |
| 194 | - | |
| 195 | - $booking_hash = isset( $args['booking_hash'] ) ? (string) $args['booking_hash'] : ''; | |
| 196 | - $allow_past_date_arr = self::get_allow_past_min_date_arr( $args ); | |
| 197 | - $context = array( | |
| 198 | - 'resource_id' => absint( $args['resource_id'] ), | |
| 220 | + private static function print_context_js( $args ) { | |
| 221 | + | |
| 222 | + $booking_hash = isset( $args['booking_hash'] ) ? (string) $args['booking_hash'] : ''; | |
| 223 | + $admin_booking_nonce = self::get_admin_booking_nonce(); | |
| 224 | + $allow_past_date_arr = self::get_allow_past_min_date_arr( $args ); | |
| 225 | + $context = array( | |
| 226 | + 'resource_id' => absint( $args['resource_id'] ), | |
| 199 | 227 | 'selected_dates_without_calendar' => (string) $args['selected_dates_without_calendar'], |
| 228 | + 'selected_dates' => (string) $args['selected_dates'], | |
| 200 | 229 | 'selected_date' => (string) $args['selected_date'], |
| 201 | 230 | 'selected_time' => (string) $args['selected_time'], |
| 202 | 231 | 'time_override_enabled' => absint( $args['time_override_enabled'] ), |
| 203 | 232 | 'time_override_source' => (string) $args['time_override_source'], |
| @@ -202,19 +231,44 @@ | ||
| 202 | 231 | 'time_override_enabled' => absint( $args['time_override_enabled'] ), |
| 203 | 232 | 'time_override_source' => (string) $args['time_override_source'], |
| 204 | 233 | 'time_override_start' => (string) $args['time_override_start'], |
| 205 | 234 | 'time_override_end' => (string) $args['time_override_end'], |
| 206 | - 'allow_past' => ! empty( $args['allow_past'] ) ? 1 : 0, | |
| 207 | - ); | |
| 208 | - ?> | |
| 209 | - <script type="text/javascript"> | |
| 210 | - window.wpbc_add_booking_component_context = <?php echo wp_json_encode( $context ); ?>; | |
| 211 | - if ( 'undefined' !== typeof _wpbc ) { | |
| 212 | - _wpbc.set_other_param( 'this_page_booking_hash', <?php echo wp_json_encode( $booking_hash ); ?> ); | |
| 213 | - _wpbc.set_other_param( 'this_page_allow_past', <?php echo wp_json_encode( ! empty( $args['allow_past'] ) ? 1 : 0 ); ?> ); | |
| 214 | - _wpbc.set_other_param( 'this_page_allow_past_arr', <?php echo wp_json_encode( $allow_past_date_arr ); ?> ); | |
| 215 | - } | |
| 216 | - </script> | |
| 235 | + 'allow_past' => ! empty( $args['allow_past'] ) ? 1 : 0, | |
| 236 | + ); | |
| 237 | + $booking_context_js = "_wpbc.set_other_param( 'this_page_booking_hash', " . wp_json_encode( $booking_hash ) . ' );'; | |
| 238 | + $booking_context_js .= "_wpbc.set_other_param( 'this_page_allow_past', " . wp_json_encode( ! empty( $args['allow_past'] ) ? 1 : 0 ) . ' );'; | |
| 239 | + $booking_context_js .= "_wpbc.set_other_param( 'this_page_allow_past_arr', " . wp_json_encode( $allow_past_date_arr ) . ' );'; | |
| 240 | + $booking_context_js .= "_wpbc.set_other_param( 'this_page_admin_booking_nonce', " . wp_json_encode( $admin_booking_nonce ) . ' );'; | |
| 241 | + | |
| 242 | + $is_context_queued = false; | |
| 243 | + if ( ! wp_doing_ajax() && class_exists( 'WPBC_FE_Assets' ) ) { | |
| 244 | + $is_context_queued = WPBC_FE_Assets::add_jq_ready_js_to_wp_script( | |
| 245 | + 'wpbc_all', | |
| 246 | + $booking_context_js, | |
| 247 | + 'wpbc:add-booking-admin-context:' . md5( $booking_context_js ) | |
| 248 | + ); | |
| 249 | + } | |
| 250 | + ?> | |
| 251 | + <script type="text/javascript"> | |
| 252 | + window.wpbc_add_booking_component_context = <?php echo wp_json_encode( $context ); ?>; | |
| 253 | + <?php if ( ! $is_context_queued ) : ?> | |
| 254 | + ( function () { | |
| 255 | + function apply_booking_context() { | |
| 256 | + if ( 'undefined' === typeof _wpbc ) { | |
| 257 | + return; | |
| 258 | + } | |
| 259 | + | |
| 260 | + <?php echo $booking_context_js; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Values are JSON encoded above. ?> | |
| 261 | + } | |
| 262 | + | |
| 263 | + if ( 'undefined' !== typeof _wpbc ) { | |
| 264 | + apply_booking_context(); | |
| 265 | + } else { | |
| 266 | + document.addEventListener( 'DOMContentLoaded', apply_booking_context ); | |
| 267 | + } | |
| 268 | + }() ); | |
| 269 | + <?php endif; ?> | |
| 270 | + </script> | |
| 217 | 271 | <?php |
| 218 | 272 | } |
| 219 | 273 | |
| 220 | 274 | |
| @@ -224,9 +278,9 @@ | ||
| 224 | 278 | * @param array $args Component options. |
| 225 | 279 | * |
| 226 | 280 | * @return array |
| 227 | 281 | */ |
| 228 | - private static function get_allow_past_min_date_arr( $args ) { | |
| 282 | + public static function get_allow_past_min_date_arr( $args ) { | |
| 229 | 283 | |
| 230 | 284 | if ( empty( $args['allow_past'] ) && empty( $args['booking_hash'] ) ) { |
| 231 | 285 | return array(); |
| 232 | 286 | } |
| @@ -271,16 +325,53 @@ | ||
| 271 | 325 | } |
| 272 | 326 | |
| 273 | 327 | |
| 274 | 328 | /** |
| 275 | - * Resolve booking form: explicit component args first, then legacy $_GET. | |
| 329 | + * Resolve default booking form for specific booking resource. | |
| 276 | 330 | * |
| 277 | - * @param array $args Component options. | |
| 331 | + * @param int $resource_id Booking resource ID. | |
| 332 | + * @param string $default_form Fallback form name. | |
| 278 | 333 | * |
| 279 | 334 | * @return string |
| 280 | 335 | */ |
| 281 | - private static function get_explicit_or_get_booking_form( $args ) { | |
| 336 | + public static function get_default_booking_form_for_resource( $resource_id, $default_form = 'standard' ) { | |
| 282 | 337 | |
| 338 | + $resource_id = absint( $resource_id ); | |
| 339 | + $default_form = ( '' !== (string) $default_form ) ? (string) $default_form : 'standard'; | |
| 340 | + | |
| 341 | + if ( $resource_id <= 0 ) { | |
| 342 | + return sanitize_text_field( wp_unslash( $default_form ) ); | |
| 343 | + } | |
| 344 | + | |
| 345 | + $default_custom_form_name = ''; | |
| 346 | + if ( function_exists( 'apply_bk_filter' ) ) { | |
| 347 | + $default_custom_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', '', $resource_id ); | |
| 348 | + } | |
| 349 | + | |
| 350 | + if ( | |
| 351 | + ( '' === (string) $default_custom_form_name ) | |
| 352 | + && class_exists( 'WPBC_FE_Custom_Form_Helper' ) | |
| 353 | + && method_exists( 'WPBC_FE_Custom_Form_Helper', 'get_default_custom_form__for__booking_resource' ) | |
| 354 | + ) { | |
| 355 | + $default_custom_form_name = WPBC_FE_Custom_Form_Helper::get_default_custom_form__for__booking_resource( $resource_id ); | |
| 356 | + } | |
| 357 | + | |
| 358 | + $default_custom_form_name = sanitize_text_field( wp_unslash( (string) $default_custom_form_name ) ); | |
| 359 | + | |
| 360 | + return ( '' !== $default_custom_form_name ) ? $default_custom_form_name : sanitize_text_field( wp_unslash( $default_form ) ); | |
| 361 | + } | |
| 362 | + | |
| 363 | + | |
| 364 | + /** | |
| 365 | + * Resolve booking form: explicit component args first, then legacy $_GET, then resource default. | |
| 366 | + * | |
| 367 | + * @param array $args Component options. | |
| 368 | + * @param int $resource_id Booking resource ID. | |
| 369 | + * | |
| 370 | + * @return string | |
| 371 | + */ | |
| 372 | + private static function get_explicit_or_get_booking_form( $args, $resource_id = 0 ) { | |
| 373 | + | |
| 283 | 374 | if ( ( null !== $args['custom_booking_form'] ) && ( '' !== (string) $args['custom_booking_form'] ) ) { |
| 284 | 375 | return sanitize_text_field( wp_unslash( (string) $args['custom_booking_form'] ) ); |
| 285 | 376 | } |
| 286 | 377 | |
| @@ -287,9 +378,13 @@ | ||
| 287 | 378 | if ( ( null !== $args['booking_form'] ) && ( '' !== (string) $args['booking_form'] ) ) { |
| 288 | 379 | return sanitize_text_field( wp_unslash( (string) $args['booking_form'] ) ); |
| 289 | 380 | } |
| 290 | 381 | |
| 291 | - return WPBC_GET_Request::has_non_empty_get( 'booking_form' ) ? WPBC_GET_Request::get_sanitized( 'booking_form' ) : 'standard'; | |
| 382 | + if ( WPBC_GET_Request::has_non_empty_get( 'booking_form' ) ) { | |
| 383 | + return WPBC_GET_Request::get_sanitized( 'booking_form' ); | |
| 384 | + } | |
| 385 | + | |
| 386 | + return self::get_default_booking_form_for_resource( $resource_id, 'standard' ); | |
| 292 | 387 | } |
| 293 | 388 | |
| 294 | 389 | |
| 295 | 390 | /** |
| @@ -336,12 +431,27 @@ | ||
| 336 | 431 | * Get Calendar Options of specific User. |
| 337 | 432 | * |
| 338 | 433 | * @return array Number of months and calendar options parameter. |
| 339 | 434 | */ |
| 340 | - public static function get_saved_user_calendar_options() { | |
| 435 | + public static function get_saved_user_calendar_options() { | |
| 436 | + | |
| 437 | + return self::format_calendar_options( self::get_saved_user_calendar_settings() ); | |
| 438 | + } | |
| 439 | + | |
| 440 | + | |
| 441 | + /** | |
| 442 | + * Get the raw per-user Add Booking calendar settings. | |
| 443 | + * | |
| 444 | + * The inspector needs the individual saved fields, while | |
| 445 | + * get_saved_user_calendar_options() preserves the renderer-formatted public | |
| 446 | + * result used by the Booking Form component. | |
| 447 | + * | |
| 448 | + * @return array<string,mixed> Raw saved calendar settings. | |
| 449 | + */ | |
| 450 | + public static function get_saved_user_calendar_settings() { | |
| 451 | + | |
| 452 | + $user_calendar_options = get_user_option( 'booking_custom_' . 'add_booking_calendar_options', wpbc_get_current_user_id() ); | |
| 341 | 453 | |
| 342 | - $user_calendar_options = get_user_option( 'booking_custom_' . 'add_booking_calendar_options', wpbc_get_current_user_id() ); | |
| 343 | - | |
| 344 | 454 | if ( false === $user_calendar_options ) { |
| 345 | 455 | $user_calendar_options = array(); |
| 346 | 456 | } else { |
| 347 | 457 | $user_calendar_options = maybe_unserialize( $user_calendar_options ); |
| @@ -346,10 +456,10 @@ | ||
| 346 | 456 | } else { |
| 347 | 457 | $user_calendar_options = maybe_unserialize( $user_calendar_options ); |
| 348 | 458 | } |
| 349 | 459 | |
| 350 | - return self::format_calendar_options( $user_calendar_options ); | |
| 351 | - } | |
| 460 | + return is_array( $user_calendar_options ) ? $user_calendar_options : array(); | |
| 461 | + } | |
| 352 | 462 | |
| 353 | 463 | |
| 354 | 464 | /** |
| 355 | 465 | * Convert calendar option values to the shortcode option string used by the renderer. |