PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
11.9 11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 All 205 releases
← All changes | includes/page-bookings/bookings__sql.php +515 -91 10.15.7 → 11.9 View file →
@@ -1,4 +1,4 @@
1 1 <?php /**
2 2 * @version 1.0
3 3 * @description Bookings Listing SQL
4 4 * @category Booking Listing
@@ -30,9 +30,9 @@
30 30 */
31 31 function wpbc_ajx_get__request_params__names_default( $structure_type = 'validate_and_default' ){
32 32
33 33 // Clean specific $_REQUEST params, if param is NOT set then return "default"
34 - $params_for_cleaning = array(
34 + $params_for_cleaning = array(
35 35 // 'wh_booking_id' => array( 'validate' => 'digit_or_date', 'default' => '' ),
36 36
37 37 // 'digit_or_csd' can check about 'digit_or_csd' in arrays, as well
38 38 'wh_booking_type' => array( 'validate' => 'digit_or_csd', 'default' => array( '0' ) ) // if ['0'] - All booking resources, ['-1'] - lost bookings in deleted resources
@@ -90,12 +90,23 @@
90 90 , 'scroll_start_date' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20
91 91 , 'scroll_day' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
92 92 , 'scroll_month' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
93 93 , 'limit_hours' => array( 'validate' => 'digit_or_csd', 'default' => '' ) //
94 - , 'only_booked_resources' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
94 + , 'only_booked_resources' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
95 +
96 + );
97 +
98 + /**
99 + * Filter the Booking Listing request schema before values are sanitized.
100 + *
101 + * Extensions may add narrowly scoped listing filters without duplicating the
102 + * saved-user-request or AJAX sanitization pipeline.
103 + *
104 + * @param array<string,array<string,mixed>> $params_for_cleaning Request validation and default definitions.
105 + * @param string $structure_type Requested schema representation.
106 + */
107 + $params_for_cleaning = apply_filters( 'wpbc_booking_listing_request_params_schema', $params_for_cleaning, $structure_type );
95 108
96 - );
97 -
98 109 if ( 'validate_and_default' == $structure_type ) {
99 110 return $params_for_cleaning;
100 111 }
101 112
@@ -919,12 +930,36 @@
919 930 $sql['where'] = apply_bk_filter('update_where_sql_for_getting_bookings_in_multiuser', $sql['where'] ); // Add 'AND bk.booking_type IN ( $user_resources )' to the end of Where
920 931 }
921 932 }
922 933
923 - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
924 -
925 -
926 - switch ( $params['wh_sort'] ) {
934 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
935 +
936 + /**
937 + * Filter the prepared Booking Listing WHERE fragment and its placeholders.
938 + *
939 + * The base query has already applied dates, resources, MultiUser ownership,
940 + * status, cost, and keyword rules. Additions must return the same two keys.
941 + *
942 + * @param array{where:string,args:array<int,mixed>} $query_parts WHERE SQL and prepare arguments.
943 + * @param array<string,mixed> $request_params Sanitized listing request.
944 + * @param array<string,mixed> $params Request merged with defaults.
945 + */
946 + $query_parts = apply_filters(
947 + 'wpbc_booking_listing_sql_query_parts',
948 + array(
949 + 'where' => $sql['where'],
950 + 'args' => $sql_args,
951 + ),
952 + $request_params,
953 + $params
954 + );
955 + if ( is_array( $query_parts ) && isset( $query_parts['where'], $query_parts['args'] ) && is_string( $query_parts['where'] ) && is_array( $query_parts['args'] ) ) {
956 + $sql['where'] = $query_parts['where'];
957 + $sql_args = $query_parts['args'];
958 + }
959 +
960 +
961 + switch ( $params['wh_sort'] ) {
927 962 case 'booking_id__asc':
928 963 $order_by = 'booking_id ASC ';
929 964 break;
930 965 case 'booking_id__desc':
@@ -1603,9 +1638,9 @@
1603 1638 * )
1604 1639 * [181] => stdClass Object (
1605 1640 * ....
1606 1641 */
1607 - function wpbc_ajx_include_bookingdates_in_the_bookings( $bookings_obj, $booking_dates_obj ){
1642 + function wpbc_ajx_include_bookingdates_in_the_bookings( $bookings_obj, $booking_dates_obj ){
1608 1643
1609 1644 $bookings_arr = array();
1610 1645 foreach ( $bookings_obj as $booking ) {
1611 1646
@@ -1709,14 +1744,376 @@
1709 1744 }
1710 1745
1711 1746 } // bookings loop: $booking_id => $booking
1712 1747
1713 - return $bookings_arr;
1714 - }
1748 + return $bookings_arr;
1749 + }
1750 +
1751 +
1752 + /**
1753 + * Build an empty Booking Listing Resource-allocation DTO.
1754 + *
1755 + * A stable empty shape keeps the browser template data-only and avoids
1756 + * edition-specific checks in the presentation layer.
1757 + *
1758 + * @return array<string,mixed> Empty Resource-allocation DTO.
1759 + */
1760 + function wpbc_booking_listing_get_empty_resource_allocation() {
1761 +
1762 + return array(
1763 + 'is_multiple_resources' => false,
1764 + 'resource_count' => 0,
1765 + 'resource_count_label' => '',
1766 + 'date_summary_label' => '',
1767 + 'segment_count' => 0,
1768 + 'segments' => array(),
1769 + );
1770 + }
1771 +
1772 +
1773 + /**
1774 + * Return a localized time label for one allocation day.
1775 + *
1776 + * Duplicate timestamps are expected when a quantity booking reserves
1777 + * several Resources. Midnight represents a full day and is omitted. When
1778 + * two or more non-midnight values exist, the first and last values describe
1779 + * the booked time interval without repeating it for every Resource.
1780 + *
1781 + * @param array<string,mixed> $allocation_day Normalized day record.
1782 + *
1783 + * @return string Localized time or time-range label. Empty for full days.
1784 + */
1785 + function wpbc_booking_listing_get_allocation_day_time_label( $allocation_day ) {
1786 +
1787 + if ( empty( $allocation_day['times'] ) || ! is_array( $allocation_day['times'] ) ) {
1788 + return '';
1789 + }
1790 +
1791 + $sql_times = array_values( array_unique( array_filter( array_map( 'strval', $allocation_day['times'] ) ) ) );
1792 + sort( $sql_times, SORT_STRING );
1793 +
1794 + $formatted_times = array();
1795 + foreach ( $sql_times as $sql_time ) {
1796 + if ( '00:00:00' === $sql_time ) {
1797 + continue;
1798 + }
1799 +
1800 + list( , $formatted_time ) = wpbc_get_date_in_correct_format( $allocation_day['date'] . ' ' . $sql_time );
1801 + $formatted_time = trim( $formatted_time );
1802 + if ( '' !== $formatted_time ) {
1803 + $formatted_times[] = $formatted_time;
1804 + }
1805 + }
1806 +
1807 + $formatted_times = array_values( array_unique( $formatted_times ) );
1808 + if ( empty( $formatted_times ) ) {
1809 + return '';
1810 + }
1811 +
1812 + if ( 1 === count( $formatted_times ) ) {
1813 + return $formatted_times[0];
1814 + }
1815 +
1816 + return $formatted_times[0] . ' – ' . $formatted_times[ count( $formatted_times ) - 1 ];
1817 + }
1818 +
1819 +
1820 + /**
1821 + * Format one chronological Resource-allocation period.
1822 + *
1823 + * Common recurrent times are shown once after the date range. Check-in and
1824 + * check-out times that differ between the first and final day stay attached
1825 + * to their respective dates. Full-day periods contain dates only.
1826 + *
1827 + * @param string $start_date First date in Y-m-d format.
1828 + * @param string $end_date Final date in Y-m-d format.
1829 + * @param array<string,array> $allocation_days Normalized days keyed by Y-m-d.
1830 + *
1831 + * @return string Localized period label.
1832 + */
1833 + function wpbc_booking_listing_format_allocation_period_label( $start_date, $end_date, $allocation_days ) {
1834 +
1835 + list( $start_date_label ) = wpbc_get_date_in_correct_format( $start_date . ' 00:00:00' );
1836 + list( $end_date_label ) = wpbc_get_date_in_correct_format( $end_date . ' 00:00:00' );
1837 +
1838 + $period_days = array();
1839 + foreach ( $allocation_days as $date_key => $allocation_day ) {
1840 + if ( $date_key >= $start_date && $date_key <= $end_date ) {
1841 + $period_days[ $date_key ] = $allocation_day;
1842 + }
1843 + }
1844 +
1845 + $day_time_labels = array();
1846 + foreach ( $period_days as $date_key => $allocation_day ) {
1847 + $day_time_labels[ $date_key ] = wpbc_booking_listing_get_allocation_day_time_label( $allocation_day );
1848 + }
1849 +
1850 + if ( $start_date === $end_date ) {
1851 + $time_label = isset( $day_time_labels[ $start_date ] ) ? $day_time_labels[ $start_date ] : '';
1852 +
1853 + return '' !== $time_label ? $start_date_label . ', ' . $time_label : $start_date_label;
1854 + }
1855 +
1856 + $non_empty_time_labels = array_values( array_filter( $day_time_labels ) );
1857 + $unique_time_labels = array_values( array_unique( $non_empty_time_labels ) );
1858 + if ( count( $non_empty_time_labels ) === count( $period_days ) && 1 === count( $unique_time_labels ) ) {
1859 + return $start_date_label . ' – ' . $end_date_label . ', ' . $unique_time_labels[0];
1860 + }
1861 +
1862 + $start_time_label = isset( $day_time_labels[ $start_date ] ) ? $day_time_labels[ $start_date ] : '';
1863 + $end_time_label = isset( $day_time_labels[ $end_date ] ) ? $day_time_labels[ $end_date ] : '';
1864 + if ( '' !== $start_time_label ) {
1865 + $start_date_label .= ', ' . $start_time_label;
1866 + }
1867 + if ( '' !== $end_time_label ) {
1868 + $end_date_label .= ', ' . $end_time_label;
1869 + }
1870 +
1871 + return $start_date_label . ' – ' . $end_date_label;
1872 + }
1873 +
1874 +
1875 + /**
1876 + * Resolve authorized Resource presentation records for an allocation set.
1877 + *
1878 + * Only titles already present in the owner-filtered Booking Listing Resource
1879 + * collection are exposed. Missing or deleted Resources receive the existing
1880 + * neutral fallback instead of leaking an unavailable title.
1881 + *
1882 + * @param array<int> $resource_ids Resource IDs in display order.
1883 + * @param array<int,array> $booking_resources_arr Owner-filtered Resource records.
1884 + *
1885 + * @return array<int,array<string,mixed>> JSON-safe Resource presentation records.
1886 + */
1887 + function wpbc_booking_listing_get_allocation_resource_records( $resource_ids, $booking_resources_arr ) {
1888 +
1889 + $resource_records = array();
1890 + foreach ( $resource_ids as $resource_id ) {
1891 + $resource_id = absint( $resource_id );
1892 + $resource_title = isset( $booking_resources_arr[ $resource_id ]['title'] )
1893 + ? wp_strip_all_tags( wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) )
1894 + : __( 'Resource not exist', 'booking' );
1895 +
1896 + $resource_records[] = array(
1897 + 'resource_id' => $resource_id,
1898 + 'resource_title' => $resource_title,
1899 + 'is_missing' => ! isset( $booking_resources_arr[ $resource_id ] ),
1900 + );
1901 + }
1902 +
1903 + return $resource_records;
1904 + }
1905 +
1906 +
1907 + /**
1908 + * Group normalized allocation days into chronological Resource-set segments.
1909 + *
1910 + * Consecutive dates are merged only while their complete Resource set stays
1911 + * identical. This represents both a booking that moves between Resources and
1912 + * a quantity booking that reserves several Resources for the same period.
1913 + *
1914 + * @param array<string,array> $allocation_days Normalized days keyed by Y-m-d.
1915 + * @param array<int,array> $booking_resources_arr Owner-filtered Resource records.
1916 + *
1917 + * @return array<int,array<string,mixed>> Ordered allocation segments.
1918 + */
1919 + function wpbc_booking_listing_group_allocation_days( $allocation_days, $booking_resources_arr ) {
1920 +
1921 + $segments = array();
1922 + $current_segment = array();
1923 +
1924 + foreach ( $allocation_days as $date_key => $allocation_day ) {
1925 + $resource_ids = array_values( array_unique( array_map( 'absint', array_keys( $allocation_day['resources'] ) ) ) );
1926 + sort( $resource_ids, SORT_NUMERIC );
1927 + $resource_signature = implode( ',', $resource_ids );
1928 +
1929 + $is_same_segment = ! empty( $current_segment )
1930 + && $resource_signature === $current_segment['resource_signature']
1931 + && wpbc_is_next_day( $date_key, $current_segment['end_date'] );
1932 +
1933 + if ( ! $is_same_segment ) {
1934 + if ( ! empty( $current_segment ) ) {
1935 + $current_segment['period_label'] = wpbc_booking_listing_format_allocation_period_label(
1936 + $current_segment['start_date'],
1937 + $current_segment['end_date'],
1938 + $allocation_days
1939 + );
1940 + $current_segment['resources'] = wpbc_booking_listing_get_allocation_resource_records( $current_segment['resource_ids'], $booking_resources_arr );
1941 + unset( $current_segment['resource_signature'], $current_segment['resource_ids'] );
1942 + $segments[] = $current_segment;
1943 + }
1944 +
1945 + $current_segment = array(
1946 + 'start_date' => $date_key,
1947 + 'end_date' => $date_key,
1948 + 'day_count' => 1,
1949 + 'resource_signature' => $resource_signature,
1950 + 'resource_ids' => $resource_ids,
1951 + );
1952 + continue;
1953 + }
1954 +
1955 + $current_segment['end_date'] = $date_key;
1956 + ++$current_segment['day_count'];
1957 + }
1958 +
1959 + if ( ! empty( $current_segment ) ) {
1960 + $current_segment['period_label'] = wpbc_booking_listing_format_allocation_period_label(
1961 + $current_segment['start_date'],
1962 + $current_segment['end_date'],
1963 + $allocation_days
1964 + );
1965 + $current_segment['resources'] = wpbc_booking_listing_get_allocation_resource_records( $current_segment['resource_ids'], $booking_resources_arr );
1966 + unset( $current_segment['resource_signature'], $current_segment['resource_ids'] );
1967 + $segments[] = $current_segment;
1968 + }
1969 +
1970 + return $segments;
1971 + }
1972 +
1973 +
1974 + /**
1975 + * Build compact chronological date periods independently of Resource changes.
1976 + *
1977 + * This summary is used in the narrow date column. It avoids repeating dates
1978 + * for quantity bookings while preserving gaps between non-consecutive dates.
1979 + *
1980 + * @param array<string,array> $allocation_days Normalized days keyed by Y-m-d.
1981 + *
1982 + * @return array<int,string> Localized date-period labels.
1983 + */
1984 + function wpbc_booking_listing_get_allocation_date_period_labels( $allocation_days ) {
1985 +
1986 + $period_labels = array();
1987 + $start_date = '';
1988 + $end_date = '';
1989 +
1990 + foreach ( array_keys( $allocation_days ) as $date_key ) {
1991 + if ( '' === $start_date ) {
1992 + $start_date = $date_key;
1993 + $end_date = $date_key;
1994 + continue;
1995 + }
1996 +
1997 + if ( wpbc_is_next_day( $date_key, $end_date ) ) {
1998 + $end_date = $date_key;
1999 + continue;
2000 + }
2001 +
2002 + $period_labels[] = wpbc_booking_listing_format_allocation_period_label( $start_date, $end_date, $allocation_days );
2003 + $start_date = $date_key;
2004 + $end_date = $date_key;
2005 + }
2006 +
2007 + if ( '' !== $start_date ) {
2008 + $period_labels[] = wpbc_booking_listing_format_allocation_period_label( $start_date, $end_date, $allocation_days );
2009 + }
2010 +
2011 + return $period_labels;
2012 + }
2013 +
2014 +
2015 + /**
2016 + * Build the Booking Listing Resource-allocation DTO from saved date rows.
2017 + *
2018 + * Business Large stores the booking's main Resource in `booking.booking_type`.
2019 + * A date on that Resource has an empty `bookingdates.type_id`; only dates on
2020 + * another Resource contain `type_id`. Normalizing that fallback before
2021 + * counting or grouping prevents both missing labels and repeated per-date
2022 + * child labels.
2023 + *
2024 + * @param object $booking Booking with `booking_db`, `dates`, and `child_id` values.
2025 + * @param array<int,array> $booking_resources_arr Owner-filtered Resource records.
2026 + *
2027 + * @return array<string,mixed> JSON-safe Resource-allocation DTO.
2028 + */
2029 + function wpbc_booking_listing_build_resource_allocation( $booking, $booking_resources_arr ) {
2030 +
2031 + $resource_allocation = wpbc_booking_listing_get_empty_resource_allocation();
2032 + if (
2033 + empty( $booking->booking_db->booking_type )
2034 + || empty( $booking->dates )
2035 + || ! is_array( $booking->dates )
2036 + ) {
2037 + return $resource_allocation;
2038 + }
2039 +
2040 + $main_resource_id = absint( $booking->booking_db->booking_type );
2041 + $allocation_days = array();
2042 + $all_resource_ids = array();
2043 +
2044 + foreach ( $booking->dates as $date_index => $sql_booking_date ) {
2045 + $sql_booking_date = is_scalar( $sql_booking_date ) ? trim( (string) $sql_booking_date ) : '';
2046 + if ( ! preg_match( '/^(\d{4})-(\d{2})-(\d{2})(?:\s+(\d{2}):(\d{2}):(\d{2}))?$/', $sql_booking_date, $date_parts ) ) {
2047 + continue;
2048 + }
2049 +
2050 + $year = (int) $date_parts[1];
2051 + $month = (int) $date_parts[2];
2052 + $day = (int) $date_parts[3];
2053 + $hour = isset( $date_parts[4] ) ? (int) $date_parts[4] : 0;
2054 + $minute = isset( $date_parts[5] ) ? (int) $date_parts[5] : 0;
2055 + $second = isset( $date_parts[6] ) ? (int) $date_parts[6] : 0;
2056 + if (
2057 + ! checkdate( $month, $day, $year )
2058 + || $hour > 23
2059 + || $minute > 59
2060 + || $second > 59
2061 + ) {
2062 + continue;
2063 + }
2064 +
2065 + $date_key = sprintf( '%04d-%02d-%02d', $year, $month, $day );
2066 + $sql_time = isset( $date_parts[4], $date_parts[5], $date_parts[6] )
2067 + ? sprintf( '%02d:%02d:%02d', $hour, $minute, $second )
2068 + : '00:00:00';
2069 + $date_resource_id = isset( $booking->child_id[ $date_index ] ) && ! empty( $booking->child_id[ $date_index ] )
2070 + ? absint( $booking->child_id[ $date_index ] )
2071 + : $main_resource_id;
2072 +
2073 + if ( empty( $date_resource_id ) ) {
2074 + continue;
2075 + }
2076 +
2077 + if ( ! isset( $allocation_days[ $date_key ] ) ) {
2078 + $allocation_days[ $date_key ] = array(
2079 + 'date' => $date_key,
2080 + 'times' => array(),
2081 + 'resources' => array(),
2082 + );
2083 + }
2084 +
2085 + $allocation_days[ $date_key ]['times'][] = $sql_time;
2086 + $allocation_days[ $date_key ]['resources'][ $date_resource_id ] = true;
2087 + $all_resource_ids[ $date_resource_id ] = true;
2088 + }
2089 +
2090 + if ( empty( $allocation_days ) ) {
2091 + return $resource_allocation;
2092 + }
2093 +
2094 + ksort( $allocation_days, SORT_STRING );
2095 + $resource_count = count( $all_resource_ids );
2096 + $period_labels = wpbc_booking_listing_get_allocation_date_period_labels( $allocation_days );
2097 + $segments = wpbc_booking_listing_group_allocation_days( $allocation_days, $booking_resources_arr );
2098 +
2099 + $resource_allocation['is_multiple_resources'] = ( $resource_count > 1 );
2100 + $resource_allocation['resource_count'] = $resource_count;
2101 + $resource_allocation['resource_count_label'] = sprintf(
2102 + /* translators: %d: Number of booking Resources reserved by one booking. */
2103 + _n( '%d booking resource', '%d booking resources', $resource_count, 'booking' ),
2104 + $resource_count
2105 + );
2106 + $resource_allocation['date_summary_label'] = implode( ', ', $period_labels );
2107 + $resource_allocation['segment_count'] = count( $segments );
2108 + $resource_allocation['segments'] = $segments;
2109 +
2110 + return $resource_allocation;
2111 + }
2112 +
2113 +
2114 + function wpbc_ajx_parse_bookings( $bookings_arr, $resources_arr ) {
1715 2115
1716 -
1717 - function wpbc_ajx_parse_bookings( $bookings_arr, $resources_arr ) {
1718 -
1719 2116 $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
1720 2117
1721 2118 foreach ( $bookings_arr as $booking_id => $booking ) {
1722 2119
@@ -1732,8 +2129,28 @@
1732 2129 if ( class_exists( 'wpdev_bk_multiuser' ) ) {
1733 2130 $resource_owner_user = ( isset( $resources_arr[ $resource_id ] ) ) ? $resources_arr[ $resource_id ]['users'] : $user_id;
1734 2131 }
1735 2132
2133 + $resource_title_listing = $resource_title;
2134 + $resource_id_listing = $resource_id;
2135 + $child_resource_id_arr = array();
2136 + if ( ( class_exists( 'wpdev_bk_biz_l' ) ) && ( ! empty( $booking->child_id ) ) && ( is_array( $booking->child_id ) ) ) {
2137 + foreach ( $booking->child_id as $child_resource_id ) {
2138 + if ( ! empty( $child_resource_id ) ) {
2139 + $child_resource_id_arr[] = (int) $child_resource_id;
2140 + }
2141 + }
2142 + $child_resource_id_arr = array_values( array_unique( $child_resource_id_arr ) );
2143 +
2144 + if ( ( 1 === count( $child_resource_id_arr ) ) && ( isset( $resources_arr[ $child_resource_id_arr[0] ] ) ) ) {
2145 + $resource_id_listing = $child_resource_id_arr[0];
2146 + $resource_title_listing = wpbc_lang( $resources_arr[ $child_resource_id_arr[0] ]['title'] );
2147 + }
2148 + }
2149 + $resource_allocation = class_exists( 'wpdev_bk_biz_l' )
2150 + ? wpbc_booking_listing_build_resource_allocation( $booking, $resources_arr )
2151 + : wpbc_booking_listing_get_empty_resource_allocation();
2152 +
1736 2153 // Parse form fields only from $booking->booking_db->form ------------------------------------------
1737 2154 $booking_data_arr = wpbc_parse_booking_data_fields( $booking->booking_db->form,
1738 2155 array( 'resource_id' => $resource_id )
1739 2156 );
@@ -1779,11 +2196,14 @@
1779 2196 // Set dates and times in correct format ---------------------------------------------------------------
1780 2197 $booking_data_arr = wpbc_parse_booking_data_fields_formats( $booking_data_arr );
1781 2198
1782 2199 // Get SHORT / WIDE Dates showing data -----------------------------------------------------------------
1783 - $dates_attr = array( 'date_html_tag' => 'span' );
1784 - $short_dates_content = wpbc_get_formated_dates__short( $booking->short_dates, (boolean) $booking->approved, $booking->short_dates_child_id, $resources_arr, $dates_attr );
1785 - $wide_dates_content = wpbc_get_formated_dates__wide( $booking->dates, (boolean) $booking->approved, $booking->child_id, $resources_arr, $dates_attr );
2200 + $dates_attr = array(
2201 + 'date_html_tag' => 'span',
2202 + 'show_child_resource_in_dates' => false,
2203 + );
2204 + $short_dates_content = wpbc_get_formated_dates__short( $booking->short_dates, (bool) $booking->approved, $booking->short_dates_child_id, $resources_arr, $dates_attr );
2205 + $wide_dates_content = wpbc_get_formated_dates__wide( $booking->dates, (bool) $booking->approved, $booking->child_id, $resources_arr, $dates_attr );
1786 2206
1787 2207 //------------------------------------------------------------------------------------------------------
1788 2208 // Payment Status
1789 2209 //------------------------------------------------------------------------------------------------------
@@ -1852,8 +2272,10 @@
1852 2272 // Add some fields to [ 'parsed_fields' ]
1853 2273 //------------------------------------------------------------------------------------------------------
1854 2274 $booking_data_arr['resource_title'] = $resource_title;
1855 2275 $booking_data_arr['resource_id'] = $resource_id;
2276 + $booking_data_arr['resource_title_listing'] = $resource_title_listing;
2277 + $booking_data_arr['resource_id_listing'] = $resource_id_listing;
1856 2278 $booking_data_arr['resource_owner_user'] = $resource_owner_user;
1857 2279 //$booking_data_arr['short_dates_content'] = $short_dates_content;
1858 2280 //$booking_data_arr['wide_dates_content'] = $wide_dates_content;
1859 2281
@@ -1860,10 +2282,15 @@
1860 2282 //------------------------------------------------------------------------------------------------------
1861 2283 // Form Show - "Content of booking fields data" form
1862 2284 //------------------------------------------------------------------------------------------------------
1863 2285
1864 - $custom_booking_form_name = ( ! empty( $booking_data_arr['wpbc_custom_booking_form'] ) ) ? $booking_data_arr['wpbc_custom_booking_form'] : ''; // FixIn: 9.4.3.12.
1865 - $form_show_template = wpbc_get_content_booking_form_show( $resource_id , $custom_booking_form_name ); // <strong>First Name</strong>:<span class="fieldvalue">[name]</span>&nbsp;&nbsp; ...
2286 + $custom_booking_form_name = ( ! empty( $booking_data_arr['wpbc_custom_booking_form'] ) ) ? $booking_data_arr['wpbc_custom_booking_form'] : ''; // FixIn: 9.4.3.12.
2287 + $booking_data_arr['admin_edit_url'] = wpbc_get_booking_admin_edit_url(
2288 + $resource_id,
2289 + isset( $booking_data_arr['hash'] ) ? $booking_data_arr['hash'] : '',
2290 + $custom_booking_form_name
2291 + );
2292 + $form_show_template = wpbc_get_content_booking_form_show( $resource_id , $custom_booking_form_name ); // <strong>First Name</strong>:<span class="fieldvalue">[name]</span>&nbsp;&nbsp; ...
1866 2293 $parsed_form_show = wpbc_get_parsed_content_booking_form_show( $booking_data_arr, $form_show_template ); // <strong>First Name</strong>:<span class="fieldvalue">John</span>&nbsp;&nbsp; ...
1867 2294
1868 2295 //------------------------------------------------------------------------------------------------------
1869 2296 // Google Calendar link
@@ -1876,9 +2303,11 @@
1876 2303 $booking_data_arr['visitorbookingpayurl'] = ( class_exists( 'wpdev_bk_biz_s' ) )
1877 2304 ? apply_bk_filter( 'wpdev_booking_set_booking_edit_link_at_email', '[visitorbookingpayurl]', $booking_id )
1878 2305 : '';
1879 2306 // =====================================================================================================
1880 - $bookings_arr[ $booking_id ]->parsed_fields = $booking_data_arr;
2307 + $booking_data_arr = apply_filters( 'wpbc_booking_listing_parsed_fields', $booking_data_arr, $booking_id, $booking );
2308 + $bookings_arr[ $booking_id ]->parsed_fields = $booking_data_arr;
2309 + $bookings_arr[ $booking_id ]->resource_allocation = $resource_allocation;
1881 2310
1882 2311
1883 2312 // =====================================================================================================
1884 2313 $bookings_arr[ $booking_id ]->templates = array(
@@ -1921,8 +2350,9 @@
1921 2350 function wpbc_get_formated_dates__short( $short_dates_arr, $is_approved = false, $dates_type_id_arr = array(), $booking_resources_arr = array(), $attr = array() ) {
1922 2351
1923 2352 $defaults = array(
1924 2353 'date_html_tag' => 'a',
2354 + 'show_child_resource_in_dates' => true,
1925 2355 );
1926 2356 $params = wp_parse_args( $attr, $defaults );
1927 2357
1928 2358 $css_class_approved = ( $is_approved ) ? 'approved' : '';
@@ -1928,20 +2358,35 @@
1928 2358 $css_class_approved = ( $is_approved ) ? 'approved' : '';
1929 2359 $short_dates_content = '';
1930 2360 $short_dates_content_arr = array();
1931 2361 $date_number = 0;
1932 - $previous_formatted_date = '';
1933 - $previous_short_dates_content_sup;
1934 - foreach ( $short_dates_arr as $dt ) {
2362 + $previous_formatted_date = '';
2363 + $previous_short_dates_content_sup;
2364 + $previous_sql_date = '';
2365 + $previous_short_date_item = '';
2366 + foreach ( $short_dates_arr as $dt ) {
1935 2367
1936 2368 if ( '-' === $dt ) {
1937 2369 $short_dates_content_arr[] = '<span class="date_tire"> - </span>';
1938 - } elseif ( ',' === $dt ) {
1939 - $short_dates_content_arr[] = '<span class="date_tire date_comma">, </span>';
1940 - } else {
2370 + } elseif ( ',' === $dt ) {
2371 + $short_dates_content_arr[] = '<span class="date_tire date_comma">, </span>';
2372 + } else {
2373 +
2374 + // Separate recurrent time slots: previous end (...02) followed by the next start (...01).
2375 + $is_next_time_slot = (
2376 + ( ! empty( $previous_sql_date ) )
2377 + && ( '02' === substr( trim( $previous_sql_date ), -2 ) )
2378 + && ( '01' === substr( trim( $dt ), -2 ) )
2379 + );
2380 + if ( $is_next_time_slot && ( ',' !== $previous_short_date_item ) ) {
2381 + if ( '-' === $previous_short_date_item ) {
2382 + array_pop( $short_dates_content_arr );
2383 + }
2384 + $short_dates_content_arr[] = '<span class="date_tire date_comma">, </span>'; // FixIn: 11.4.2.
2385 + }
2386 +
2387 + list( $formatted_date, $formatted_time ) = wpbc_get_date_in_correct_format( $dt );
1941 2388
1942 - list( $formatted_date, $formatted_time ) = wpbc_get_date_in_correct_format( $dt );
1943 -
1944 2389 $short_dates_content = '';
1945 2390 $short_dates_content_sup = ''; // Times and booking resources.
1946 2391
1947 2392 if ( 'a' === $params['date_html_tag'] ) {
@@ -1956,19 +2401,22 @@
1956 2401 if ( $previous_formatted_date !== $formatted_date ) {
1957 2402 $short_dates_content .= $formatted_date;
1958 2403 $short_dates_content_sup .= '<sup class="field-booking-time">' . $formatted_time . '</sup>';
1959 2404 } else {
1960 - // same date (probaly it is one date) !
1961 - if ( count( $short_dates_content_arr ) > 0 ) {
1962 - // Unset tire: '-'.
1963 - unset( $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ] );
1964 - if ( ! empty( wp_strip_all_tags( $previous_short_dates_content_sup ) ) ) {
1965 - $tag_closed_span_and_a = $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ];
1966 - // unset time_sup
1967 - unset( $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ] );
1968 - $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ] = $tag_closed_span_and_a;
1969 - }
1970 - $short_dates_content_sup .= '<sup class="field-booking-time">' . wp_strip_all_tags( $previous_short_dates_content_sup ) . ' - ' . $formatted_time . '</sup>';
2405 + // same date (probaly it is one date) !
2406 + if ( count( $short_dates_content_arr ) > 0 ) {
2407 + // Unset tire: '-'.
2408 + array_pop( $short_dates_content_arr );
2409 + if ( ! empty( wp_strip_all_tags( $previous_short_dates_content_sup ) ) ) {
2410 + $tag_closed_span_and_a = array_pop( $short_dates_content_arr );
2411 + array_pop( $short_dates_content_arr ); // Unset time_sup.
2412 + $short_dates_content_arr[] = $tag_closed_span_and_a; // FixIn: 11.4.2.
2413 + }
2414 + $short_dates_content_sup .= '<sup class="field-booking-time"> '
2415 + . trim( wp_strip_all_tags( $previous_short_dates_content_sup ) )
2416 + . ' - '
2417 + . trim( $formatted_time )
2418 + . '</sup>'; // FixIn: 11.4.2.
1971 2419 }
1972 2420 }
1973 2421
1974 2422 // BL.
@@ -1973,8 +2421,9 @@
1973 2421
1974 2422 // BL.
1975 2423 if (
1976 2424 ( class_exists( 'wpdev_bk_biz_l' ) )
2425 + && ( $params['show_child_resource_in_dates'] )
1977 2426 && ( ! empty( $dates_type_id_arr[ $date_number ] ) )
1978 2427 && ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
1979 2428 ){
1980 2429
@@ -1995,12 +2444,14 @@
1995 2444 $short_dates_content_arr[] = '</span></' . $params['date_html_tag'] . '>';
1996 2445
1997 2446
1998 2447
1999 - $previous_short_dates_content_sup = $short_dates_content_sup;
2000 - $previous_formatted_date = $formatted_date;
2001 - }
2002 - $date_number++;
2448 + $previous_short_dates_content_sup = $short_dates_content_sup;
2449 + $previous_formatted_date = $formatted_date;
2450 + $previous_sql_date = $dt;
2451 + }
2452 + $previous_short_date_item = $dt;
2453 + $date_number++;
2003 2454 }
2004 2455
2005 2456 $short_dates_content = implode( '', $short_dates_content_arr );
2006 2457
@@ -2021,8 +2472,9 @@
2021 2472 function wpbc_get_formated_dates__wide( $dates_arr, $is_approved = false, $dates_type_id_arr = array(), $booking_resources_arr = array(), $attr = array() ) {
2022 2473
2023 2474 $defaults = array(
2024 2475 'date_html_tag' => 'a',
2476 + 'show_child_resource_in_dates' => true,
2025 2477 );
2026 2478 $params = wp_parse_args( $attr, $defaults );
2027 2479
2028 2480 $wide_dates_arr = array();
@@ -2047,8 +2499,9 @@
2047 2499
2048 2500 // BL
2049 2501 if (
2050 2502 ( class_exists( 'wpdev_bk_biz_l' ) )
2503 + && ( $params['show_child_resource_in_dates'] )
2051 2504 && ( '' != $dates_type_id_arr[ $date_number ] )
2052 2505 && ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
2053 2506 ){
2054 2507 $resource_title = ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
@@ -2181,9 +2634,9 @@
2181 2634 [cost_hint] => &amp;#36;95
2182 2635 [rangetime] => 10:00 AM - 12:00 PM
2183 2636 [name] => test
2184 2637 [email] => [email protected]
2185 - ...
2638 + ...
2186 2639 )
2187 2640
2188 2641 * @param array $booking_system_arr array of system fields from DB
2189 2642 Array ( [booking_id] => 188
@@ -2194,9 +2647,9 @@
2194 2647 [pay_request] => 0
2195 2648 [id] => 188
2196 2649 [approved] => 0
2197 2650 )
2198 -
2651 +
2199 2652 * @param array $system_keys_arr system fields keys that need to be added, like this:
2200 2653 Array ( booking_id, trash, sync_gid, is_new, status
2201 2654 , sort_date, modification_date, hash, booking_type
2202 2655 , remark, cost, pay_status, pay_request, id, approved )
@@ -2323,54 +2776,26 @@
2323 2776 if ( isset( $wpbc__form_show_cache[ $cache_key ] ) ) {
2324 2777 return $wpbc__form_show_cache[ $cache_key ];
2325 2778 }
2326 2779
2327 - // ------------------------------------------------------------
2328 - // Legacy resolution (keep exactly as before).
2329 - // ------------------------------------------------------------
2330 - if ( ! class_exists( 'wpdev_bk_personal' ) ) {
2780 + if ( '' === $custom_booking_form_name ) {
2781 + $default_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', 'standard', $resource_id );
2782 + if ( ! empty( $default_form_name ) ) {
2783 + $my_booking_form_name = $default_form_name;
2784 + }
2785 + }
2786 +
2787 + $booking_form_show = '';
2788 +
2789 + if ( class_exists( 'WPBC_FE_Form_Source_Resolver' ) && class_exists( 'WPBC_BFB_Form_Loader' ) ) {
2331 2790
2332 - $booking_form_show = wpbc_simple_form__get_form_show__as_shortcodes();
2333 - $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $booking_form_show );
2334 -
2335 - } else {
2336 -
2337 - $booking_form_show = get_bk_option( 'booking_form_show' );
2338 - $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $booking_form_show );
2339 -
2340 - // BM / MU legacy forms logic.
2341 - if ( class_exists( 'wpdev_bk_biz_m' ) ) {
2342 -
2343 - if ( '' !== $custom_booking_form_name ) { // FixIn: 9.4.3.12.
2344 - $booking_form_show = apply_bk_filter( 'wpdev_get_booking_form_content', $booking_form_show, $custom_booking_form_name );
2345 - $my_booking_form_name = $custom_booking_form_name;
2346 - } else {
2347 - // BM :: Get default Custom Form of Resource
2348 - $my_booking_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', 'standard', $resource_id );
2349 - if ( ( 'standard' !== $my_booking_form_name ) && ( '' !== $my_booking_form_name ) ) {
2350 - $booking_form_show = apply_bk_filter( 'wpdev_get_booking_form_content', $booking_form_show, $my_booking_form_name );
2351 - }
2352 - }
2353 -
2354 - // MU :: if resource belongs to Regular User -> load THAT owner's form (not logged-in user).
2355 - $booking_form_show = apply_bk_filter( 'wpbc_multiuser_get_booking_form_show_of_regular_user', $booking_form_show, $resource_id, $my_booking_form_name ); // FixIn: 8.1.3.19.
2356 - }
2357 - }
2358 -
2359 - // ------------------------------------------------------------
2360 - // NEW: BFB resolver override (must be AFTER BM/MU legacy resolution).
2361 - // This ensures BFB "content_form" wins and legacy doesn't clobber it.
2362 - // ------------------------------------------------------------
2363 - if ( class_exists( 'WPBC_FE_Form_Source_Resolver' ) && class_exists( 'WPBC_BFB_Form_Loader' ) ) {
2364 -
2365 2791 $req = array(
2366 2792 'resource_id' => (int) $resource_id,
2367 2793 'form_slug' => (string) $my_booking_form_name,
2368 2794 'form_status' => $form_status,
2369 2795 'custom_params' => array(),
2370 - 'legacy_instance' => null,
2371 - 'ctx' => ( is_array( $ctx ) ? $ctx : array() ),
2372 - );
2796 + 'ctx' => ( is_array( $ctx ) ? $ctx : array() ),
2797 + );
2373 2798
2374 2799 $resolved = WPBC_FE_Form_Source_Resolver::resolve( $req );
2375 2800
2376 2801 // If preview requested but not found, try published as fallback.
@@ -2396,13 +2821,12 @@
2396 2821 $content_form = (string) $bfb_pair['content'];
2397 2822 }
2398 2823
2399 2824 if ( '' !== trim( $content_form ) ) {
2400 - // Keep legacy behavior: custom html shortcodes.
2401 - $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $content_form );
2402 - }
2403 - }
2404 - }
2825 + $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $content_form );
2826 + }
2827 + }
2828 + }
2405 2829
2406 2830 // ------------------------------------------------------------
2407 2831 // Language + cleanup (keep old behavior).
2408 2832 // ------------------------------------------------------------
@@ -2705,5 +3129,5 @@
2705 3129 die( '<strong>Error!</strong> Probably nonce for this page has been expired. Please <a href="javascript:void(0)" onclick="javascript:location.reload();">reload the page</a>.' );
2706 3130 }
2707 3131 }
2708 3132 add_action( 'check_ajax_referer', 'wpbc_check_ajax_referer__for_booking_listing', 2, 10 );
2709 -// </editor-fold>
3133 +// </editor-fold>