__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
<?php

if ( ! defined( 'ABSPATH' ) ) exit;                                             // Exit if accessed directly            // FixIn: 9.8.0.4.


// <editor-fold     defaultstate="collapsed"                        desc="  ==  SQL - Get Dates array from DB  ==  "  >

	// -----------------------------------------------------------------------------------------------------------------
	// SQL - Get Dates array from DB
	// -----------------------------------------------------------------------------------------------------------------

	/**
	 * Get SQL dates array from DB as:   [   [0] => std_object( booking_date:'2023-08-08 10:00:01', approved:0, booking_id:45, type:1 ... ),  [1] => std_object( ), ... ]
	 *
	 * @param array $params   =   array(
				                      'approved'            => 'all' | 0 | 1                      default 'all'
								    , 'resource_id'         => array, CSD, int                   if empty then default '1'
								    , 'additional_bk_types' => array, CSD, int      OPTIONAL               default array()
								    , 'skip_booking_id'     => CSD                                default ''
				                )
	 *
	 * @return array            Array (  [0] => stdClass Object (   [booking_date] => 2023-08-08 10:00:01
														            [approved] => 0
														            [date_res_type] =>
														            [booking_id] => 45
														            [form] => selectbox-one^rangetime2^10:00 - 12:00~text^selected_short_dates_hint2^...
														            [parent] => 0
														            [prioritet] => 20
														            [type] => 2
														        )
									    [1] => stdClass Object (
														            [booking_date] => 2023-08-08 10:00:01
														            [approved] => 0
														            [date_res_type] =>
														            [booking_id] => 46
														            [form] => selectbox-one^rangetime10^10:00 - 12:00~text^selected_short_dates_hint10^...
														            [parent] => 2
														            [prioritet] => 1
														            [type] => 10
														        ), ...
	 *
	 *
	 * Example:

			$sql_dates_params = array(
								  'approved'        => ( ( 'On' == get_bk_option( 'booking_is_show_pending_days_as_available' ) ) ? '1' : 'all' )
								, 'resource_id'     => $type_id
								, 'skip_booking_id' => wpbc_get_booking_id__from_hash_in_url() 								// int | ''		// Booking IDs  to skip getting from DB
							);
			$dates_approve = wpbc__sql__get_booking_dates( $sql_dates_params );

	 */
	function wpbc__sql__get_booking_dates( $params  ){

		//TODO:  think about pre-caching SQL request for all  booking resources - useful  for [bookingselect  shortcode ...]          $params['resource_id'] = implode(',',range(1,17));

		// <editor-fold     defaultstate="collapsed"                        desc=" = CACHE - GET    ::    check if such request was cached and get it = "  >

		$params_for_cache = maybe_serialize( $params );
		$cache_result = wpbc_cache__get( 'wpbc__sql__get_booking_dates', $params_for_cache );
		if ( ! is_null( $cache_result ) ) {
			return $cache_result;
		}

		// </editor-fold>

		global $wpdb;

	    $defaults = array(
			              'dates_to_check'      => 'CURDATE'                                    //  'CURDATE'  |  'ALL'  |  [ '2023-07-15' , '2023-07-21' ]
	                    , 'approved'            => 'all'            // 'all' | 0 | 1
					    , 'resource_id'         => ''               // INT
					    , 'additional_bk_types' => array()          // arrays only
					    , 'skip_booking_id'     => ''               // CSD              '3,5'
		                , 'as_single_resource'  => false            // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'
	                );
	    $params   = wp_parse_args( $params, $defaults );


		// Convert $params['additional_bk_types']  and $params['resource_id'] to  one CSD variable   or default '1' if all empty
		$resource_id__arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'], $params['additional_bk_types'] );
		$resource_id__csd = implode( ',', $resource_id__arr );

		// S a n i t i z e
		$resource_id__csd          = wpbc_sanitize_digit_or_csd( $resource_id__csd );
		$params['skip_booking_id'] = wpbc_sanitize_digit_or_csd( $params['skip_booking_id'] );
		$params['approved']        = ( 'all' == $params['approved'] ) ? 'all' : intval( $params['approved'] );


		$sql_trash_bookings    = ' AND bk.trash != 1 ';
		$sql_skip_bookings     = (    '' == $params['skip_booking_id'] ) ? '' : " AND dt.booking_id NOT IN ( {$params['skip_booking_id']} ) ";
		$sql_approved_bookings = ( 'all' == $params['approved'] )        ? '' : " AND dt.approved = {$params['approved']} ";

		$or__sql_child_bookings_4_parent = ( ! $params['as_single_resource'] ) ? " OR bt.parent  IN ( {$resource_id__csd} ) " : '' ;

		$where_dates = wpbc_get__sql_where__for__dates( $params );

		/**
		 * Description:
		 *              OR dt.type_id IN ( {$resource_id__csd} )
		 *                                                          It is means that sometimes bookings can be started in one booking resource,
		 *                                                          and in future dates can be finished in other 'child' booking resource(s).
		 *                                                          It's possible,  when 'main' booking resource,  where booking was started
		 *                                                          has future dates as 'unavailable' or booked
		 *
		 *              OR dt.type_id IN ( {$resource_id__csd} )
		 *                                                          It's means that this booking belong to child booking resource, and do not belong to parent booking resource!
		 */

		if (  class_exists('wpdev_bk_biz_l') ) {

					$my_sql =  "SELECT DISTINCT dt.booking_date, dt.approved, dt.type_id as date_res_type, dt.booking_id, bk.form, bt.parent, bt.prioritet, bt.booking_type_id as type  
				                FROM {$wpdb->prefix}bookingdates as dt 
				
				                    INNER JOIN {$wpdb->prefix}booking as bk  
				                    ON    bk.booking_id = dt.booking_id 
				                    
										INNER JOIN {$wpdb->prefix}bookingtypes as bt  
										ON    bk.booking_type = bt.booking_type_id 
				
				                WHERE 1 = 1       
										{$where_dates} 
										AND (
										           bk.booking_type IN ( {$resource_id__csd} ) 
										        OR dt.type_id IN ( {$resource_id__csd} )        
												{$or__sql_child_bookings_4_parent}
					                        )                       
										{$sql_approved_bookings} 
										{$sql_trash_bookings} 
										{$sql_skip_bookings} 
				                ORDER BY dt.booking_date";

					// Explanation:
					// OR bt.parent  IN ( ... ) -> Bookings from CHILD booking resources
					// OR dt.type_id IN ( ... ) -> Dates from other booking resources, which belong to this booking resource

		} else if ( class_exists('wpdev_bk_biz_m') ) {  // Here we get  form  for booking details.

			$my_sql =  "SELECT DISTINCT dt.booking_date, dt.approved, dt.booking_id, bk.booking_type as type, bk.form 
		                FROM {$wpdb->prefix}bookingdates as dt 
		
		                    INNER JOIN {$wpdb->prefix}booking as bk  
		                    ON    bk.booking_id = dt.booking_id  
		
		                WHERE 1 = 1       
								{$where_dates} 
								AND bk.booking_type IN ( {$resource_id__csd} )                       
								{$sql_approved_bookings} 
								{$sql_trash_bookings} 
								{$sql_skip_bookings} 
		                ORDER BY dt.booking_date";

		} else {                                      // Fast request  only  for dates
			$my_sql =  "SELECT DISTINCT dt.booking_date, dt.approved, dt.booking_id, bk.booking_type as type  
		                FROM {$wpdb->prefix}bookingdates as dt 
		
		                    INNER JOIN {$wpdb->prefix}booking as bk  
		                    ON    bk.booking_id = dt.booking_id  
		
		                WHERE 1 = 1       
								{$where_dates} 
								AND bk.booking_type IN ( {$resource_id__csd} )                       
								{$sql_approved_bookings} 
								{$sql_trash_bookings} 
								{$sql_skip_bookings} 
		                ORDER BY dt.booking_date";
		}



		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
		$sql__dates_obj__arr = $wpdb->get_results( $my_sql );


		// <editor-fold     defaultstate="collapsed"                        desc=" = CACHE - SAVE :: = "  >
		$cache_result = wpbc_cache__save( 'wpbc__sql__get_booking_dates', $params_for_cache, $sql__dates_obj__arr );
		// </editor-fold>

		return $sql__dates_obj__arr;
	}


			/**
			 * Get SQL WHERE condition for Dates
			 *
			 * @param array $params     [ 'dates_to_check' => 'CURDATE' ]   |   [ 'dates_to_check' => 'ALL' ]   |   [ 'dates_to_check' => [ '2023-07-15' , '2023-07-21' ]  ]
			 *
			 * @return string           ' AND (  dt.booking_date >= C URDATE()  ) '
			 */
			function wpbc_get__sql_where__for__dates( $params ){

			    $defaults = array(
					              'dates_to_check' => 'CURDATE'        //  'CURDATE'  |  'ALL'  |  [ '2023-07-15' , '2023-07-21' ]
			                );
			    $params   = wp_parse_args( $params, $defaults );


				if ( 'ALL' == $params['dates_to_check'] ) {                                                             // All  dates           ->   ''

					return   '';

				} else if ( 'CURDATE' == $params['dates_to_check'] ) {                                                  // Current dates        ->   CURDATE

					return   ' AND (  dt.booking_date >= ' . wpbc_sql_date_math_expr_explicit('', 'curdate') . '  ) ' ;

				} else if ( is_array( $params['dates_to_check'] ) ) {                                                   // Specific Date(s)     ->   [ '2023-07-15' , '2023-07-21' ]

					$dates_sql_array = array();

					for( $i = 0; $i <  count( $params['dates_to_check'] ); $i++) {

						$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'  ) )";
					}

					$dates_sql_str = implode( ' OR ', $dates_sql_array );

					return   " AND (  {$dates_sql_str}  ) " ;

				}

				// Default CURDATE
				return ' AND (  dt.booking_date >= ' . wpbc_sql_date_math_expr_explicit('', 'curdate') . '  ) ';
			}



	/**
	 * Get array of "Booked Dates" as:   ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
	 *
	 * @param array $params   array(
	 *				                      'approved'            => 'all'                        // 'all' | 0 | 1
	 *								    , 'resource_id'         => '1'                          // arrays | CSD | int
	 *								    , 'additional_bk_types' => array()     OPTIONAL         // arrays | CSD | int
	 *								    , 'skip_booking_id'     => '' 		                    // CSD              '3,5'
	 *				                )
	 *
	 * @return array        [  [2023-08-09]: [  [3]: [  '43211 - 86392': object(  'booking_date' => 2023-08-09 12:00:01 ... ), ... ], ... ], [2023-08-10]:  ...  ]
	 *
	 *    Explanation:
	 *                         [2023-08-09]: [
	 *										    [3]: [
	 *													'43211 - 86392': object(
	 *																			[booking_date] => 2023-08-09 12:00:01
	 *																			[approved] => 0
	 *																			[date_res_type] =>
	 *																			[booking_id] => 65
	 *																			[form] => text^selected_short_dates_hint3^August 10...
	 *																			[parent] => 0
	 *																			[prioritet] => 30
	 *																			[type] => 3
	 *                                                                          [__summary__booking] : [
	 *
	 *							                                                        [sql__booking_dates__arr] : [
	 *																								                    [1691668811] => 2023-08-10 12:00:01
	 *																								                    [1691675992] => 2023-08-10 14:00:02
	 *																							                    ]
	 *							                                                        [__dates_obj] => WPBC_BOOKING_DATE Object(
	 *																											[readable_dates]: [   '2023-08-10': [ 12:00:01 - 14:00:02 ]   ]
	 *																											[is_debug] => 0
	 *																										)
	 *							                                                        [__dates_obj__bm__extended] => WPBC_BOOKING_DATE_EXTENDED Object (
	 *																															[readable_dates] : [
	 *																																				[2023-08-09] : [ 12:00:01 - 24:00:00 ]
	 *																																				[2023-08-10] : [ 00:00:00 - 24:00:00 ]
	 *																																				[2023-08-11] : [ 00:00:00 - 24:00:00 ]
	 *																																				[2023-08-12] : [ 00:00:00 - 24:00:00 ]
	 *																																				[2023-08-13] : [ 00:00:00 - 14:00:02 ]
	 *																																			]
	 *																															[is_debug] => 0
	 *																															[extended_dates_times_arr] : []
	 *																															[debug_dates_times_arr] : []
	 *																														)
	 *							                                                        [sql__booking_dates__arr__extended] : 	[
	 *																											[1691582401] => 2023-08-09 12:00:01
	 *																											[1691625600] => 2023-08-10 00:00:00
	 *																											[1691712000] => 2023-08-11 00:00:00
	 *																											[1691798400] => 2023-08-12 00:00:00
	 *																											[1691935202] => 2023-08-13 14:00:02
	 *																										]
	 *
	 *																									]
	 *							                                            )
	 *													'64811 - 86392': object(
	 *							                            [booking_date] => 2023-08-09 18:00:01
	 *							                            [approved] => 0
	 *							                            [date_res_type] =>
	 *							                            [booking_id] => 66
	 *														....
	 *							                        )
	 *
	 *							                ]
	 *
	 *										  ]
	 *
	 *							[2023-08-10]: [ ... ]
	 *							...
	 *
	 *     Example 1:
	 *                  $booked_dates__per_resources__arr = wpbc_get__booked_dates__per_resources__arr( array( 'resource_id' => $type_id ) );
	 *     Example 2:
	 *                  $booked_dates__per_resources__arr = wpbc_get__booked_dates__per_resources__arr(
	 * 																			                      'approved'            => 'all'        // 'all' | 0 | 1
	 * 																							    , 'resource_id'         => '1'          // arrays | CSD | int
	 * 																							    , 'additional_bk_types' => array()      // arrays | CSD | int
	 * 																							    , 'skip_booking_id'     => '' 		    // int | ''             // CSD
	 * 																			                );
	 *
	 *
	 *
	 *
	 *      $booked_dates__resources__seconds__arr[ '2023-08-08' ][ 'resource_id' ][ 'time_seconds_range' ] =  Booking Date Object()
	 *
	 *      Seconds:    [36011 - 43192] -  [start_time_second - end_time_second]
	 *      Seconds:    [0]             -  FULL DAY Booking
	 *
	 *      Day start at   ( 10 + 1 )                      second
	 *      Day End at     ( ( 24 * 60 * 60 ) - 10 + 2 )   second
	 *
	 *      To prevent intersections:
	 *          Each  booking Start time has    +10 seconds
	 *          Each  booking End   time has    -10 seconds
	 *      So real time here [36011 - 43192]  is   [ 36001 - 43202 ]
	 *
	 *      Full day booking end with       0
	 *      Start time booking end with     1
	 *      End time booking end with       2
	 */
	function wpbc_get__booked_dates__per_resources__arr( $params ){

	    $defaults = array(
						  'dates_to_check'      => 'CURDATE'                                    //  'CURDATE'  |  'ALL'  |  [ '2023-07-15' , '2023-07-21' ]
	                    , 'approved'            => ( ( get_bk_option( 'booking_is_show_pending_days_as_available' ) == 'On' ) ? '1' : 'all' )             // 'all' | 0 | 1
					    , 'resource_id'         => '1'                                          // arrays | CSD | int
					    , 'additional_bk_types' => array()                                      // arrays | CSD | int       // OPTIONAL
					    , 'skip_booking_id'     => wpbc_get_booking_id__from_hash_in_url() 		// int | ''                 // CSD         '3,5'
	                    , 'as_single_resource'  => false                                        // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'
	                    , 'is_days_always_available' => ( ( 'On' == get_bk_option( 'booking_is_days_always_available' ) ) ? true : false )

		                , 'aggregate_params' => array()  //Optional.  It can contain: [   'aggregate_resource_id_arr' =>  [ 4 ] , 'resource_id__with_children__arr' => [3,25] ]
	                );
		$params_for_dates = wp_parse_args( $params, $defaults );


		// $params_for_dates['is_days_always_available'] = in_array( $params_for_dates['resource_id'], array( '1' ) );  // Set some resources as always avavailable.

		if ( $params_for_dates['is_days_always_available'] ) {          // All  bookings showing as available dates.
			return array();
		}


		/**
		 * 1. SQL - get array of all  booked dates for our booking resource(s):     [   [0] => date_object{ [booking_date] => 2023-08-08 10:00:01, [approved] => 0, .. },  ..   ]
		 *
		 * Example:   [
		                [0] => stdClass Object (    [booking_date] => 2023-08-08 10:00:01
										            [approved] => 0
										            [date_res_type] =>
										            [booking_id] => 45
										            [form] => selectbox-one^rangetime2^10:00 - 12:00~text^selected_short_dates_hint2^...
										            [parent] => 0
										            [prioritet] => 20
										            [type] => 2
										        )
					    [1] => stdClass Object (
										            [booking_date] => 2023-08-08 10:00:01
										            [approved] => 0
										            [date_res_type] =>
										            [booking_id] => 46
										            [form] => selectbox-one^rangetime10^10:00 - 12:00~text^selected_short_dates_hint10^...
										            [parent] => 2
										            [prioritet] => 1
										            [type] => 10
										        ), ...
					  ]
		 */
		$sql__b_dates__arr = wpbc__sql__get_booking_dates( $params_for_dates );


		/**
		 * 2. From SQL dates into:          [ > resource_id < ][ > booking_id < ] -> __summary__booking['sql__booking_dates__arr'] = [   [ '>seconds<' ]: '> SQL DATE <' , ...   ]
		 *                                                                                                                              [1693303211]  => 2023-08-29 10:00:01
		 *                                                                                                                              [1693353600]  => 2023-08-30 00:00:00
		 *                                                                                                                              [1693483192]  => 2023-08-31 12:00:02
		 *                                                                                                                           ]
		 */
		$resources__booking_id__obj = wpbc_support__transform__into__resource_booking_dates__arr(
									     array( 'sql_dates_arr' => wpbc_clone_array_of_objects( $sql__b_dates__arr )        , 'is_sort__dates_arr' => true , 'is_apply__check_in_out__10s' => true  ) );


		/**
		 * 2.0 Transfer AGGREGATE resource bookings to Main resources
		 *
		 *
		 */
		if ( ! empty( $params['aggregate_params'] ) ) {
			$resources__booking_id__obj = wpbc_aggregate__merge_bookings__from_aggregate__in_source_resource__arr(
																$resources__booking_id__obj,
																$params['aggregate_params']['resource_id__with_children__arr'],
																$params['aggregate_params']['aggregate_resource_id_arr']
															);
		}


		/**
		 * 2.1 Get                          [ > resource_id < ][ > booking_id < ] -> __summary__booking[ '_readable_dates' ]  =  [    '2023-08-01': [  0: "10:00:01 - 12:00:02" ], ...
		 *                                                                                                                            '2023-08-05': [  0: "10:00:01 - 12:00:02" ], ...
		 *                                                                                                                       ]
		 */
		$resources__booking_id__obj = wpbc__in_all_bookings__create_WPBC_BOOKING_DATE( $resources__booking_id__obj );


		/**
		 *  2.2 Extend check in/out dates   [ > resource_id < ][ > booking_id < ] -> __summary__booking[ 'sql__booking_dates__arr__extended' ]
		 */
		if ( function_exists( 'wpbc__extend_availability__before_after__check_in_out' ) ) {

			$resources__booking_id__obj =  wpbc__extend_availability__before_after__check_in_out( $resources__booking_id__obj );
		}


		/**
		 * 3. Into:      ['2024-01-28'][ > resource_id < ][ > booking_id < ][ > only_time_seconds < ]  => obj(   booking_date: "2024-01-28 10:00:01", ... )
		 *
		 *    From:                    [ > resource_id < ][ > booking_id < ]                           => obj(   booking_date: "2024-01-28 10:00:01",  ['__summary__booking']['sql__booking_dates__arr'][] , ...   )
	     */
		$dt__res__bk__seconds__arr = wpbc_support__transform__into__date_resource_booking_timesec__arr(
												array( 'resource_booking_dates_arr' => $resources__booking_id__obj          , 'is_apply__check_in_out__10s' => true  ) );


		/**
		 * 4. Into:    ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
		 *
		 * , where    'time_seconds_range'    can be: '0' | '36011 - 43192', ...
		 */
		$dt__res__time_seconds_range__arr = wpbc_support__transform__into__date_resource_timesec_range__arr(
												array( 'date_resource_booking_timesec_arr' => $dt__res__bk__seconds__arr    , 'is_apply__check_in_out__10s' => true  ) );

		return $dt__res__time_seconds_range__arr;
	}

// </editor-fold>


// -----------------------------------------------------------------------------------------------------------------
//  Get Resource array filled by booked Dates
// -----------------------------------------------------------------------------------------------------------------


/**
 * Get all dates STATUSES as:   ['2023-08-30'][ 'summary']['status_for_day':'available', 'day_availability':3, [ > resource_id < ] => std_object( '_day_status':'full_day_booking', '__booked__times__details':[ '1 - 43192': std_object( booking_id:46, 'approved':0, ... ), '50300 - 63192': ], 'is_day_unavailable':1, ...
 *
 * @param int $single_or_parent__resource_id            // 1   --- INT (currently  it's works only  for one resource (single or parent)
 * array $params[ 'timeslots_to_check_intersect' ]           // [ '10:00 - 12:00' ] if bookings intersect with all time slots in array, then the date unavailable, if empty array then it's skipped
 *
 * @return array        {
 *							 calendar_2: {
 *											 id: 2
 *											 dates: { "2023-07-21": {…}
 *													  "2023-07-22": {
 *																		 ['summary']['status_for_bookings']: "pending"
 *																		 ['summary']['status_for_day']: "available"
 *																		 day_availability: 4
 *																		 max_capacity: 4
 *																		 statuses: Object { day: "check_in|check_in|available|available", bookings: "approved|pending||" }
 *
 * 2:  Object { is_day_unavailable: false, _day_status: "check_in", check_in_out: "check_in", … }
 *																		 10: Object { is_day_unavailable: false, _day_status: "check_in", check_in_out: "check_in", … }
 *																		 11: Object { is_day_unavailable: false, _day_status: "available", pending_approved: [] }
 *																		 12: Object { is_day_unavailable: false, _day_status: "available", pending_approved: [] }
 *                                                                  }
 *                                                  , "2023-07-23": {…}
 *                                                  , …
 *                                             }
 *                                   }
 *							calendar_5: {...}
 *                          , ...
 *                      }
 *
 *
 * Important Dates properties:
 *
		                        * ['summary']['status_for_bookings']:  "" | "pending" | "approved"
								* ['summary']['status_for_day']:     | 'available';
														* | 'time_slots_booking';
														* | 'full_day_booking';
														* | 'season_filter';
														* | 'resource_availability';
                                                        * | 'weekday_unavailable';  'from_today_unavailable' | 'limit_available_from_today'
														* | 'change_over';
														* | 'check_in';
														* | 'check_out';
														* | 'change_over check_out' .... variations....
 *
 *
 * @return array  array(
					'dates'                       => $availability_per_day              like ['2023-08-17'] = ...
				  , 'resources_id_arr__in_dates'  => $source__resource_id_arr                   like [ 1,10,11,12,14]
		    )
 */
function wpbc_get_availability_per_days_arr( $params ) {

	if ( 0 ) {      // FixIn: 9.8.3.1 ?
		wpbc_set_limit_php( 300 );      // Set 300 seconds for php execution.
	}

	$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 */
	$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 */

	$defaults = array(
		'dates_to_check'               => 'CURDATE',                                          // v:   'CURDATE'  |  'ALL'  |    arr:  '2023-07-15' , '2023-07-21'.
		'approved'                     => ( ( 'On' === get_bk_option( 'booking_is_show_pending_days_as_available' ) ) ? '1' : 'all' ),   // v:  'all' | 0 | 1.
		'resource_id'                  => '1',                                                                          // Single or parent booking resource!!!!  // arrays | CSD | int ???.
		'additional_bk_types'          => array(),                   // arrays | CSD | int // OPTIONAL -> aggregate_resource_id_arr ... it is array of booking resources from aggregate shortcode parameter.
		'skip_booking_id'              => wpbc_get_booking_id__from_hash_in_url(),                                      // int | '' // CSD  '3,5'.
		'as_single_resource'           => false,                                              // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'.
		'max_days_count'               => wpbc_get_max_visible_days_in_calendar(),            // 365.
		'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.
		'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.
		'custom_form'                  => '',                                                 // Required for checking all available time-slots and compare with  booked time slots.
	);

	$params = wp_parse_args( $params, $defaults );

	// FixIn: 10.7.1.2. //FixIn: 10.10.3.2.
	if (
		( false !== strpos( $params['request_uri'], 'allow_past' ) ) ||
		(
			( false !== strpos( $params['request_uri'], 'page=wpbc-new' ) ) &&
			( false !== strpos( $params['request_uri'], 'booking_hash' ) )
		)
	) {
		$params['dates_to_check'] = 'ALL';
	}

	// -----------------------------------------------------------------------------------------------------------------
	// R e s o u r c e (s)    D a t a
	// -----------------------------------------------------------------------------------------------------------------
	// Get array  of booking resource ID    [1, 13, 8, 6, 7]   or  default:     [ 1 ]
	$source__resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'] );                             // [1, 13, 8, 6, 7]
	//$source__resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'], $params['additional_bk_types'] );                             // [1, 13, 8, 6, 7]
	$first_resource_id = $source__resource_id_arr[0];                                                                           // First from  the list,  or 1 if not provided.

	// Get here Obj. of booking resource (which can include CHILD booking resources)
	$resources_obj = new WPBC_RESOURCE_SUPPORT( array(
									                  'resource_id'        => $source__resource_id_arr,                         //CSD | D
													  'as_single_resource' => $params['as_single_resource']             // If true,  then  skip child booking resources
											));
	// Resource ID arr (Can be Parent and Child resource ID)
	$resource_id__with_children__arr = $resources_obj->get_resource_id_arr();                                       // [ 2, 10, 11, 12 ]

	// Get Maximum capacity of resource
	$resource_obj = $resources_obj->get__booking_resource_obj( $first_resource_id );
	$max_resource_capacity_int = empty( $resource_obj ) ? 1 : $resource_obj->capacity;                                           // 1 | 4

	// Get base cost of resource
	$resource_base_cost = $resources_obj->get_resources_base_cost_arr();                            // [ 0, 25, 100, 99]




	// -----------------------------------------------------------------------------------------------------------------
	//	Get real AGGREGATE resource ID arr
	// -----------------------------------------------------------------------------------------------------------------
	$real_resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'] );                       // [ 1 ]
	if ( empty( $params['additional_bk_types'] ) ) {
		$aggregate_resource_id_arr = array();
	} else {
		$aggregate_resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['additional_bk_types'] );               // [1, 13, 8, 6, 7]
	}
	// Excluding from 'additional_bk_types'  all  resources in 'resource_id'
	$aggregate_resource_id_arr = array_diff( $aggregate_resource_id_arr, $real_resource_id_arr );                       // [ 13, 8, 6, 7 ]
	$aggregate_resource_id_arr = array_values( $aggregate_resource_id_arr );                                            // reindex array,  for ability to  transfer array  instead of obj to JS client side.

	$params['aggregate_params'] = array(
										'aggregate_resource_id_arr'       => $aggregate_resource_id_arr,
										'resource_id__with_children__arr' => $resource_id__with_children__arr
									);

	// -----------------------------------------------------------------------------------------------------------------
	// B o o k i n g s
	// -----------------------------------------------------------------------------------------------------------------
	// Main function to get "Bookings":   ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
	$bookings__in_dates = wpbc_get__booked_dates__per_resources__arr( $params );



	// -----------------------------------------------------------------------------------------------------------------
	// Booking > Availability page
	// -----------------------------------------------------------------------------------------------------------------
	$search_dates = $params['dates_to_check'];    // 'CURDATE' | 'ALL' |  [ "2023-08-03" , "2023-08-04" , "2023-08-05" ]

	//FixIn: 9.8.15.10  Aggregate or not Aggregate Booking > Availability ?     aggregate_type = 'all' | 'bookings_only'
	if ( ( ! empty( $params['aggregate_type'] ) ) && ( 'bookings_only' === $params['aggregate_type'] ) ) {              // FixIn: 9.9.0.16.
		$unavailable_dates__per_resources__arr = wpbc_for_resources_arr__get_unavailable_dates(
																$resource_id__with_children__arr,                       // Only One Primary Resource !!
																$search_dates
														);    // [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
	} else {
		$unavailable_dates__per_resources__arr = wpbc_for_resources_arr__get_unavailable_dates(
														wpbc_get_unique_array_of_resources_id( $resource_id__with_children__arr, $aggregate_resource_id_arr ),      // Get  unavailable dates for primary  and aggregate booking resources
														$search_dates
													);    // [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
	}
	$unavailable_dates__per_resources__arr = wpbc_aggregate_merge_availability( $unavailable_dates__per_resources__arr,
																				$resource_id__with_children__arr,
																				$aggregate_resource_id_arr );

	// -----------------------------------------------------------------------------------------------------------------
	// Booking > Resources > Availability page
	// -----------------------------------------------------------------------------------------------------------------
    $season_filters_availability = array();
	if ( class_exists('wpdev_bk_biz_m') ) {
		foreach ( $resource_id__with_children__arr as $resource_id_for_season ) {
			$season_filters_availability[ $resource_id_for_season ] = apply_bk_filter( 'get_available_days', $resource_id_for_season );
		}
	}




	// -----------------------------------------------------------------------------------------------------------------
	//   P a r a m e t e r s    f o r    L O O P
	// -----------------------------------------------------------------------------------------------------------------

	// - Is this Booking > Add booking page ? --------------------------------------------------------------------------
	$is_this_bap_page  = ( false !== strpos( $params['request_uri'], 'page=wpbc-new' ) ) ? true : false;
	$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

	// FixIn: 10.7.1.2.
	if ( ! $is_this_hash_page ) {
		$is_this_hash_page = ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ? true : false;
	}

	if ( ( $is_this_bap_page ) && ( $is_this_hash_page ) ) {        // Start  days in calendar  from        = PAST
		$params['dates_to_check'] = 'ALL';
	}

	if ( 'ALL' == $params['dates_to_check'] ) {                                                                         // All  dates           ->   ''

		$start_day_number     = - 1 * $params['max_days_count'];
		//$today_inix_timestamp = strtotime( '-' . intval( $params['max_days_count'] ) . ' days' );                       // - 300 days

		// Get time, relative to Timezone from WordPress  > Settings General page   // FixIn: 9.9.0.17.
		$start_date_unix       = strtotime( '-' . intval( $params['max_days_count'] ) . ' days' );                     // - 365 days
		$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' );
		$today_inix_timestamp  = strtotime( $date_with_wp_timezone );

	} else if ( 'CURDATE' == $params['dates_to_check'] ) {                                                              // Current dates        ->   CURDATE

		$start_day_number     = 1;
		// $today_inix_timestamp = strtotime( gmdate( 'Y-m-d 00:00:00', strtotime( 'now' ) ) );                              // Today 00:00:00

		// Get time, relative to Timezone from WordPress  > Settings General page   // FixIn: 9.9.0.17.
		$start_date_unix        = strtotime( 'now' );
		$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' );
		$today_inix_timestamp = strtotime( $date_with_wp_timezone );

	} else if ( is_array( $params['dates_to_check'] ) ) {

		$start_day_number = 1;

		$today_inix_timestamp = strtotime( $params['dates_to_check'][0] . ' 00:00:00' );                                // '2023-09-03 00:00:00'

		$dif_in_days =   strtotime( $params['dates_to_check'][ ( count( $params['dates_to_check'] ) - 1 ) ] . ' 00:00:00' )
		               - strtotime( $params['dates_to_check'][0] . ' 00:00:00' );

		$dif_in_days = $dif_in_days / ( 24 * 60 * 60 );
		$params['max_days_count'] = ceil( $dif_in_days ) + 1;
	}


	// Get Time Slots from booking form for Each date:      [   '2023-10-25' => [ '12:20 - 12:55', '13:00 - 14:00' ],         '2023-10-26' => [ ... ], ...   ]
	$readable_timeslots_arr__in_dates_arr__to_check_intersect = wpbc_get_times_fields_configuration__by_dates(
													$first_resource_id,                                     // Resource ID (used in case of MultiUser version for getting specific form  for regular  users)
													$params['custom_form'],                                 // Form  name for getting time slots configuration
													$today_inix_timestamp,                                  // start_date_unix_timestamp
													( $params['max_days_count'] - $start_day_number )       // days_count
												);

	// =================================================================================================================
	// --  Here are GO
	// =================================================================================================================
	$availability_per_day = array();

	for ( $day_num = $start_day_number; $day_num <= $params['max_days_count']; $day_num ++ ) {

		$my_day_tag = gmdate( 'Y-m-d', $today_inix_timestamp );                                   // '2023-07-19'


		//--------------------------------------------------------------------------------------------------------------
		// 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
		$as_seconds_timeslots_arr__to_check_intersect = wpbc_get__time_range_in_seconds_arr__for_date( $readable_timeslots_arr__in_dates_arr__to_check_intersect, $my_day_tag );
		/*
		// TODO: check this, if it's required ?  // If empty,  maybe get  default 'timeslots_to_check_intersect' from  root of this function  parameters ????
		if ( empty( $as_seconds_timeslots_arr__to_check_intersect ) ) {


			if ( ! is_array( $params[ 'timeslots_to_check_intersect' ] ) ) {            // Root parameters from  this function
				$params[ 'timeslots_to_check_intersect' ] = array( $params[ 'timeslots_to_check_intersect' ] );
			}

			$as_seconds_timeslots_arr__to_check_intersect = array();
			foreach ( $params[ 'timeslots_to_check_intersect' ] as $time_slot_readable ) {
				$as_seconds_timeslots_arr__to_check_intersect[] = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $time_slot_readable );
			}
		}
		*/
		//--------------------------------------------------------------------------------------------------------------


		$availability_per_day[ $my_day_tag ] = array();

		// Helpful tip. Definition here variables in such  order, useful for having such  order in _wpbc JS variable for showing it with _wpbc.bookings_in_calendars__get_all(); command
		$availability_per_day[ $my_day_tag ]['day_availability'] = $max_resource_capacity_int;          // 4
		$availability_per_day[ $my_day_tag ]['max_capacity']     = $max_resource_capacity_int;          // 4
		$availability_per_day[ $my_day_tag ]['statuses']         = array();
		$availability_per_day[ $my_day_tag ]['statuses']['day_status']      = array();                  // per each child booking resource
		$availability_per_day[ $my_day_tag ]['statuses']['bookings_status'] = array();                  // per each child booking resource
		$availability_per_day[ $my_day_tag ]['summary'] = array();
		$availability_per_day[ $my_day_tag ]['summary']['status_for_day']       = '';                   // available | time_slots_booking | full_day_booking | ...
		$availability_per_day[ $my_day_tag ]['summary']['status_for_bookings']  = '';                   // pending   |  approved   | CO:   pending_pending  |  pending_approved  |   approved_pending  |   approved_approved
		$availability_per_day[ $my_day_tag ]['summary']['tooltip_times']        = '';
		$availability_per_day[ $my_day_tag ]['summary']['tooltip_availability'] = '';
		$availability_per_day[ $my_day_tag ]['summary']['tooltip_day_cost']     = '';
		$availability_per_day[ $my_day_tag ]['summary']['tooltip_booking_details']     = '';


		// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		// R E S O U R C E S   -   S t a r t
		// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		foreach ( $resource_id__with_children__arr as $resource_id ) {                  // [1, 13, 8, 6, 7]

			$availability_per_day[ $my_day_tag ][ $resource_id ] = new stdClass();
			$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = false;
			$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'available';
			$availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array();
			$availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips = array(
																					'resource_title' => $resources_obj->get_resource_title( $resource_id ),
																					'times'        => '',
																					'details'      => array()
																				);
			$availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots = array(
																					'in_seconds'      => array(),       // seconds
																					'readable24h'     => array(),       // readable  24H  -  for debug only
																					'merged_seconds'  => array(),       // seconds (reduced number of time_ranges)
																					'merged_readable' => array()        // readable  12AM
																				);
			// Day  Cost / Rates ---------------------------------------------------------------------------------------
			$fin_day_cost = wpbc_support_capacity__get_day_cost( $my_day_tag, $resource_id, $resource_base_cost[ $resource_id ] );
			$availability_per_day[ $my_day_tag ][ $resource_id ]->date_cost_rate = $fin_day_cost;


			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			// B O O K I N G S   -   S t a r t
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

			if (    ( isset( $bookings__in_dates[ $my_day_tag ] ) )
			     && ( isset( $bookings__in_dates[ $my_day_tag ][ $resource_id ] ) )   ){

				$this_date_bookings = $bookings__in_dates[ $my_day_tag ][ $resource_id ];                               // [ [36011 - 86392] => stdClass Object(   [approved] => 1  , ... ) ,... ]
				ksort( $this_date_bookings );
				$availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = $this_date_bookings;

			} else {
				$this_date_bookings = array();
			}


			/**
			 * If bookings exist then:
			 *                          1. Removing some properties here to hide personal details,
			 *                          2. Set Approved / Pending status of the bookings
			 *                          3. By default, set "_day_status" as 'time_slots_booking'  ( later we will change to 'full_day_booking', if applied )
			 */
			if ( ! empty( $this_date_bookings ) ) {

				// =====================================================================================================
				//  T i m e s   -   Start
				// =====================================================================================================
				foreach ( $this_date_bookings as $booked_times__key => $booked_times__value ) {

					// By default, set "_day_status" as 'time_slots_booking'  ( later we will change to 'full_day_booking', if applied )
					$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'time_slots_booking';

					// -------------------------------------------------------------------------------------------------
					// Get Time-Slot
					if ( false === strpos( $booked_times__key, '-' ) ) {                                                // Full day ?   -   0 == $booked_times__key
						$time_range__seconds__arr = array( 0, 86400 );                                                          // 24 * 60 * 60
					} else {
						$time_range__seconds__arr = wpbc_transform_timerange__s_range__in__seconds_arr( $booked_times__key );   // '43211 - 86392'   into   [43211, 86400]
					}

					// Real time: [43211, 86400]
					$availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['in_seconds'][] = $time_range__seconds__arr;

					// For DEBUG only  --  Readable 24H:  '10:00:01 - 12:30:02'
					$availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['readable24h'][] = wpbc_transform_timerange__seconds_arr__in__24_hours_range( $time_range__seconds__arr );

					// -------------------------------------------------------------------------------------------------
					// Pending | Approved  ::  for correct order of all statuses - make it based on start time index    / $time_range__seconds__arr[0] == 0   in situation of  FULL day booking
					$availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved[ $time_range__seconds__arr[0] ] = ( '1' == $booked_times__value->approved ) ? 'approved' : 'pending';


					//   T O O L T I P   ::   Booking Details
					$booked_time_title = ( ( 0 == $time_range__seconds__arr[0] ) && ( $time_range__seconds__arr[1] >= 86400 ) )
											? __( 'Full day', 'booking' )
											: wpbc_transform_timerange__seconds_arr__in__formated_hours( $time_range__seconds__arr );
					$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip__set_for_details( $availability_per_day, $my_day_tag, $resource_id,
																															$this_date_bookings, $booked_times__key, $resources_obj, $booked_time_title );

					// Unset   ...->form  and other fields...
					$this_date_bookings[ $booked_times__key ] = wpbc_support_capacity__unset_some_fields( $this_date_bookings[ $booked_times__key ] );

				}  //  T i m e s   -   E n d     Booked Times Loop  -  for current resource


				// =====================================================================================================
				//   Merge intersected time intervals =
				// =====================================================================================================
				$merged_seconds_arr = wpbc_merge_intersected_intervals( $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['in_seconds'] );

				$availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_seconds'] = $merged_seconds_arr;

				foreach ( $merged_seconds_arr as $booked_time_slots__in_seconds ) {
					$availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable'][] = wpbc_transform_timerange__seconds_arr__in__formated_hours( $booked_time_slots__in_seconds );
				}

				//   T O O L T I P   ::   Times
				$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_for_times( $availability_per_day, $my_day_tag, $resource_id, $resource_id__with_children__arr );

				// =====================================================================================================
				// End times
				// =====================================================================================================


				// For correct order of all booking statuses - we will make it based on start time index - Sort array starting from  1 second 00:00  to  12:00 to  23:00  etc...
				ksort( $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved );

				// array_keys( $booked_time_slots ) can be:   [0] -> 'Full day'   |   ['36011 - 43192', '56011 - 86392'] -> '10:00 - 12:00', '15:55 - 24:00'
				$booked_time_slots = array_keys( $this_date_bookings );


				// =====================================================================================================
				// Full day  booking -----------------------------------------------------------------------------------       full_by_bookings
				// =====================================================================================================
				if ( in_array( '0', $booked_time_slots ) ) {

					$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
					$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'full_day_booking';

					// Reset all other possible time slot statuses, in general  they  must  not exist,  but for some case
					$availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array();

					// Pending or approved,  for full day  booking:     $this_date_bookings['0']
					$availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved[] = ( '1' == $this_date_bookings['0']->approved ) ? 'approved' : 'pending';

					//   T O O L T I P   ::   Times - Full Day Booked
					$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
																															 , $resource_id__with_children__arr, __( 'Full day', 'booking' ) );

				}   // end 'full day' if


				// =====================================================================================================
				// All time slots booked ? -----------------------------------------------------------------------------
				// =====================================================================================================
				if (
					   ( ! empty( $as_seconds_timeslots_arr__to_check_intersect ) )                     // We need to  check  intersection  with some time slot     '36011 - 43192'
					&& ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable )   // And this date still free                                 false
				){

					$is_some_timeslot_available = wpbc_is_some_timeslot__available__in_arr( $as_seconds_timeslots_arr__to_check_intersect, $booked_time_slots );

					// -------------------------------------------------------------------------------------------------        full_by_bookings
					if ( ! $is_some_timeslot_available ) {
						// All  time slots booked !!!

						$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
						$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'full_day_booking';
						$availability_per_day[ $my_day_tag ][ $resource_id ]->_booking_form_timeslots_unavailable = implode( '|', $params[ 'timeslots_to_check_intersect' ] );

						//   T O O L T I P   ::   Times - Full Day Booked
						$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
																																 , $resource_id__with_children__arr, __( 'Full day', 'booking' ) );
					} else {
						// Some time slots available or there is no time slot passed in this function
					}

				}   // end 'all time slots booked' if



				// =====================================================================================================
				// Change over days  =
				// =====================================================================================================
				if (
					   ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) )
					&& ( wpbc_is_booking_used_check_in_out_time( $params[ 'request_uri' ] ) )
					&& ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable )   // And this date still free                                 false
				) {

					/**
					 * "Change over days" - possible situations:      check_in | check_out | change_over | ...
					 *
					 * $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status =    check_in
					 *                                                                      | check_out
					 *                                                                      | change_over
					 *                                                                      | 'mixed'
					 *  'mixed' - e.g. 'change_over check_out'  where several child resources and some is 'change_over' and others are 'check_out'
					 *
					 *
					 * Possible situations for change-over days:
					 *
					 * // A. If in $booked_time_slots array one of values  (or in $this_date_bookings one of keys)
					 * //      1. Started with time  that is ended with  1 second
					 * //      2. and Ended with '24:00' it is means '86392',  like this:   '28811 - 86392'
					 * // then it's means that  we have 'check_in' time here
					 *
					 * // B. If in $booked_time_slots array one of values  (or in $this_date_bookings one of keys)
					 * //      1. Started with '00:00' it is means '1'
					 * //      2. and Ended  time  that is ended with  2 second
					 * //                                                          like this:   '1 - 32402'
					 * // then it's means that  we have 'check_out' time here
					 *
					 * // C. If we have A. and B.  then  we have 'change_over' here
					 */

					$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array();

					foreach ( $this_date_bookings as $booked_times__key => $booked_times__value ) {

						if ( false === strpos( $booked_times__key, '-' ) ) {
							continue;       // for situation  with  FULL day  booking,  here        $booked_times__key = 0
						}

						$rangeA_arr    = explode( '-', $booked_times__key );
						$rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
						$rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );

						// start time
						$is_starttime__check_in = $rangeA_arr[0] % 10;                                                  // 0, 1, 2
						$is_starttime__check_in = ( 1 == $is_starttime__check_in ) ? true : false;

						// end time
						$is_endtime__check_out = $rangeA_arr[1] % 10;
						$is_endtime__check_out = ( 2 == $is_endtime__check_out ) ? true : false;


						if ( ( $is_starttime__check_in ) && ( WPBC_FULL_DAY_TIME_OUT == $rangeA_arr[1] ) ) {                                // A  ::   start_time - 86392    e.g.     14:00 - 24:00
							// only "check in" time here
							$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out[] = 'check_in';

						} else if ( ( WPBC_FULL_DAY_TIME_IN == $rangeA_arr[0] ) && ( $is_endtime__check_out ) ) {                           // B  ::        1 - end_time     e.g.     00:00 - 10:00
							// only "check out" time here
							$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out[] = 'check_out';
						}

					}
					$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array_unique( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );
					$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array_filter( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );    // All entries of array equal to FALSE (0, '', '0' ) will be removed.

					if (
						   ( in_array( 'check_in',  $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) )
						&& ( in_array( 'check_out', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) )
					) {
						$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out       = array( 'change_over' );      // both check in / out times here
						$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;

						// Possible statuses: pending_pending | pending_approved | approved_pending | approved_approved
						$availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array( implode( '_', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved ) );
					}

					$availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );

					if ( ! empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) ) {
						$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out;
					}
				}   // end change-over if


			}
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			// B O O K I N G S   -   E n d
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

			//==========================================================================================================
			//      $availability_per_day[..]->_day_status  =  'season_filter' | ...
			//==========================================================================================================
			// Booking > Resources > Availability page          >>>            'season_filter'
			$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__season_filter( $availability_per_day, $my_day_tag, $resource_id, $season_filters_availability );

			// Booking > Availability page                      >>>             'resource_availability'
			$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 );

			// Week Days unavailable                            >>>            'weekday_unavailable'
			$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id );

			// if ( ( ! $is_this_bap_page ) || ( ! $is_this_hash_page ) ) {
			if ( ( ! $is_this_bap_page ) && ( ! $is_this_hash_page ) ) {
				// Do not apply these settings at Booking > Add booking page, when we edit booking - e.g. exist 'booking_hash'

				// Unavailable days from today                  >>>            'from_today_unavailable'
				$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id );

				// Limit available days from today              >>>            'limit_available_from_today'
				$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 );
			}
			//==========================================================================================================


			//   T O O L T I P   ::   Times - Unavailable Day
			if ( in_array( $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status, array( 'season_filter',
																									 'resource_availability',
																									 'weekday_unavailable',
																									 'from_today_unavailable',
																									 'limit_available_from_today'
																								) )
			){
				$availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
																														 , $resource_id__with_children__arr, __( 'Unavailable', 'booking' ) );
			}


			// =========================================================================================================
			// Entire    D A Y    statuses
			// =========================================================================================================

			if ( $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) {
				// Set merged time interval  as fully  unavailable.
				$availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_seconds'] = array( array( 0, 86400 ) );  // FixIn: 10.11.5.1.
				// Reduce DAY day_availability,  if some season or days unavailable or full by  bookings.
				--$availability_per_day[ $my_day_tag ]['day_availability'];
			}

			// 'resource_availability' | 'weekday_unavailable' | 'from_today_unavailable' | 'limit_available_from_today' | 'season_filter' | 'full_day_booking' | 'time_slots_booking' | 'available'.
			$availability_per_day[ $my_day_tag ]['statuses']['day_status'][] = $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status;

			// 'approved' | 'pending'.
			$availability_per_day[ $my_day_tag ]['statuses']['bookings_status'][] = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved );

			// Go to next child booking resource.
		}

		// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		// R E S O U R C E S   -   E n d
		// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


		// -------------------------------------------------------------------------------------------------------------
        // Day summary :
		// -------------------------------------------------------------------------------------------------------------
		$availability_per_day[ $my_day_tag ] = wpbc_update_summary_availability_per_this_day( $availability_per_day[ $my_day_tag ], $my_day_tag, $resource_id__with_children__arr );

		// Go next day    	  +  1 day
		$today_inix_timestamp += 24 * 60 * 60;
	}


	return array(
					'dates'                       => $availability_per_day
				  , 'resources_id_arr__in_dates'  => $resource_id__with_children__arr
	              , 'aggregate_resource_id_arr'   => $aggregate_resource_id_arr
				);
}


// <editor-fold     defaultstate="collapsed"                        desc="  ==  S U P P O R T  ==  "  >


	// S U P P O R T

	/**
	 * Update Summary statuses for the Day
	 *
	 * @param $availability_per_this_day
	 * @param $my_day_tag
	 * @param $resource_id_arr
	 *
	 * @return mixed
	 *
	 *
	 * Dates Status Concept Strategy ::
	 *
	 * Check date booking status based on 'all booking resources':
	 * ( and as one common situation, when we have only  1 resource )
	 *
	 * | 'approved'                 - when all booking resources has approved FULL day  bookings or some booking resource unavailable
	 * | 'pending'                  - when at least one booking in one booking resource has pending status and there is no available booking resources
	 * | 'times_partially_booked'   - when at least one booking in one booking resource has time bookings and there is no available booking resources
	 *                                  and if all  time slot approved then  status approved
	 *                                  otherwise if at least one time slot booking has pending status then  it has pending status
	 *
	 *                              if all 'time_slots' booked (it's time slot passed into function as parameter)
	 *                              then  such  date in specific booking resource  has pending or approved status,  based on 'pending'|'approved' rule
	 *
	 * | 'check_in'                 - if activated 'change over days'  and all bookings have 'check-in' status
	 * | 'check_out'                - if activated 'change over days'  and all bookings have 'check-out' status
     * |                                if in booking resource  exist  both check in/out bookings,  and  activated 'change over days'
	 *                                  then such booking resource date has approved or pending status depends on from  status of these bookings
	 * | 'season_unavailable'       - if all  booking resources defined as unavailable at  Booking > Resources > Availability page
	 * | 'resource_unavailable'     - if all  booking resources defined as unavailable at  Booking > Availability page
	 * | 'other_unavailable'        - if all  booking resources defined as unavailable at  Booking > Settings General page in "Availability" section
	 *
	 */
	function wpbc_update_summary_availability_per_this_day( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

		// -------------------------------------------------------------------------------------------------------------
		// Summary Tooltips
		// -------------------------------------------------------------------------------------------------------------
		$availability_per_this_day['summary']['tooltip_times']           = wpbc_support_capacity__tooltip__summary__times( $availability_per_this_day, $my_day_tag, $resource_id_arr );
		$availability_per_this_day['summary']['tooltip_booking_details'] = wpbc_support_capacity__tooltip__summary__booked_details( $availability_per_this_day, $my_day_tag, $resource_id_arr );
		$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 );
		$availability_per_this_day['summary']['tooltip_availability']    = wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr );


		$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 );
		$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.

		// -------------------------------------------------------------------------------------------------------------
		// ['summary']['status_for_day']
		// -------------------------------------------------------------------------------------------------------------
		$temp_status = array();
		foreach ( $availability_per_this_day['statuses']['day_status'] as $bookings_status_arr ) {
			$bookings_status_arr = explode( '|', $bookings_status_arr );
			foreach ( $bookings_status_arr as $bookings_status_element ) {
				$temp_status[] = $bookings_status_element;
			}
		}
		$temp_status = array_filter( $temp_status );                                                                    // All entries of array equal to FALSE (0, '', '0' ) will be removed.
		$temp_status = array_unique( $temp_status );                                                                    // Erase duplicates
		$availability_per_this_day['summary']['status_for_day'] = $temp_status;

		/**
		 * Possible day statuses (searched by  value of _day_status):
		 *
		 * available
		 * time_slots_booking
		 * full_day_booking
		 *
		 * limit_available_from_today
		 * from_today_unavailable
		 * weekday_unavailable
		 * resource_availability
		 * season_filter
		 *
		 *      change_over
		 *      check_out
		 *      check_in
		 *              'mixed'  from check_in/check_out/change_over
		 */

		// Priority:    available > time_slots_booking > full_day_booking
		//                        > season_filter > resource_availability
		//                        > weekday_unavailable > from_today_unavailable > limit_available_from_today

		// if at least one booking "available" then day has this status
		if ( in_array( 'available', $availability_per_this_day['summary']['status_for_day'] ) ) {                      $availability_per_this_day['summary']['status_for_day'] = 'available';
		} 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';
		} else if ( ( ! in_array( 'check_out',  $availability_per_this_day['summary']['status_for_day'] ) )
	               && ( in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) ) ) {          $availability_per_this_day['summary']['status_for_day'] = 'check_in';
		} else if ( ( ! in_array( 'check_in',  $availability_per_this_day['summary']['status_for_day'] ) )
	               && ( in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) ) ) {         $availability_per_this_day['summary']['status_for_day'] = 'check_out';
		} else if ( in_array( 'full_day_booking', $availability_per_this_day['summary']['status_for_day'] ) ) {        $availability_per_this_day['summary']['status_for_day'] = 'full_day_booking';
		} else if ( in_array( 'season_filter', $availability_per_this_day['summary']['status_for_day'] ) ) {           $availability_per_this_day['summary']['status_for_day'] = 'season_filter';
		} else if ( in_array( 'resource_availability', $availability_per_this_day['summary']['status_for_day'] ) ) {   $availability_per_this_day['summary']['status_for_day'] = 'resource_availability';
		} else if ( in_array( 'weekday_unavailable', $availability_per_this_day['summary']['status_for_day'] ) ) {     $availability_per_this_day['summary']['status_for_day'] = 'weekday_unavailable';
		} else if ( in_array( 'from_today_unavailable', $availability_per_this_day['summary']['status_for_day'] ) ) {  $availability_per_this_day['summary']['status_for_day'] = 'from_today_unavailable';
		} else if ( in_array( 'limit_available_from_today', $availability_per_this_day['summary']['status_for_day'])){ $availability_per_this_day['summary']['status_for_day'] = 'limit_available_from_today';
		} else {
			$availability_per_this_day['summary']['status_for_day'] = implode( ' ', $availability_per_this_day['summary']['status_for_day'] );
		}


		// -------------------------------------------------------------------------------------------------------------
		// ['summary']['status_for_bookings']
		// -------------------------------------------------------------------------------------------------------------
		$temp_status = array();
		foreach ( $availability_per_this_day['statuses']['bookings_status'] as $bookings_status_arr ) {
			$bookings_status_arr = explode( '|', $bookings_status_arr );
			foreach ( $bookings_status_arr as $bookings_status_element ) {
				$temp_status[] = $bookings_status_element;
			}
		}
		$temp_status = array_filter( $temp_status );                                                                    // All entries of array equal to FALSE (0, '', '0' ) will be removed.
		$temp_status = array_unique( $temp_status );
		$availability_per_this_day['summary']['status_for_bookings'] = $temp_status;

		// Priority:    pending > approved > ''

		// if at least one booking pending then day is pending
		if ( in_array( 'pending',  $availability_per_this_day['summary']['status_for_bookings'] ) ) {                  $availability_per_this_day['summary']['status_for_bookings'] = 'pending';
		} else if ( in_array( 'pending_pending',  $availability_per_this_day['summary']['status_for_bookings'] ) ) {   $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending';
			// Usual  situations for change over days:  pending_pending  |  pending_approved  |   approved_pending  |   approved_approved
		} else {
			 $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ',  $availability_per_this_day['summary']['status_for_bookings'] );
		}


		// -------------------------------------------------------------------------------------------------------------
		return $availability_per_this_day;
	}


		// T O O L T I P s

		/**
		 * Set tooltip summary  -- Time-Slots
		 *
		 * @param $availability_per_this_day
		 * @param $my_day_tag
		 * @param $resource_id_arr
		 *
		 * @return string       -   tooltip content or ''
		 */
		function wpbc_support_capacity__tooltip__summary__times( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

		    $tooltip = '';

			if ( 'On' != get_bk_option( 'booking_disable_timeslots_in_tooltip' ) ) {                                    //FixIn: 9.5.0.2.2

				$tooltip_title_word = get_bk_option( 'booking_highlight_timeslot_word' );
				$tooltip_title_word = wpbc_lang( $tooltip_title_word );
				$tooltip_title_word = ( empty( $tooltip_title_word ) )
										? ''
										: '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';

				$status_summary_tooltip_times = array();
				foreach ( $resource_id_arr as $resource_id ) {
					if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['times'] ) ) {
						$status_summary_tooltip_times[] = $availability_per_this_day[ $resource_id ]->tooltips['times'];
					}
				}

				if ( ! empty( $status_summary_tooltip_times ) ) {

					$tooltip = '<div class="wpbc_tooltip_section tooltip__times">'
					                . $tooltip_title_word
					                . implode( '', $status_summary_tooltip_times )
					           . '</div>';
				}
			}

			return $tooltip;
		}

		function wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

			$tooltip = '';

            if ( ( 'On' == get_bk_option( 'booking_is_show_availability_in_tooltips' ) ) && ( $availability_per_this_day['max_capacity'] > 1 ) ) {

				$tooltip_title_word = get_bk_option( 'booking_highlight_availability_word' );
				$tooltip_title_word = wpbc_lang( $tooltip_title_word );
				$tooltip_title_word = ( empty( $tooltip_title_word ) )
										? ''
										: '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';

				$tooltip_content_header = '';

				if ( ! empty( $availability_per_this_day['day_availability'] ) ) {

					$tooltip = '<div class="wpbc_tooltip_section tooltip__availability">'
				                    . $tooltip_title_word
									. '<div class="wpbc_tooltip_resource_container">'
										. $tooltip_content_header
										. '<div class="wpbc_tooltip_item">'
												. $availability_per_this_day['day_availability']
										. '</div>'
									. '</div>'
					           . '</div>';
				}
			}
			return $tooltip;
		}

		function wpbc_support_capacity__tooltip__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

			$tooltip = '';
			if (
				  ( ! empty( $availability_per_this_day['day_availability'] ) )
               && ( 'On' == get_bk_option( 'booking_is_show_cost_in_tooltips' ) )
			){

				$tooltip_title_word = get_bk_option( 'booking_highlight_cost_word' );
				$tooltip_title_word = wpbc_lang( $tooltip_title_word );
				$tooltip_title_word = ( empty( $tooltip_title_word ) )
										? ''
										: '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';

				$id_of_first_resource = $resource_id_arr[0];
				$tooltip_content_header = '';

				if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) {

					 $cur_sym  = get_bk_option( 'booking_cost_in_date_cell_currency' );       // in Booking > Settings General page in "Calendar" section
					//$cur_sym = wpbc_get_currency_symbol();                                  // in Booking > Settings > Payment page

					$cost_text = wpbc_formate_cost_hint__no_html( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate, $cur_sym );
					$cost_text = html_entity_decode( $cost_text );

					$tooltip = '<div class="wpbc_tooltip_section tooltip__day_cost">'
				                    . $tooltip_title_word
									. '<div class="wpbc_tooltip_resource_container">'
										. $tooltip_content_header
										. '<div class="wpbc_tooltip_item">'
												. $cost_text
										. '</div>'
									. '</div>'
					           . '</div>';
				}
			}
			return $tooltip;
		}


		function wpbc_support_capacity__in_day_hint__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

			$tooltip = '';
			if (
				  ( ! empty( $availability_per_this_day['day_availability'] ) )
               && ( 'On' == get_bk_option( 'booking_is_show_cost_in_date_cell' ) )
			){

				$id_of_first_resource = $resource_id_arr[0];

				if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) {

					 $cur_sym  = get_bk_option( 'booking_cost_in_date_cell_currency' );       // in Booking > Settings General page in "Calendar" section
					//$cur_sym = wpbc_get_currency_symbol();                                  // in Booking > Settings > Payment page

					$cost_text = $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate;
					$cost_text = number_format( floatval( $cost_text ), wpbc_get_cost_decimals(), '.', '' );
					$cost_text = wp_strip_all_tags( wpbc_cost_show( $cost_text, array(  'currency' => 'CURRENCY_SYMBOL' ) ) );
					$cost_text = str_replace( array( 'CURRENCY_SYMBOL', '&' ), array( $cur_sym, '&amp;' ), $cost_text );
					$cost_text = html_entity_decode($cost_text);

					$tooltip =  '<span class="wpbc_in_date_hint__cost">' . $cost_text . '</span>';;
				}
			}
			return $tooltip;
		}

		// FixIn: 10.6.4.1.
		/**
		 * Get availability  for in Day cells
		 *
		 * @param $availability_per_this_day
		 * @param $my_day_tag
		 * @param $resource_id_arr
		 *
		 * @return string
		 */
		function wpbc_support_capacity__in_day_hint__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

			$tooltip = '';

            if (
					( 'On' == get_bk_option( 'booking_is_show_availability_in_date_cell' ) ) &&
					( $availability_per_this_day['max_capacity'] > 1 )
            ) {

				$tooltip_title_word = get_bk_option( 'booking_highlight_availability_word_in_date_cell' );
				$tooltip_title_word = wpbc_lang( $tooltip_title_word );
				$tooltip_title_word = ( empty( $tooltip_title_word ) )
										? ''
										: '<span class="wpbc_in_date_hint__availability_title">' . $tooltip_title_word . '</span>';


				if ( ! empty( $availability_per_this_day['day_availability'] ) ) {

					$tooltip = '<span class="wpbc_in_date_hint__availability">'
									. '<span class="wpbc_in_date_hint__availability_number">'
											. intval( $availability_per_this_day['day_availability'] )
					                        . '&nbsp;'
									. '</span>'
				                    . $tooltip_title_word
					           . '</span>';
					$tooltip = html_entity_decode($tooltip);
				}
			}
			return $tooltip;
		}



		/**
		 * Set tooltip summary  -- Booking Details
		 *
		 * @param $availability_per_this_day
		 * @param $my_day_tag
		 * @param $resource_id_arr
		 *
		 * @return string       -   tooltip content or ''
		 */
		function wpbc_support_capacity__tooltip__summary__booked_details( $availability_per_this_day, $my_day_tag, $resource_id_arr ){

			$tooltip = '';

			if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) {                                            //FixIn: 9.5.0.2.2

				$tooltip_title_word = '<div class="wpbc_tooltip_title">' . esc_html__('Booking details','booking') . '</div>';

				$status_summary_tooltip_times = array();
				foreach ( $resource_id_arr as $resource_id ) {
					if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['details'] ) ) {

						if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['resource_title'] ) ){
							$tooltip_content_header = '<div class="wpbc_tooltip_header">'
															. $availability_per_this_day[ $resource_id ]->tooltips['resource_title'] . ': '
			                                        . '</div>';
						} else{
							$tooltip_content_header = '';
						}

						$booking_details_text = '<div class="wpbc_tooltip_resource_container">'
						                            . $tooltip_content_header
						                            . implode( ' ', $availability_per_this_day[ $resource_id ]->tooltips['details'] )
                                              . '</div>';

						$status_summary_tooltip_times[] = $booking_details_text;
					}
				}

				if ( ! empty( $status_summary_tooltip_times ) ) {

					$tooltip = '<div class="wpbc_tooltip_section tooltip__booking_details">'
					                . $tooltip_title_word
					                . implode( '', $status_summary_tooltip_times )
					           . '</div>';
				}
			}
			return $tooltip;
		}

				/**
				*  Set Tooltip -- Booking Details
				*
				* @param $availability_per_day
				* @param $my_day_tag
				* @param $resource_id
				* @param $this_date_bookings
				* @param $booked_times__key
				* @param $resources_obj
				*
				* @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
				*/
				function wpbc_support_capacity__tooltip__set_for_details( $availability_per_day, $my_day_tag, $resource_id, $this_date_bookings, $booked_times__key, $resources_obj, $booked_time ) {

                    // Get booking details for tooltip,  if needed
					if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) {

						$booking_id               = $this_date_bookings[ $booked_times__key ]->booking_id;
						$this_booking_resource_id = $this_date_bookings[ $booked_times__key ]->type;

					    $booking_details_text = wpbc_support_capacity__get_booking_details(
																						$this_date_bookings[ $booked_times__key ],
																						$resources_obj->get__booking_resource_obj( $this_booking_resource_id )
																					);
						$tooltip_text  = '';
						$tooltip_text .= '<div class="wpbc_tooltip_item tooltip_booked_time">' . $booked_time          . '</div>';           // Booked time
						$tooltip_text .= '<div class="wpbc_tooltip_item">' . $booking_details_text . '</div>';           // Booking details

						$availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['details'][ $booking_id ] = $tooltip_text;
					}

					return $availability_per_day[ $my_day_tag ][ $resource_id ];
				}

				/**
				 *  Set Tooltip Times -- Time-Slots
				 *
				 * @param $availability_per_day
				 * @param $my_day_tag
				 * @param $resource_id
				 * @param $resource_id_arr
				 *
				 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
				 */
				function wpbc_support_capacity__tooltip_times__set_for_times( $availability_per_day, $my_day_tag, $resource_id, $resource_id_arr ){

					// Times Tooltip -  time slot list  --------------------------------------------------------------------
					$tooltip_content_header = '';

					if ( count( $resource_id_arr ) > 1 ) {

						$class_name = 'tooltip_items_count_' . count( $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable'] );

						$tooltip_content_header = '<div class="wpbc_tooltip_header ' . $class_name . ' ">'
														. $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['resource_title'] . ': '
		                                        . '</div>';
					}

					$tooltip_content_arr = array_map(      function ( $item ) {
																				return '<div class="wpbc_tooltip_item">' . $item . '</div>';
																			}
														, $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable']
													);

					$availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['times'] = '<div class="wpbc_tooltip_resource_container">'
					                                                                                . $tooltip_content_header
					                                                                                . implode( '', $tooltip_content_arr )
					                                                                          . '</div>';
					return $availability_per_day[ $my_day_tag ][ $resource_id ];
				}

				/**
				 *  Set Tooltip Times -- Full Day
				 *
				 * @param $availability_per_day
				 * @param $my_day_tag
				 * @param $resource_id
				 * @param $resource_id_arr
				 * @param $status_title
				 *
				 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
				 */
				function wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id, $resource_id_arr, $status_title ){

					// Times Tooltip -  FULL DAY  --------------------------------------------------------------------
					$tooltip_content_header = '';

					if ( count( $resource_id_arr ) > 1 ) {

						$class_name = 'tooltip_items_count_1';

						$tooltip_content_header = '<div class="wpbc_tooltip_header ' . $class_name . ' ">'
														. $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['resource_title'] . ': '
		                                        . '</div>';
					}

					$tooltip_content_text =  '<div class="wpbc_tooltip_item">' . $status_title . '</div>';

					$availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['times'] = '<div class="wpbc_tooltip_resource_container">'
					                                                                                . $tooltip_content_header
					                                                                                . $tooltip_content_text
					                                                                          . '</div>';
					return $availability_per_day[ $my_day_tag ][ $resource_id ];
				}



		/**
		 * Get parsed booking data, if required
		 *
		 * @param object $this_date_bookings
		 * @param object $resource_obj
		 *
		 * @return string
		 */
		function wpbc_support_capacity__get_booking_details( $this_date_bookings, $resource_obj ) {

			if (    ( ! class_exists( 'wpdev_bk_biz_m' ) )
			     || ( 'On' !== get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) )
			){
			    return '';
		    }

			$booking_details_for_hint = '';

			if ( isset( $this_date_bookings->form ) ) {

				// Get shortcodes
				$booking_shortcodes_in_tooltips = get_bk_option( 'booking_booked_data_in_tooltips' );                       // '[name] [secondname]'

				$resource_id = $this_date_bookings->type;

				// Get parsed booking data field values -- e.g.:  [ "rangetime":"12:00 - 14:00", "secondname":"Smith",... ]
				$booking_data_arr = wpbc_get_parsed_booking_data_arr( $this_date_bookings->form, $resource_id, array( 'get' => 'value' ) );
				$booking_data_arr['booking_id']     = $this_date_bookings->booking_id;
				$booking_data_arr['resource_id']    = $resource_id;
				$booking_data_arr['resource_title'] = ( ! empty( $resource_obj ) ) ? wpbc_lang( $resource_obj->title ) : '';

				// Replace existing shortcodes
				foreach ( $booking_data_arr as $replace_shortcode => $replace_value ) {

					if ( is_null( $replace_value ) ) { $replace_value = ''; };

					$replace_value = wpbc_replace__true_false__to__yes_no( $replace_value );									    // FixIn: 9.8.9.1.

		            $booking_shortcodes_in_tooltips = str_replace(  array(
																			'[' . $replace_shortcode . ']'
		                                                                  , '{' . $replace_shortcode . '}'
			                                                        )
		                                                            , $replace_value
		                                                            , $booking_shortcodes_in_tooltips
		                                                );
		        }

				$booking_details_for_hint = $booking_shortcodes_in_tooltips;

		        // Remove all shortcodes, which is not replaced early.
				$booking_details_for_hint = preg_replace( '/[\[\{][a-zA-Z0-9.,_-]{0,}[\]\}]/', '', $booking_details_for_hint );
			}

			return $booking_details_for_hint;
		}


		/**
		 * Unset  some fields from booking data for do  not show personal data at front-end side
		 *
		 * @param object $this_date_bookings
		 *
		 * @return object
		 */
		function wpbc_support_capacity__unset_some_fields( $this_date_bookings ) {

			if ( isset( $this_date_bookings->form ) ) {
				unset( $this_date_bookings->form );               // Hide booking details
			}

			if ( isset( $this_date_bookings->booking_date ) ) {
				unset( $this_date_bookings->booking_date );       // Confusing property of last end booking date, because we have 'sql summary booking dates arrays' for all dates and times
			}

			return $this_date_bookings;
		}


		// D A Y    S T A T U S    U N A V A I L A B L E

		/**
		 * Set > _day_status = 'limit_available_from_today'  depends on   Booking > Settings General page --->  "Limit available days from today"
		 *
		 * @param $availability_per_day                                 [ ... ]
		 * @param $my_day_tag                                           - '2023-08-08'
		 * @param $resource_id                                          - 2
		 *
		 * @return array                                                -   $availability_per_day[ $my_day_tag ][ $resource_id ]
		 */
		function wpbc_support_capacity__day_status__limit_available_from_today( $availability_per_day, $my_day_tag, $resource_id ){

			// -----------------------------------------------------------------------------------------------------        // limit_available_from_today
			// 3. Limit available days from today
			if ( function_exists( 'wpbc_is_day_available__relative__limit_available_from_today' ) ) {
				if ( ! wpbc_is_day_available__relative__limit_available_from_today( $my_day_tag ) ) {
					// this date unavailable
					$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
					$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status        = 'limit_available_from_today';

					if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
						$availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array();               // Reset  bookings details
					}
				}
			}

			return $availability_per_day[ $my_day_tag ][ $resource_id ];
		}


		/**
		 * Set > _day_status = 'from_today_unavailable'  depends on   Booking > Settings General page --->  "Unavailable days from today"
		 *
		 * @param $availability_per_day                                 [ ... ]
		 * @param $my_day_tag                                           - '2023-08-08'
		 * @param $resource_id                                          - 2
		 *
		 * @return array                                                -   $availability_per_day[ $my_day_tag ][ $resource_id ]
		 */
		function wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id ){

			// FixIn: 10.8.1.4.

			// -----------------------------------------------------------------------------------------------------        // from_today_unavailable
			// 2. Unavailable days from today
			$unavailable_days_num_from_today = get_bk_option( 'booking_unavailable_days_num_from_today' );

			// FixIn: 10.8.1.4.
			if ( ! empty( $unavailable_days_num_from_today ) ) {
				if ( 'm' === substr( $unavailable_days_num_from_today, - 1 ) ) {
					$start_date_unix = strtotime( '+' . ( intval( $unavailable_days_num_from_today ) - 1 ) . ' minutes' );                // + 0 days
				} else {
					$start_date_unix = strtotime( '+' . intval( $unavailable_days_num_from_today ) . ' days' );                           // + 0 days
				}
			} else {
				$start_date_unix = strtotime( 'now' );
			}

			$date_start__gmt                   = gmdate( 'Y-m-d H:i:s', $start_date_unix );                                         // '2025-01-25 12:50:10'
			$date_start__midnight__wp_timezone = wpbc_datetime_localized__use_wp_timezone( $date_start__gmt, 'Y-m-d 00:00:00' );    // Local Midnight.

			// 'Today Midnight' - 'Calendar Day Cell' .
			$days_number = intval( ( strtotime( $date_start__midnight__wp_timezone ) - strtotime( $my_day_tag ) ) / 86400 );

			if ( $days_number > 0 ) {
				// This date Unavailable.
				$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
				$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status        = 'from_today_unavailable';

				if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
					$availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array();                   // Reset  bookings details
				}
			}

			return $availability_per_day[ $my_day_tag ][ $resource_id ];
		}


		/**
		 * Set > _day_status = 'weekday_unavailable'  depends on   Booking > Settings General page --->  "Week Days unavailable"
		 *
		 * @param $availability_per_day                                 [ ... ]
		 * @param $my_day_tag                                           - '2023-08-08'
		 * @param $resource_id                                          - 2
		 *
		 * @return array                                                -   $availability_per_day[ $my_day_tag ][ $resource_id ]
		 */
		function wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id ){

			// 1. Week Days unavailable --------------------------------------------------------------------------------        // weekday_unavailable
			$unavailable_weekdays = array();
			foreach ( range( 0, 6 ) as $week_day_num ) {
				$unavailable_weekdays[ $week_day_num ] = ( 'On' == get_bk_option( 'booking_unavailable_day' . $week_day_num ) ) ? true : false;
			}

			$this_day_week_num = gmdate( 'w', strtotime( $my_day_tag ) ); // 0 - 6

			if ( $unavailable_weekdays[ $this_day_week_num ] ) {
				// this date unavailable
				$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
				$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'weekday_unavailable';

				if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
					$availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array();                   // Reset  bookings details
				}
			}

			return $availability_per_day[ $my_day_tag ][ $resource_id ];
		}


		/**
		 * Set > _day_status = 'resource_availability'  depends on   Booking > Availability page
		 *
		 * @param $availability_per_day                               [ ... ]
		 * @param $my_day_tag                                         - '2023-08-08'
		 * @param $resource_id                                        - 2
		 * @param array $unavailable_dates__per_resources__arr        - [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
		 *
		 * @return array                                    -   $availability_per_day[ $my_day_tag ][ $resource_id ]
		 */
		function wpbc_support_capacity__day_status__resource_availability( $availability_per_day, $my_day_tag, $resource_id, $unavailable_dates__per_resources__arr ){

			// Booking > Availability page -----------------------------------------------------------------------------        // resource_availability
			/**
			 * $unavailable_dates__per_resources__arr =  Array (     [2] => Array(   [0] => 2023-08-01
																	                 [1] => 2023-08-02
																		        )
																    [10] => Array(   [0] => 2023-08-05
																		             [1] => 2023-08-06
																		        )
																)
			 */
			if (
				   ( isset( $unavailable_dates__per_resources__arr[ $resource_id ] ) )
		        && ( in_array( $my_day_tag, $unavailable_dates__per_resources__arr[ $resource_id ] ) )
			) {

				$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
				$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'resource_availability';

				if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
					$availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array();                   // Reset  bookings details
				}
			}

			return $availability_per_day[ $my_day_tag ][ $resource_id ];
		}


		/**
		 * Set > _day_status = 'season_filter'  depends on   Booking > Resources > Availability page
		 *
		 * @param $availability_per_day                               [ ... ]
		 * @param $my_day_tag                                         - '2023-08-08'
		 * @param $resource_id                                        - 2
		 * @param array $season_filters_availability                  - [...]
		 *
		 * @return array                                              -   $availability_per_day[ $my_day_tag ][ $resource_id ]
		 */
		function wpbc_support_capacity__day_status__season_filter( $availability_per_day, $my_day_tag, $resource_id, $season_filters_availability ){

		    if ( function_exists( 'wpbc_is_this_day_available_in_season_filters' ) ) {                                       // BM  and higher

				$is_date_available = wpbc_is_this_day_available_in_season_filters( $my_day_tag, $resource_id, $season_filters_availability[ $resource_id ] );    // Get availability
				if ( ! $is_date_available ) {

					$availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
					$availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'season_filter';

					if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
						$availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array();               // Reset  bookings details
					}
				}
			}

			return $availability_per_day[ $my_day_tag ][ $resource_id ];
		}


		// D A Y   C O S T

		/**
		 * Get day cost     depend on Rates
		 * @param $my_day_tag                                         - '2023-08-08'
		 * @param $resource_id                                        - 2
		 * @param $base_cost                                          - 25
		 *
		 * @return int|string
		 */
		function wpbc_support_capacity__get_day_cost( $my_day_tag, $resource_id, $base_cost ) {

			$fin_day_cost = 0;
			if ( function_exists( 'wpbc_get_1_day_cost_apply_rates' ) ) {

				list( $year, $month, $day ) = explode( '-', $my_day_tag );

				$day   = intval( $day );
				$month = intval( $month );
				$year  = intval( $year );

				$fin_day_cost = wpbc_get_1_day_cost_apply_rates( $resource_id, $base_cost, $day, $month, $year );
			}

			return $fin_day_cost;
		}


// </editor-fold>



//TODO:         M I G R A T E        to      9.8
// .
// 		instead of this:  	<script type="text/javascript">  wpbc_settings.set_option( 'pending_days_selectable', true ); </script>
// 			   use this:    <script type="text/javascript">  _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'pending_days_selectable' , true  );  </script>
//  Booking Calendar -  JavaScript Settings
//  Example or redefine some settings:
//  <script type="text/javascript">  wpbc_settings.set_option( 'pending_days_selectable', true ); </script>
//  [booking type=1]
//   .
// .
// 1. Define parameters for calendar(s):
// 											_wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'single'}  );
// 											_wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'multiple'}  );
// 											_wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'fixed'}  );
// 												_wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'fixed__days_num'  : 7 } );
// 												_wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'fixed__week_days__start': [-1] } ); // { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }
// 											_wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'dynamic'}  );
// 												_wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_min'      , 7  );
// 												_wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_max'      , 14  );
// 												_wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_specific' , []  );	// Example [5,7]
// 												_wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__week_days__start'    , [-1]  ); // { -1 - Any | 0 - Su,  1 - Mo,  2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat }
//  JavaScript functions changes:
// 		wpbc_unselect_all_days( resource_id ) 		                        ->	wpbc_calendar__unselect_all_dates( resource_id )
// 		showErrorMessage( element , errorMessage , isScrollStop );          ->  wpbc_front_end__show_message__warning( jq_node, message );
// 		showMessageUnderElement( element , errorMessage , message_type);    ->  wpbc_front_end__show_message__warning_under_element( jq_node, message );
// 		makeScroll( object_name );                                          ->  wpbc_do_scroll( jq_node );
// .
//  JavaScript hooks changes:
//								jQuery( ".booking_form_div" ).trigger( "date_selected", [ resource_id, date ] );
//					become
//								jQuery( ".booking_form_div" ).trigger( "date_selected", [ resource_id, mouse_clicked_dates, all_selected_dates_arr ] );
// 								where:
// 											mouse_clicked_dates  		Can be: "05.10.2023 - 07.10.2023"  |  "10.10.2023 - 10.10.2023"  |
// 											all_selected_dates_arr 		Can be: [ "2023-10-05", "2023-10-06", "2023-10-07", … ]
// PHP actions:
//   from: 	make_bk_action('wpdev_booking_post_inserted', $booking_id, $bktype, $str_dates__dd_mm_yyyy,  array($start_time, $end_time ) , $formdata );
//   removed!
// .
//   from:	apply_filters('wpdev_booking_form_content', $form , $resource_id);
//   to:     	apply_filters( 'wpbc_booking_form_html__update__append_change_over_times', $form, $resource_id );
// .
// Removed PHP actions:
// . 'show_payment_forms__for_ajax'
//	 *  make_bk_action('wpbc_ add_new_booking' , array(
//	 *		 'bktype' => 1
//	 *		 , 'dates' => '27.08.2014, 28.08.2014, 29.08.2014'
//	 *		 , 'form' => 'selectbox-one^rangetime1^10:00 - 12:00~text^name1^Jo~text^secondname1^Smith~email^email1^[email protected]~text^phone1^678676678~text^address1^Linkoln Street~text^city1^London~text^postcode1^78788~selectbox-one^country1^GB~selectbox-one^visitors1^1~selectbox-one^children1^1~textarea^details1^Rooms with sea view~checkbox^term_and_condition1[]^I Accept term and conditions'
//	 *		 , 'is_send_emeils' => 0
//	 *		// , 'booking_form_type' => ''
//	 *		// , 'wpdev_active_locale' => 'en_US'
//	 *		) );
// .
//      add_bk_filter('wpbc_add_new_booking_filter' , 'wpbc_add_new_booking' );
// TODO: recheck  hooks in wpbc-dev-api.php

Filemanager

Name Type Size Permission Actions
_out Folder 0750
_src Folder 0750
aggregate.php File 6.35 KB 0640
booking_date_class.php File 10.52 KB 0640
calendar_load.php File 22.57 KB 0640
capacity.php File 101.96 KB 0640
captcha_simple_text.php File 6.36 KB 0640
confirmation.php File 21.37 KB 0640
confirmation_page.php File 16.81 KB 0640
create_booking.php File 83.19 KB 0640
dates_times_support.php File 69.99 KB 0640
get_times_fields.php File 16.76 KB 0640
resource_support.php File 10.47 KB 0640
where_to_save.php File 21.78 KB 0640
wpbc_cache.php File 4.48 KB 0640
Filemanager