| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly //FixIn: 9.8.0.4 | |
| 3 | +if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly // FixIn: 9.8.0.4. | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | // <editor-fold defaultstate="collapsed" desc=" == SQL - Get Dates array from DB == " > |
| 7 | 7 | |
| @@ -165,11 +165,11 @@ | ||
| 165 | 165 | {$sql_skip_bookings} |
| 166 | 166 | ORDER BY dt.booking_date"; |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | - // Show past bookings, as well | |
| 170 | - // $my_sql = str_replace( 'AND dt.booking_date >= CURDATE()', '', $my_sql ); | |
| 171 | 169 | |
| 170 | + | |
| 171 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter | |
| 172 | 172 | $sql__dates_obj__arr = $wpdb->get_results( $my_sql ); |
| 173 | 173 | |
| 174 | 174 | |
| 175 | 175 | // <editor-fold defaultstate="collapsed" desc=" = CACHE - SAVE :: = " > |
| @@ -184,9 +184,9 @@ | ||
| 184 | 184 | * Get SQL WHERE condition for Dates |
| 185 | 185 | * |
| 186 | 186 | * @param array $params [ 'dates_to_check' => 'CURDATE' ] | [ 'dates_to_check' => 'ALL' ] | [ 'dates_to_check' => [ '2023-07-15' , '2023-07-21' ] ] |
| 187 | 187 | * |
| 188 | - * @return string ' AND ( dt.booking_date >= CURDATE() ) ' | |
| 188 | + * @return string ' AND ( dt.booking_date >= C URDATE() ) ' | |
| 189 | 189 | */ |
| 190 | 190 | function wpbc_get__sql_where__for__dates( $params ){ |
| 191 | 191 | |
| 192 | 192 | $defaults = array( |
| @@ -198,29 +198,68 @@ | ||
| 198 | 198 | if ( 'ALL' == $params['dates_to_check'] ) { // All dates -> '' |
| 199 | 199 | |
| 200 | 200 | return ''; |
| 201 | 201 | |
| 202 | - } else if ( 'CURDATE' == $params['dates_to_check'] ) { // Current dates -> CURDATE() | |
| 202 | + } else if ( 'CURDATE' == $params['dates_to_check'] ) { // Current dates -> CURDATE | |
| 203 | 203 | |
| 204 | - return ' AND ( dt.booking_date >= CURDATE() ) ' ; | |
| 204 | + return ' AND ( dt.booking_date >= ' . wpbc_sql_date_math_expr_explicit('', 'curdate') . ' ) ' ; | |
| 205 | 205 | |
| 206 | - } else if ( is_array( $params['dates_to_check'] ) ) { // Specific Date(s) -> [ '2023-07-15' , '2023-07-21' ] | |
| 206 | + } else if ( is_array( $params['dates_to_check'] ) ) { // Specific Date(s). | |
| 207 | 207 | |
| 208 | - $dates_sql_array = array(); | |
| 208 | + // FixIn: 10.14.9.1. | |
| 209 | 209 | |
| 210 | - for( $i = 0; $i < count( $params['dates_to_check'] ); $i++) { | |
| 210 | + // Sanitize and validate all incoming dates first. | |
| 211 | + $dates_to_check = wpbc_sanitize_dates_to_check( $params['dates_to_check'] ); | |
| 211 | 212 | |
| 212 | - $dates_sql_array[] = "( ( dt.booking_date >= '{$params['dates_to_check'][$i]} 00:00:00' ) AND ( dt.booking_date <= '{$params['dates_to_check'][$i]} 23:59:59' ) )"; | |
| 213 | + // If nothing valid left – do not add any date filter (or return empty string). | |
| 214 | + if ( empty( $dates_to_check ) ) { | |
| 215 | + return ''; | |
| 213 | 216 | } |
| 214 | 217 | |
| 215 | - $dates_sql_str = implode( ' OR ', $dates_sql_array ); | |
| 218 | + global $wpdb; | |
| 216 | 219 | |
| 217 | - return " AND ( {$dates_sql_str} ) " ; | |
| 220 | + $count_dates = count( $dates_to_check ); | |
| 218 | 221 | |
| 222 | + // Case 1: date range (2 items: start / end). | |
| 223 | + if ( 2 === $count_dates ) { | |
| 224 | + $start = $dates_to_check[0] . ' 00:00:00'; | |
| 225 | + $end = $dates_to_check[1] . ' 23:59:59'; | |
| 226 | + | |
| 227 | + // %s will be properly escaped and quoted by $wpdb->prepare(). | |
| 228 | + $dates_sql_str = $wpdb->prepare( ' ( ( dt.booking_date >= %s ) AND ( dt.booking_date <= %s ) ) ', $start, $end ); | |
| 229 | + | |
| 230 | + // Case 2: one date – from that day forward. | |
| 231 | + } else if ( 1 === $count_dates ) { | |
| 232 | + | |
| 233 | + $start = $dates_to_check[0] . ' 00:00:00'; | |
| 234 | + | |
| 235 | + $dates_sql_str = $wpdb->prepare( ' ( dt.booking_date >= %s ) ', $start ); | |
| 236 | + | |
| 237 | + // Case 3: list of specific separate dates – OR between each day. | |
| 238 | + } else { | |
| 239 | + | |
| 240 | + $conditions = array(); | |
| 241 | + $values = array(); | |
| 242 | + | |
| 243 | + foreach ( $dates_to_check as $date ) { | |
| 244 | + | |
| 245 | + $conditions[] = '( ( dt.booking_date >= %s ) AND ( dt.booking_date <= %s ) )'; | |
| 246 | + | |
| 247 | + $values[] = $date . ' 00:00:00'; | |
| 248 | + $values[] = $date . ' 23:59:59'; | |
| 249 | + } | |
| 250 | + | |
| 251 | + $conditions_sql = implode( ' OR ', $conditions ); | |
| 252 | + | |
| 253 | + // $values is an array; $wpdb->prepare() will expand it safely. | |
| 254 | + $dates_sql_str = $wpdb->prepare( $conditions_sql, $values ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared | |
| 255 | + } | |
| 256 | + | |
| 257 | + return ' AND ( ' . $dates_sql_str . ' ) '; | |
| 219 | 258 | } |
| 220 | 259 | |
| 221 | 260 | // Default CURDATE |
| 222 | - return ' AND ( dt.booking_date >= CURDATE() ) '; | |
| 261 | + return ' AND ( dt.booking_date >= ' . wpbc_sql_date_math_expr_explicit('', 'curdate') . ' ) '; | |
| 223 | 262 | } |
| 224 | 263 | |
| 225 | 264 | |
| 226 | 265 | |
| @@ -340,8 +379,10 @@ | ||
| 340 | 379 | ); |
| 341 | 380 | $params_for_dates = wp_parse_args( $params, $defaults ); |
| 342 | 381 | |
| 343 | 382 | |
| 383 | + // $params_for_dates['is_days_always_available'] = in_array( $params_for_dates['resource_id'], array( '1' ) ); // Set some resources as always avavailable. | |
| 384 | + | |
| 344 | 385 | if ( $params_for_dates['is_days_always_available'] ) { // All bookings showing as available dates. |
| 345 | 386 | return array(); |
| 346 | 387 | } |
| 347 | 388 | |
| @@ -496,28 +537,44 @@ | ||
| 496 | 537 | ) |
| 497 | 538 | */ |
| 498 | 539 | function wpbc_get_availability_per_days_arr( $params ) { |
| 499 | 540 | |
| 500 | - if ( 0 ) { //FixIn: 9.8.3.1 ? | |
| 541 | + if ( 0 ) { // FixIn: 9.8.3.1 ? | |
| 501 | 542 | wpbc_set_limit_php( 300 ); // Set 300 seconds for php execution. |
| 502 | 543 | } |
| 503 | 544 | |
| 545 | + $server_request_uri = ( ( isset( $_SERVER['REQUEST_URI'] ) ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */ | |
| 546 | + $server_http_referer_uri = ( ( isset( $_SERVER['HTTP_REFERER'] ) ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */ | |
| 504 | 547 | |
| 505 | - $defaults = array( | |
| 506 | - 'dates_to_check' => 'CURDATE' // 'CURDATE' | 'ALL' | [ '2023-07-15' , '2023-07-21' ] | |
| 507 | - , 'approved' => ( ( get_bk_option( 'booking_is_show_pending_days_as_available' ) == 'On' ) ? '1' : 'all' ) // 'all' | 0 | 1 | |
| 508 | - , 'resource_id' => '1' // Single or parent booking resource!!!! // arrays | CSD | int ??? | |
| 509 | - , 'additional_bk_types' => array() // arrays | CSD | int // OPTIONAL -> aggregate_resource_id_arr ... it is array of booking resources from aggregate shortcode parameter | |
| 510 | - , 'skip_booking_id' => wpbc_get_booking_id__from_hash_in_url() // int | '' // CSD '3,5' | |
| 511 | - , 'as_single_resource' => false // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources' | |
| 512 | - , 'max_days_count' => wpbc_get_max_visible_days_in_calendar() // 365 | |
| 513 | - , 'timeslots_to_check_intersect' => array() // array( '12:20 - 12:55', '13:00 - 14:00' ) //TODO: ? do we really need it, because below we get it from function | |
| 514 | - , 'request_uri' => ( ( ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) ? $_SERVER['HTTP_REFERER'] : $_SERVER['REQUEST_URI'] ) // front-end: $_SERVER['REQUEST_URI'] | ajax: $_SERVER['HTTP_REFERER'] // It different in Ajax requests. It's used for change-over days to detect for exception at specific pages | |
| 515 | - , 'custom_form' => '' // Required for checking all available time-slots and compare with booked time slots | |
| 516 | - ); | |
| 517 | - $params = wp_parse_args( $params, $defaults ); | |
| 548 | + $defaults = array( | |
| 549 | + 'dates_to_check' => 'CURDATE', // v: 'CURDATE' | 'ALL' | arr: '2023-07-15' , '2023-07-21'. | |
| 550 | + 'approved' => ( ( 'On' === get_bk_option( 'booking_is_show_pending_days_as_available' ) ) ? '1' : 'all' ), // v: 'all' | 0 | 1. | |
| 551 | + 'resource_id' => '1', // Single or parent booking resource!!!! // arrays | CSD | int ???. | |
| 552 | + 'additional_bk_types' => array(), // arrays | CSD | int // OPTIONAL -> aggregate_resource_id_arr ... it is array of booking resources from aggregate shortcode parameter. | |
| 553 | + 'skip_booking_id' => wpbc_get_booking_id__from_hash_in_url(), // int | '' // CSD '3,5'. | |
| 554 | + 'as_single_resource' => false, // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'. | |
| 555 | + 'max_days_count' => wpbc_get_max_visible_days_in_calendar(), // 365. | |
| 556 | + 'timeslots_to_check_intersect' => array(), // arr: '12:20 - 12:55', '13:00 - 14:00' ) // TODO: ? do we really need it, because below we get it from function. | |
| 557 | + 'request_uri' => ( ( ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) ? $server_http_referer_uri : $server_request_uri ), // front-end: $server_request_uri | ajax: $server_http_referer_uri // It different in Ajax requests. It's used for change-over days to detect for exception at specific pages. | |
| 558 | + 'allow_past' => false, | |
| 559 | + 'custom_form' => '', // Required for checking all available time-slots and compare with booked time slots. | |
| 560 | + 'force_check_from_today_unavailable' => false, // Optional admin tools can force relative availability checks inside explicit date ranges. | |
| 561 | + ); | |
| 518 | 562 | |
| 563 | + $params = wp_parse_args( $params, $defaults ); | |
| 519 | 564 | |
| 565 | + // FixIn: 10.7.1.2. //FixIn: 10.10.3.2. | |
| 566 | + if ( | |
| 567 | + ( ! empty( $params['allow_past'] ) ) || | |
| 568 | + ( false !== strpos( $params['request_uri'], 'allow_past' ) ) || | |
| 569 | + ( | |
| 570 | + wpbc_is_new_booking_page_url( $params['request_uri'] ) && | |
| 571 | + ( false !== strpos( $params['request_uri'], 'booking_hash' ) ) | |
| 572 | + ) | |
| 573 | + ) { | |
| 574 | + $params['dates_to_check'] = 'ALL'; | |
| 575 | + } | |
| 576 | + | |
| 520 | 577 | // ----------------------------------------------------------------------------------------------------------------- |
| 521 | 578 | // R e s o u r c e (s) D a t a |
| 522 | 579 | // ----------------------------------------------------------------------------------------------------------------- |
| 523 | 580 | // Get array of booking resource ID [1, 13, 8, 6, 7] or default: [ 1 ] |
| @@ -566,10 +623,15 @@ | ||
| 566 | 623 | // ----------------------------------------------------------------------------------------------------------------- |
| 567 | 624 | // Main function to get "Bookings": ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ... |
| 568 | 625 | $bookings__in_dates = wpbc_get__booked_dates__per_resources__arr( $params ); |
| 569 | 626 | |
| 627 | + // ----------------------------------------------------------------------------------------------------------------- | |
| 628 | + // Time slots availability blocks. | |
| 629 | + // ----------------------------------------------------------------------------------------------------------------- | |
| 630 | + $availability_timeslots__in_dates = array(); // FixIn: 10.16.1. | |
| 570 | 631 | |
| 571 | 632 | |
| 633 | + | |
| 572 | 634 | // ----------------------------------------------------------------------------------------------------------------- |
| 573 | 635 | // Booking > Availability page |
| 574 | 636 | // ----------------------------------------------------------------------------------------------------------------- |
| 575 | 637 | $search_dates = $params['dates_to_check']; // 'CURDATE' | 'ALL' | [ "2023-08-03" , "2023-08-04" , "2023-08-05" ] |
| @@ -574,9 +636,9 @@ | ||
| 574 | 636 | // ----------------------------------------------------------------------------------------------------------------- |
| 575 | 637 | $search_dates = $params['dates_to_check']; // 'CURDATE' | 'ALL' | [ "2023-08-03" , "2023-08-04" , "2023-08-05" ] |
| 576 | 638 | |
| 577 | 639 | //FixIn: 9.8.15.10 Aggregate or not Aggregate Booking > Availability ? aggregate_type = 'all' | 'bookings_only' |
| 578 | - if ( ( ! empty( $params['aggregate_type'] ) ) && ( 'bookings_only' === $params['aggregate_type'] ) ) { //FixIn: 9.9.0.16 | |
| 640 | + if ( ( ! empty( $params['aggregate_type'] ) ) && ( 'bookings_only' === $params['aggregate_type'] ) ) { // FixIn: 9.9.0.16. | |
| 579 | 641 | $unavailable_dates__per_resources__arr = wpbc_for_resources_arr__get_unavailable_dates( |
| 580 | 642 | $resource_id__with_children__arr, // Only One Primary Resource !! |
| 581 | 643 | $search_dates |
| 582 | 644 | ); // [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ] |
| @@ -588,9 +650,28 @@ | ||
| 588 | 650 | } |
| 589 | 651 | $unavailable_dates__per_resources__arr = wpbc_aggregate_merge_availability( $unavailable_dates__per_resources__arr, |
| 590 | 652 | $resource_id__with_children__arr, |
| 591 | 653 | $aggregate_resource_id_arr ); |
| 654 | + // FixIn: 10.16.1. | |
| 655 | + if ( function_exists( 'wpbc_availability_timeslots__get_intervals_for_resources' ) ) { | |
| 656 | + $availability_timeslots__resource_ids = wpbc_get_unique_array_of_resources_id( $resource_id__with_children__arr, $aggregate_resource_id_arr ); | |
| 657 | + $availability_timeslots__in_dates = wpbc_availability_timeslots__get_intervals_for_resources( | |
| 658 | + array( | |
| 659 | + 'resource_id' => $availability_timeslots__resource_ids, | |
| 660 | + 'dates_to_check' => $search_dates, | |
| 661 | + 'max_days_count' => $params['max_days_count'], | |
| 662 | + ) | |
| 663 | + ); | |
| 592 | 664 | |
| 665 | + if ( function_exists( 'wpbc_availability_timeslots__aggregate_merge_intervals' ) ) { | |
| 666 | + $availability_timeslots__in_dates = wpbc_availability_timeslots__aggregate_merge_intervals( | |
| 667 | + $availability_timeslots__in_dates, | |
| 668 | + $resource_id__with_children__arr, | |
| 669 | + $aggregate_resource_id_arr | |
| 670 | + ); | |
| 671 | + } | |
| 672 | + } | |
| 673 | + | |
| 593 | 674 | // ----------------------------------------------------------------------------------------------------------------- |
| 594 | 675 | // Booking > Resources > Availability page |
| 595 | 676 | // ----------------------------------------------------------------------------------------------------------------- |
| 596 | 677 | $season_filters_availability = array(); |
| @@ -607,10 +688,16 @@ | ||
| 607 | 688 | // P a r a m e t e r s f o r L O O P |
| 608 | 689 | // ----------------------------------------------------------------------------------------------------------------- |
| 609 | 690 | |
| 610 | 691 | // - Is this Booking > Add booking page ? -------------------------------------------------------------------------- |
| 611 | - $is_this_bap_page = ( false !== strpos( $params['request_uri'], 'page=wpbc-new' ) ) ? true : false; | |
| 692 | + $is_this_bap_page = wpbc_is_new_booking_page_url( $params['request_uri'] ); | |
| 612 | 693 | $is_this_hash_page = ( false !== strpos( $params['request_uri'], 'booking_hash' ) ) ? true : false; // Set it to TRUE for adding booking in past at Booking > Add booking page |
| 694 | + | |
| 695 | + // FixIn: 10.7.1.2. | |
| 696 | + if ( ! $is_this_hash_page ) { | |
| 697 | + $is_this_hash_page = ( ( ! empty( $params['allow_past'] ) ) || ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ) ? true : false; | |
| 698 | + } | |
| 699 | + | |
| 613 | 700 | if ( ( $is_this_bap_page ) && ( $is_this_hash_page ) ) { // Start days in calendar from = PAST |
| 614 | 701 | $params['dates_to_check'] = 'ALL'; |
| 615 | 702 | } |
| 616 | 703 | |
| @@ -618,21 +705,21 @@ | ||
| 618 | 705 | |
| 619 | 706 | $start_day_number = - 1 * $params['max_days_count']; |
| 620 | 707 | //$today_inix_timestamp = strtotime( '-' . intval( $params['max_days_count'] ) . ' days' ); // - 300 days |
| 621 | 708 | |
| 622 | - // Get time, relative to Timezone from WordPress > Settings General page //FixIn: 9.9.0.17 | |
| 709 | + // Get time, relative to Timezone from WordPress > Settings General page // FixIn: 9.9.0.17. | |
| 623 | 710 | $start_date_unix = strtotime( '-' . intval( $params['max_days_count'] ) . ' days' ); // - 365 days |
| 624 | - $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( date( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' ); | |
| 711 | + $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( gmdate( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' ); | |
| 625 | 712 | $today_inix_timestamp = strtotime( $date_with_wp_timezone ); |
| 626 | 713 | |
| 627 | - } else if ( 'CURDATE' == $params['dates_to_check'] ) { // Current dates -> CURDATE() | |
| 714 | + } else if ( 'CURDATE' == $params['dates_to_check'] ) { // Current dates -> CURDATE | |
| 628 | 715 | |
| 629 | 716 | $start_day_number = 1; |
| 630 | - // $today_inix_timestamp = strtotime( date( 'Y-m-d 00:00:00', strtotime( 'now' ) ) ); // Today 00:00:00 | |
| 717 | + // $today_inix_timestamp = strtotime( gmdate( 'Y-m-d 00:00:00', strtotime( 'now' ) ) ); // Today 00:00:00 | |
| 631 | 718 | |
| 632 | - // Get time, relative to Timezone from WordPress > Settings General page //FixIn: 9.9.0.17 | |
| 719 | + // Get time, relative to Timezone from WordPress > Settings General page // FixIn: 9.9.0.17. | |
| 633 | 720 | $start_date_unix = strtotime( 'now' ); |
| 634 | - $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( date( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' ); | |
| 721 | + $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( gmdate( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' ); | |
| 635 | 722 | $today_inix_timestamp = strtotime( $date_with_wp_timezone ); |
| 636 | 723 | |
| 637 | 724 | } else if ( is_array( $params['dates_to_check'] ) ) { |
| 638 | 725 | |
| @@ -637,12 +724,12 @@ | ||
| 637 | 724 | } else if ( is_array( $params['dates_to_check'] ) ) { |
| 638 | 725 | |
| 639 | 726 | $start_day_number = 1; |
| 640 | 727 | |
| 641 | - $today_inix_timestamp = strtotime( $params['dates_to_check'][0] . ' 00:00:00' ); // '2023-09-03 00:00:00' | |
| 728 | + $today_inix_timestamp = strtotime( $params['dates_to_check'][0] . ' 00:00:00 UTC' ); // '2023-09-03 00:00:00' | |
| 642 | 729 | |
| 643 | - $dif_in_days = strtotime( $params['dates_to_check'][ ( count( $params['dates_to_check'] ) - 1 ) ] . ' 00:00:00' ) | |
| 644 | - - strtotime( $params['dates_to_check'][0] . ' 00:00:00' ); | |
| 730 | + $dif_in_days = strtotime( $params['dates_to_check'][ ( count( $params['dates_to_check'] ) - 1 ) ] . ' 00:00:00 UTC' ) | |
| 731 | + - strtotime( $params['dates_to_check'][0] . ' 00:00:00 UTC' ); | |
| 645 | 732 | |
| 646 | 733 | $dif_in_days = $dif_in_days / ( 24 * 60 * 60 ); |
| 647 | 734 | $params['max_days_count'] = ceil( $dif_in_days ) + 1; |
| 648 | 735 | } |
| @@ -662,9 +749,9 @@ | ||
| 662 | 749 | $availability_per_day = array(); |
| 663 | 750 | |
| 664 | 751 | for ( $day_num = $start_day_number; $day_num <= $params['max_days_count']; $day_num ++ ) { |
| 665 | 752 | |
| 666 | - $my_day_tag = date( 'Y-m-d', $today_inix_timestamp ); // '2023-07-19' | |
| 753 | + $my_day_tag = gmdate( 'Y-m-d', $today_inix_timestamp ); // '2023-07-19' | |
| 667 | 754 | |
| 668 | 755 | |
| 669 | 756 | //-------------------------------------------------------------------------------------------------------------- |
| 670 | 757 | // Get Time-Slots from booking form to CHECK INTERSECT :: Convert readable time slot to time slot as seconds [ '12:20 - 12:55', '13:00 - 14:00' ] OR [] if not time slots |
| @@ -697,8 +784,9 @@ | ||
| 697 | 784 | $availability_per_day[ $my_day_tag ]['statuses']['bookings_status'] = array(); // per each child booking resource |
| 698 | 785 | $availability_per_day[ $my_day_tag ]['summary'] = array(); |
| 699 | 786 | $availability_per_day[ $my_day_tag ]['summary']['status_for_day'] = ''; // available | time_slots_booking | full_day_booking | ... |
| 700 | 787 | $availability_per_day[ $my_day_tag ]['summary']['status_for_bookings'] = ''; // pending | approved | CO: pending_pending | pending_approved | approved_pending | approved_approved |
| 788 | + $availability_per_day[ $my_day_tag ]['summary']['status_for_bookings_arr'] = array(); // Structured statuses array, e.g. array( 'approved', 'approved_approved' ). | |
| 701 | 789 | $availability_per_day[ $my_day_tag ]['summary']['tooltip_times'] = ''; |
| 702 | 790 | $availability_per_day[ $my_day_tag ]['summary']['tooltip_availability'] = ''; |
| 703 | 791 | $availability_per_day[ $my_day_tag ]['summary']['tooltip_day_cost'] = ''; |
| 704 | 792 | $availability_per_day[ $my_day_tag ]['summary']['tooltip_booking_details'] = ''; |
| @@ -871,11 +959,20 @@ | ||
| 871 | 959 | |
| 872 | 960 | // ===================================================================================================== |
| 873 | 961 | // Change over days = |
| 874 | 962 | // ===================================================================================================== |
| 963 | + $is_booking_used_check_in_out_time = null; | |
| 964 | + if ( function_exists( 'wpbc_settings_calendar__preview_is_changeover_enabled' ) ) { | |
| 965 | + $is_booking_used_check_in_out_time = wpbc_settings_calendar__preview_is_changeover_enabled( $resource_id, $params['request_uri'] ); | |
| 966 | + } | |
| 967 | + if ( null === $is_booking_used_check_in_out_time ) { | |
| 968 | + $is_booking_used_check_in_out_time = ( | |
| 969 | + ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) ) | |
| 970 | + && ( wpbc_is_booking_used_check_in_out_time( $params['request_uri'], $resource_id ) ) | |
| 971 | + ); | |
| 972 | + } | |
| 875 | 973 | if ( |
| 876 | - ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) ) | |
| 877 | - && ( wpbc_is_booking_used_check_in_out_time( $params[ 'request_uri' ] ) ) | |
| 974 | + $is_booking_used_check_in_out_time | |
| 878 | 975 | && ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) // And this date still free false |
| 879 | 976 | ) { |
| 880 | 977 | |
| 881 | 978 | /** |
| @@ -960,9 +1057,48 @@ | ||
| 960 | 1057 | } |
| 961 | 1058 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 962 | 1059 | // B O O K I N G S - E n d |
| 963 | 1060 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1061 | + // Working Time applies only to time-based booking forms: rangetime, start/end, or start/duration. | |
| 1062 | + $working_time__timeslots_to_check_intersect = $as_seconds_timeslots_arr__to_check_intersect; | |
| 1063 | + if ( empty( $working_time__timeslots_to_check_intersect ) && ! empty( $params['timeslots_to_check_intersect'] ) ) { | |
| 1064 | + if ( ! is_array( $params['timeslots_to_check_intersect'] ) ) { | |
| 1065 | + $params['timeslots_to_check_intersect'] = array( $params['timeslots_to_check_intersect'] ); | |
| 1066 | + } | |
| 1067 | + $working_time__timeslots_to_check_intersect = array(); | |
| 1068 | + foreach ( $params['timeslots_to_check_intersect'] as $time_slot_readable ) { | |
| 1069 | + $working_time__timeslots_to_check_intersect[] = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $time_slot_readable ); | |
| 1070 | + } | |
| 1071 | + } | |
| 964 | 1072 | |
| 1073 | + if ( | |
| 1074 | + ! empty( $working_time__timeslots_to_check_intersect ) | |
| 1075 | + && function_exists( 'wpbc_working_time__get_non_working_intervals_for_date' ) | |
| 1076 | + && function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' ) | |
| 1077 | + ) { | |
| 1078 | + $working_time__blocked_intervals = wpbc_working_time__get_non_working_intervals_for_date( $resource_id, $my_day_tag ); | |
| 1079 | + | |
| 1080 | + if ( ! empty( $working_time__blocked_intervals ) ) { | |
| 1081 | + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj( | |
| 1082 | + $availability_per_day[ $my_day_tag ][ $resource_id ], | |
| 1083 | + $working_time__blocked_intervals, | |
| 1084 | + $working_time__timeslots_to_check_intersect | |
| 1085 | + ); | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | + | |
| 1089 | + // FixIn: 10.16.1. | |
| 1090 | + if ( | |
| 1091 | + function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' ) | |
| 1092 | + && isset( $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ] ) | |
| 1093 | + ) { | |
| 1094 | + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj( | |
| 1095 | + $availability_per_day[ $my_day_tag ][ $resource_id ], | |
| 1096 | + $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ], | |
| 1097 | + $as_seconds_timeslots_arr__to_check_intersect | |
| 1098 | + ); | |
| 1099 | + } | |
| 1100 | + | |
| 965 | 1101 | //========================================================================================================== |
| 966 | 1102 | // $availability_per_day[..]->_day_status = 'season_filter' | ... |
| 967 | 1103 | //========================================================================================================== |
| 968 | 1104 | // Booking > Resources > Availability page >>> 'season_filter' |
| @@ -970,19 +1106,36 @@ | ||
| 970 | 1106 | |
| 971 | 1107 | // Booking > Availability page >>> 'resource_availability' |
| 972 | 1108 | $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__resource_availability( $availability_per_day, $my_day_tag, $resource_id, $unavailable_dates__per_resources__arr ); |
| 973 | 1109 | |
| 974 | - // Week Days unavailable >>> 'weekday_unavailable' | |
| 975 | - $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id ); | |
| 1110 | + if ( empty( $params['skip_general_availability'] ) ) { | |
| 1111 | + // Week Days unavailable >>> 'weekday_unavailable' | |
| 1112 | + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id ); | |
| 1113 | + } | |
| 976 | 1114 | |
| 977 | - if ( ( ! $is_this_bap_page ) || ( ! $is_this_hash_page ) ) { | |
| 1115 | + // if ( ( ! $is_this_bap_page ) || ( ! $is_this_hash_page ) ) { | |
| 1116 | + if ( empty( $params['skip_general_availability'] ) && ( ! $is_this_bap_page ) && ( ! $is_this_hash_page ) ) { | |
| 978 | 1117 | // Do not apply these settings at Booking > Add booking page, when we edit booking - e.g. exist 'booking_hash' |
| 979 | 1118 | |
| 980 | - // Unavailable days from today >>> 'from_today_unavailable' | |
| 981 | - $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id ); | |
| 1119 | + // Skip checking unavailable from today, if defined the calendar_dates_start='2025-02-10' calendar_dates_end='2025-12-31' in shortcode. // FixIn: 10.13.1.4. | |
| 1120 | + $is_skip_check__from_today_unavailable = false; | |
| 1121 | + if ( is_array( $params['dates_to_check'] ) && empty( $params['force_check_from_today_unavailable'] ) ) { | |
| 1122 | + if ( ( ( count( $params['dates_to_check'] ) ) > 0 ) && ( wpbc_is_date_less_than( $params['dates_to_check'][0], $my_day_tag ) ) ) { | |
| 1123 | + $is_skip_check__from_today_unavailable = true; | |
| 1124 | + } | |
| 1125 | + if ( ( ( count( $params['dates_to_check'] ) ) > 1 ) && ( wpbc_is_date_higher_than( $params['dates_to_check'][1], $my_day_tag ) ) ) { | |
| 1126 | + $is_skip_check__from_today_unavailable = true; | |
| 1127 | + } | |
| 1128 | + } | |
| 982 | 1129 | |
| 983 | - // Limit available days from today >>> 'limit_available_from_today' | |
| 984 | - $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__limit_available_from_today( $availability_per_day, $my_day_tag, $resource_id ); | |
| 1130 | + if ( ! $is_skip_check__from_today_unavailable ) { | |
| 1131 | + | |
| 1132 | + // Unavailable days from today >>> 'from_today_unavailable'. | |
| 1133 | + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id ); | |
| 1134 | + | |
| 1135 | + // Limit available days from today >>> 'limit_available_from_today'. | |
| 1136 | + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__limit_available_from_today( $availability_per_day, $my_day_tag, $resource_id ); | |
| 1137 | + } | |
| 985 | 1138 | } |
| 986 | 1139 | //========================================================================================================== |
| 987 | 1140 | |
| 988 | 1141 | |
| @@ -1002,21 +1155,24 @@ | ||
| 1002 | 1155 | // ========================================================================================================= |
| 1003 | 1156 | // Entire D A Y statuses |
| 1004 | 1157 | // ========================================================================================================= |
| 1005 | 1158 | |
| 1006 | - if ( $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) { | |
| 1007 | - // Reduce DAY day_availability, if some season or days unavailable or full by bookings | |
| 1008 | - $availability_per_day[ $my_day_tag ][ 'day_availability' ]--; | |
| 1159 | + if ( $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) { | |
| 1160 | + // Set merged time interval as fully unavailable. | |
| 1161 | + $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_seconds'] = array( array( 0, 86400 ) ); // FixIn: 10.11.5.1. | |
| 1162 | + // Reduce DAY day_availability, if some season or days unavailable or full by bookings. | |
| 1163 | + --$availability_per_day[ $my_day_tag ]['day_availability']; | |
| 1009 | 1164 | } |
| 1010 | 1165 | |
| 1011 | - // 'resource_availability' | 'weekday_unavailable' | 'from_today_unavailable' | 'limit_available_from_today' | 'season_filter' | 'full_day_booking' | 'time_slots_booking' | 'available' | |
| 1166 | + // 'resource_availability' | 'weekday_unavailable' | 'from_today_unavailable' | 'limit_available_from_today' | 'season_filter' | 'full_day_booking' | 'time_slots_booking' | 'available'. | |
| 1012 | 1167 | $availability_per_day[ $my_day_tag ]['statuses']['day_status'][] = $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status; |
| 1013 | 1168 | |
| 1014 | - // 'approved' | 'pending' | |
| 1169 | + // 'approved' | 'pending'. | |
| 1015 | 1170 | $availability_per_day[ $my_day_tag ]['statuses']['bookings_status'][] = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved ); |
| 1016 | 1171 | |
| 1017 | - // Go to next child booking resource | |
| 1172 | + // Go to next child booking resource. | |
| 1018 | 1173 | } |
| 1174 | + | |
| 1019 | 1175 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1020 | 1176 | // R E S O U R C E S - E n d |
| 1021 | 1177 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1022 | 1178 | |
| @@ -1087,12 +1243,11 @@ | ||
| 1087 | 1243 | $availability_per_this_day['summary']['tooltip_day_cost'] = wpbc_support_capacity__tooltip__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ); |
| 1088 | 1244 | $availability_per_this_day['summary']['tooltip_availability'] = wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ); |
| 1089 | 1245 | |
| 1090 | 1246 | |
| 1247 | + $availability_per_this_day['summary']['hint__in_day__cost'] = wpbc_support_capacity__in_day_hint__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ); | |
| 1248 | + $availability_per_this_day['summary']['hint__in_day__availability'] = wpbc_support_capacity__in_day_hint__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ); // FixIn: 10.6.4.1. | |
| 1091 | 1249 | |
| 1092 | - | |
| 1093 | - $availability_per_this_day['summary']['hint__in_day__cost'] = wpbc_support_capacity__in_day_hint__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ); | |
| 1094 | - | |
| 1095 | 1250 | // ------------------------------------------------------------------------------------------------------------- |
| 1096 | 1251 | // ['summary']['status_for_day'] |
| 1097 | 1252 | // ------------------------------------------------------------------------------------------------------------- |
| 1098 | 1253 | $temp_status = array(); |
| @@ -1102,8 +1257,9 @@ | ||
| 1102 | 1257 | $temp_status[] = $bookings_status_element; |
| 1103 | 1258 | } |
| 1104 | 1259 | } |
| 1105 | 1260 | $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed. |
| 1261 | + $temp_status_counts = array_count_values( $temp_status ); | |
| 1106 | 1262 | $temp_status = array_unique( $temp_status ); // Erase duplicates |
| 1107 | 1263 | $availability_per_this_day['summary']['status_for_day'] = $temp_status; |
| 1108 | 1264 | |
| 1109 | 1265 | /** |
| @@ -1128,10 +1284,34 @@ | ||
| 1128 | 1284 | // Priority: available > time_slots_booking > full_day_booking |
| 1129 | 1285 | // > season_filter > resource_availability |
| 1130 | 1286 | // > weekday_unavailable > from_today_unavailable > limit_available_from_today |
| 1131 | 1287 | |
| 1132 | - // if at least one booking "available" then day has this status | |
| 1288 | + // Capacity resources can be available even when every child has a check-in/out or full-day status. | |
| 1289 | + $max_capacity = isset( $availability_per_this_day['max_capacity'] ) ? intval( $availability_per_this_day['max_capacity'] ) : 1; | |
| 1290 | + $blocking_statuses = array( | |
| 1291 | + 'full_day_booking', | |
| 1292 | + 'season_filter', | |
| 1293 | + 'resource_availability', | |
| 1294 | + 'weekday_unavailable', | |
| 1295 | + 'from_today_unavailable', | |
| 1296 | + 'limit_available_from_today', | |
| 1297 | + 'change_over', | |
| 1298 | + ); | |
| 1299 | + $blocked_capacity = 0; | |
| 1300 | + foreach ( $blocking_statuses as $blocking_status ) { | |
| 1301 | + $blocked_capacity += isset( $temp_status_counts[ $blocking_status ] ) ? intval( $temp_status_counts[ $blocking_status ] ) : 0; | |
| 1302 | + } | |
| 1303 | + $booked_capacity__before_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_out'] ) ? intval( $temp_status_counts['check_out'] ) : 0 ); | |
| 1304 | + $booked_capacity__after_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_in'] ) ? intval( $temp_status_counts['check_in'] ) : 0 ); | |
| 1305 | + $is_capacity_available_during_change_over = ( | |
| 1306 | + ( $max_capacity > 1 ) | |
| 1307 | + && ( $max_capacity > max( $booked_capacity__before_check_in, $booked_capacity__after_check_in ) ) | |
| 1308 | + && ( ! in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) ) | |
| 1309 | + ); | |
| 1310 | + | |
| 1311 | + // if at least one resource is available then day has this status | |
| 1133 | 1312 | if ( in_array( 'available', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'available'; |
| 1313 | + } else if ( $is_capacity_available_during_change_over ) { $availability_per_this_day['summary']['status_for_day'] = 'available'; | |
| 1134 | 1314 | } else if ( in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'time_slots_booking'; |
| 1135 | 1315 | } else if ( ( ! in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) ) |
| 1136 | 1316 | && ( in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) ) ) { $availability_per_this_day['summary']['status_for_day'] = 'check_in'; |
| 1137 | 1317 | } else if ( ( ! in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) ) |
| @@ -1157,19 +1337,21 @@ | ||
| 1157 | 1337 | $temp_status[] = $bookings_status_element; |
| 1158 | 1338 | } |
| 1159 | 1339 | } |
| 1160 | 1340 | $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed. |
| 1161 | - $temp_status = array_unique( $temp_status ); | |
| 1162 | - $availability_per_this_day['summary']['status_for_bookings'] = $temp_status; | |
| 1341 | + $temp_status = array_values( array_unique( $temp_status ) ); | |
| 1163 | 1342 | |
| 1343 | + // Structured booking statuses contract. Keep numeric keys sequential so JSON encodes this as a JS array. | |
| 1344 | + $availability_per_this_day['summary']['status_for_bookings_arr'] = $temp_status; | |
| 1345 | + | |
| 1164 | 1346 | // Priority: pending > approved > '' |
| 1165 | 1347 | |
| 1166 | 1348 | // if at least one booking pending then day is pending |
| 1167 | - if ( in_array( 'pending', $availability_per_this_day['summary']['status_for_bookings'] ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending'; | |
| 1168 | - } else if ( in_array( 'pending_pending', $availability_per_this_day['summary']['status_for_bookings'] ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending'; | |
| 1349 | + if ( in_array( 'pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending'; | |
| 1350 | + } else if ( in_array( 'pending_pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending'; | |
| 1169 | 1351 | // Usual situations for change over days: pending_pending | pending_approved | approved_pending | approved_approved |
| 1170 | 1352 | } else { |
| 1171 | - $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ', $availability_per_this_day['summary']['status_for_bookings'] ); | |
| 1353 | + $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ', $temp_status ); | |
| 1172 | 1354 | } |
| 1173 | 1355 | |
| 1174 | 1356 | |
| 1175 | 1357 | // ------------------------------------------------------------------------------------------------------------- |
| @@ -1262,28 +1444,32 @@ | ||
| 1262 | 1444 | $tooltip_title_word = ( empty( $tooltip_title_word ) ) |
| 1263 | 1445 | ? '' |
| 1264 | 1446 | : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' '; |
| 1265 | 1447 | |
| 1266 | - $id_of_first_resource = $resource_id_arr[0]; | |
| 1267 | - $tooltip_content_header = ''; | |
| 1448 | + if ( isset( $resource_id_arr[0] ) ) { | |
| 1268 | 1449 | |
| 1269 | - if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) { | |
| 1450 | + $id_of_first_resource = $resource_id_arr[0]; | |
| 1451 | + $tooltip_content_header = ''; | |
| 1270 | 1452 | |
| 1271 | - $cur_sym = get_bk_option( 'booking_cost_in_date_cell_currency' ); // in Booking > Settings General page in "Calendar" section | |
| 1272 | - //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page | |
| 1453 | + if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) { | |
| 1273 | 1454 | |
| 1274 | - $cost_text = wpbc_formate_cost_hint__no_html( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate, $cur_sym ); | |
| 1275 | - $cost_text = html_entity_decode( $cost_text ); | |
| 1455 | + $cur_sym = get_bk_option( 'booking_cost_in_date_cell_currency' ); // in Booking > Settings General page in "Calendar" section | |
| 1456 | + //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page | |
| 1276 | 1457 | |
| 1277 | - $tooltip = '<div class="wpbc_tooltip_section tooltip__day_cost">' | |
| 1278 | - . $tooltip_title_word | |
| 1279 | - . '<div class="wpbc_tooltip_resource_container">' | |
| 1280 | - . $tooltip_content_header | |
| 1281 | - . '<div class="wpbc_tooltip_item">' | |
| 1282 | - . $cost_text | |
| 1458 | + $cost_text = wpbc_formate_cost_hint__no_html( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate, $cur_sym ); | |
| 1459 | + $cost_text = html_entity_decode( $cost_text ); | |
| 1460 | + | |
| 1461 | + $tooltip = '<div class="wpbc_tooltip_section tooltip__day_cost">' | |
| 1462 | + . $tooltip_title_word | |
| 1463 | + . '<div class="wpbc_tooltip_resource_container">' | |
| 1464 | + . $tooltip_content_header | |
| 1465 | + . '<div class="wpbc_tooltip_item">' | |
| 1466 | + . $cost_text | |
| 1467 | + . '</div>' | |
| 1283 | 1468 | . '</div>' |
| 1284 | - . '</div>' | |
| 1285 | - . '</div>'; | |
| 1469 | + . '</div>'; | |
| 1470 | + } | |
| 1471 | + | |
| 1286 | 1472 | } |
| 1287 | 1473 | } |
| 1288 | 1474 | return $tooltip; |
| 1289 | 1475 | } |
| @@ -1305,19 +1491,62 @@ | ||
| 1305 | 1491 | //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page |
| 1306 | 1492 | |
| 1307 | 1493 | $cost_text = $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate; |
| 1308 | 1494 | $cost_text = number_format( floatval( $cost_text ), wpbc_get_cost_decimals(), '.', '' ); |
| 1309 | - $cost_text = strip_tags( wpbc_cost_show( $cost_text, array( 'currency' => 'CURRENCY_SYMBOL' ) ) ); | |
| 1495 | + $cost_text = wp_strip_all_tags( wpbc_cost_show( $cost_text, array( 'currency' => 'CURRENCY_SYMBOL' ) ) ); | |
| 1310 | 1496 | $cost_text = str_replace( array( 'CURRENCY_SYMBOL', '&' ), array( $cur_sym, '&' ), $cost_text ); |
| 1311 | 1497 | $cost_text = html_entity_decode($cost_text); |
| 1312 | 1498 | |
| 1313 | - $tooltip = $cost_text; | |
| 1499 | + $tooltip = '<span class="wpbc_in_date_hint__cost">' . $cost_text . '</span>';; | |
| 1314 | 1500 | } |
| 1315 | 1501 | } |
| 1316 | 1502 | return $tooltip; |
| 1317 | 1503 | } |
| 1318 | 1504 | |
| 1505 | + // FixIn: 10.6.4.1. | |
| 1319 | 1506 | /** |
| 1507 | + * Get availability for in Day cells | |
| 1508 | + * | |
| 1509 | + * @param $availability_per_this_day | |
| 1510 | + * @param $my_day_tag | |
| 1511 | + * @param $resource_id_arr | |
| 1512 | + * | |
| 1513 | + * @return string | |
| 1514 | + */ | |
| 1515 | + function wpbc_support_capacity__in_day_hint__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){ | |
| 1516 | + | |
| 1517 | + $tooltip = ''; | |
| 1518 | + | |
| 1519 | + if ( | |
| 1520 | + ( 'On' == get_bk_option( 'booking_is_show_availability_in_date_cell' ) ) && | |
| 1521 | + ( $availability_per_this_day['max_capacity'] > 1 ) | |
| 1522 | + ) { | |
| 1523 | + | |
| 1524 | + $tooltip_title_word = get_bk_option( 'booking_highlight_availability_word_in_date_cell' ); | |
| 1525 | + $tooltip_title_word = wpbc_lang( $tooltip_title_word ); | |
| 1526 | + $tooltip_title_word = ( empty( $tooltip_title_word ) ) | |
| 1527 | + ? '' | |
| 1528 | + : '<span class="wpbc_in_date_hint__availability_title">' . $tooltip_title_word . '</span>'; | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + if ( ! empty( $availability_per_this_day['day_availability'] ) ) { | |
| 1532 | + | |
| 1533 | + $tooltip = '<span class="wpbc_in_date_hint__availability">' | |
| 1534 | + . '<span class="wpbc_in_date_hint__availability_number">' | |
| 1535 | + . intval( $availability_per_this_day['day_availability'] ) | |
| 1536 | + . ' ' | |
| 1537 | + . '</span>' | |
| 1538 | + . $tooltip_title_word | |
| 1539 | + . '</span>'; | |
| 1540 | + $tooltip = html_entity_decode($tooltip); | |
| 1541 | + } | |
| 1542 | + } | |
| 1543 | + return $tooltip; | |
| 1544 | + } | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + /** | |
| 1320 | 1549 | * Set tooltip summary -- Booking Details |
| 1321 | 1550 | * |
| 1322 | 1551 | * @param $availability_per_this_day |
| 1323 | 1552 | * @param $my_day_tag |
| @@ -1330,9 +1559,9 @@ | ||
| 1330 | 1559 | $tooltip = ''; |
| 1331 | 1560 | |
| 1332 | 1561 | if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) { //FixIn: 9.5.0.2.2 |
| 1333 | 1562 | |
| 1334 | - $tooltip_title_word = '<div class="wpbc_tooltip_title">' . __('Booking details','booking') . '</div>'; | |
| 1563 | + $tooltip_title_word = '<div class="wpbc_tooltip_title">' . esc_html__('Booking details','booking') . '</div>'; | |
| 1335 | 1564 | |
| 1336 | 1565 | $status_summary_tooltip_times = array(); |
| 1337 | 1566 | foreach ( $resource_id_arr as $resource_id ) { |
| 1338 | 1567 | if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['details'] ) ) { |
| @@ -1507,9 +1736,9 @@ | ||
| 1507 | 1736 | foreach ( $booking_data_arr as $replace_shortcode => $replace_value ) { |
| 1508 | 1737 | |
| 1509 | 1738 | if ( is_null( $replace_value ) ) { $replace_value = ''; }; |
| 1510 | 1739 | |
| 1511 | - $replace_value = wpbc_replace__true_false__to__yes_no( $replace_value ); //FixIn: 9.8.9.1 | |
| 1740 | + $replace_value = wpbc_replace__true_false__to__yes_no( $replace_value ); // FixIn: 9.8.9.1. | |
| 1512 | 1741 | |
| 1513 | 1742 | $booking_shortcodes_in_tooltips = str_replace( array( |
| 1514 | 1743 | '[' . $replace_shortcode . ']' |
| 1515 | 1744 | , '{' . $replace_shortcode . '}' |
| @@ -1591,23 +1820,33 @@ | ||
| 1591 | 1820 | * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ] |
| 1592 | 1821 | */ |
| 1593 | 1822 | function wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id ){ |
| 1594 | 1823 | |
| 1824 | + // FixIn: 10.8.1.4. | |
| 1825 | + | |
| 1595 | 1826 | // ----------------------------------------------------------------------------------------------------- // from_today_unavailable |
| 1596 | 1827 | // 2. Unavailable days from today |
| 1597 | 1828 | $unavailable_days_num_from_today = get_bk_option( 'booking_unavailable_days_num_from_today' ); |
| 1598 | 1829 | |
| 1599 | - //FixIn: 9.9.0.17 | |
| 1600 | - $start_date_unix = strtotime( '+' . intval( $unavailable_days_num_from_today ) . ' days' ); // + 0 days | |
| 1601 | - $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( date( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' ); | |
| 1602 | - $today_timestamp_wp_timezone = strtotime( $date_with_wp_timezone ); | |
| 1603 | - $days_number = intval( ( $today_timestamp_wp_timezone - strtotime( $my_day_tag ) ) / 86400 ); | |
| 1830 | + // FixIn: 10.8.1.4. | |
| 1831 | + if ( ! empty( $unavailable_days_num_from_today ) ) { | |
| 1832 | + if ( 'm' === substr( $unavailable_days_num_from_today, - 1 ) ) { | |
| 1833 | + $start_date_unix = strtotime( '+' . ( intval( $unavailable_days_num_from_today ) - 1 ) . ' minutes' ); // + 0 days | |
| 1834 | + } else { | |
| 1835 | + $start_date_unix = strtotime( '+' . intval( $unavailable_days_num_from_today ) . ' days' ); // + 0 days | |
| 1836 | + } | |
| 1837 | + } else { | |
| 1838 | + $start_date_unix = strtotime( 'now' ); | |
| 1839 | + } | |
| 1604 | 1840 | |
| 1605 | - //$days_number = intval( ( strtotime( '+' . intval( $unavailable_days_num_from_today ) . ' days' ) - strtotime( $my_day_tag ) ) / 86400 ); | |
| 1841 | + $date_start__gmt = gmdate( 'Y-m-d H:i:s', $start_date_unix ); // '2025-01-25 12:50:10' | |
| 1842 | + $date_start__midnight__wp_timezone = wpbc_datetime_localized__use_wp_timezone( $date_start__gmt, 'Y-m-d 00:00:00' ); // Local Midnight. | |
| 1606 | 1843 | |
| 1844 | + // 'Today Midnight' - 'Calendar Day Cell' . | |
| 1845 | + $days_number = intval( ( strtotime( $date_start__midnight__wp_timezone ) - strtotime( $my_day_tag ) ) / 86400 ); | |
| 1607 | 1846 | |
| 1608 | 1847 | if ( $days_number > 0 ) { |
| 1609 | - // this date unavailable | |
| 1848 | + // This date Unavailable. | |
| 1610 | 1849 | $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true; |
| 1611 | 1850 | $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'from_today_unavailable'; |
| 1612 | 1851 | |
| 1613 | 1852 | if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) { |
| @@ -1635,9 +1874,9 @@ | ||
| 1635 | 1874 | foreach ( range( 0, 6 ) as $week_day_num ) { |
| 1636 | 1875 | $unavailable_weekdays[ $week_day_num ] = ( 'On' == get_bk_option( 'booking_unavailable_day' . $week_day_num ) ) ? true : false; |
| 1637 | 1876 | } |
| 1638 | 1877 | |
| 1639 | - $this_day_week_num = date( 'w', strtotime( $my_day_tag ) ); // 0 - 6 | |
| 1878 | + $this_day_week_num = gmdate( 'w', strtotime( $my_day_tag ) ); // 0 - 6 | |
| 1640 | 1879 | |
| 1641 | 1880 | if ( $unavailable_weekdays[ $this_day_week_num ] ) { |
| 1642 | 1881 | // this date unavailable |
| 1643 | 1882 | $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true; |
| @@ -1789,9 +2028,9 @@ | ||
| 1789 | 2028 | // all_selected_dates_arr Can be: [ "2023-10-05", "2023-10-06", "2023-10-07", … ] |
| 1790 | 2029 | // PHP actions: |
| 1791 | 2030 | // from: make_bk_action('wpdev_booking_post_inserted', $booking_id, $bktype, $str_dates__dd_mm_yyyy, array($start_time, $end_time ) , $formdata ); |
| 1792 | 2031 | // removed! |
| 1793 | -// . | |
| 2032 | +// . // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 1794 | 2033 | // from: apply_filters('wpdev_booking_form_content', $form , $resource_id); |
| 1795 | 2034 | // to: apply_filters( 'wpbc_booking_form_html__update__append_change_over_times', $form, $resource_id ); |
| 1796 | 2035 | // . |
| 1797 | 2036 | // Removed PHP actions: |
| @@ -1805,5 +2044,5 @@ | ||
| 1805 | 2044 | // * // , 'wpdev_active_locale' => 'en_US' |
| 1806 | 2045 | // * ) ); |
| 1807 | 2046 | // . |
| 1808 | 2047 | // add_bk_filter('wpbc_add_new_booking_filter' , 'wpbc_add_new_booking' ); |
| 1809 | -// TODO: recheck hooks in wpbc-dev-api.php | |
| 2048 | +// TODO: recheck hooks in wpbc-dev-api.php | |