PluginProbe
Booking Calendar / 11.2
Booking Calendar v11.2
11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 All 203 releases
booking / includes / _capacity / capacity.php

capacity.php in Booking Calendar 11.2, at includes/_capacity/capacity.php

2,040 lines 109.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly // FixIn: 9.8.0.4.
4
5
6 // <editor-fold defaultstate="collapsed" desc=" == SQL - Get Dates array from DB == " >
7
8 // -----------------------------------------------------------------------------------------------------------------
9 // SQL - Get Dates array from DB
10 // -----------------------------------------------------------------------------------------------------------------
11
12 /**
13 * 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( ), ... ]
14 *
15 * @param array $params = array(
16 'approved' => 'all' | 0 | 1 default 'all'
17 , 'resource_id' => array, CSD, int if empty then default '1'
18 , 'additional_bk_types' => array, CSD, int OPTIONAL default array()
19 , 'skip_booking_id' => CSD default ''
20 )
21 *
22 * @return array Array ( [0] => stdClass Object ( [booking_date] => 2023-08-08 10:00:01
23 [approved] => 0
24 [date_res_type] =>
25 [booking_id] => 45
26 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^selected_short_dates_hint2^...
27 [parent] => 0
28 [prioritet] => 20
29 [type] => 2
30 )
31 [1] => stdClass Object (
32 [booking_date] => 2023-08-08 10:00:01
33 [approved] => 0
34 [date_res_type] =>
35 [booking_id] => 46
36 [form] => selectbox-one^rangetime10^10:00 - 12:00~text^selected_short_dates_hint10^...
37 [parent] => 2
38 [prioritet] => 1
39 [type] => 10
40 ), ...
41 *
42 *
43 * Example:
44
45 $sql_dates_params = array(
46 'approved' => ( ( 'On' == get_bk_option( 'booking_is_show_pending_days_as_available' ) ) ? '1' : 'all' )
47 , 'resource_id' => $type_id
48 , 'skip_booking_id' => wpbc_get_booking_id__from_hash_in_url() // int | '' // Booking IDs to skip getting from DB
49 );
50 $dates_approve = wpbc__sql__get_booking_dates( $sql_dates_params );
51
52 */
53 function wpbc__sql__get_booking_dates( $params ){
54
55 //TODO: think about pre-caching SQL request for all booking resources - useful for [bookingselect shortcode ...] $params['resource_id'] = implode(',',range(1,17));
56
57 // <editor-fold defaultstate="collapsed" desc=" = CACHE - GET :: check if such request was cached and get it = " >
58
59 $params_for_cache = maybe_serialize( $params );
60 $cache_result = wpbc_cache__get( 'wpbc__sql__get_booking_dates', $params_for_cache );
61 if ( ! is_null( $cache_result ) ) {
62 return $cache_result;
63 }
64
65 // </editor-fold>
66
67 global $wpdb;
68
69 $defaults = array(
70 'dates_to_check' => 'CURDATE' // 'CURDATE' | 'ALL' | [ '2023-07-15' , '2023-07-21' ]
71 , 'approved' => 'all' // 'all' | 0 | 1
72 , 'resource_id' => '' // INT
73 , 'additional_bk_types' => array() // arrays only
74 , 'skip_booking_id' => '' // CSD '3,5'
75 , 'as_single_resource' => false // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'
76 );
77 $params = wp_parse_args( $params, $defaults );
78
79
80 // Convert $params['additional_bk_types'] and $params['resource_id'] to one CSD variable or default '1' if all empty
81 $resource_id__arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'], $params['additional_bk_types'] );
82 $resource_id__csd = implode( ',', $resource_id__arr );
83
84 // S a n i t i z e
85 $resource_id__csd = wpbc_sanitize_digit_or_csd( $resource_id__csd );
86 $params['skip_booking_id'] = wpbc_sanitize_digit_or_csd( $params['skip_booking_id'] );
87 $params['approved'] = ( 'all' == $params['approved'] ) ? 'all' : intval( $params['approved'] );
88
89
90 $sql_trash_bookings = ' AND bk.trash != 1 ';
91 $sql_skip_bookings = ( '' == $params['skip_booking_id'] ) ? '' : " AND dt.booking_id NOT IN ( {$params['skip_booking_id']} ) ";
92 $sql_approved_bookings = ( 'all' == $params['approved'] ) ? '' : " AND dt.approved = {$params['approved']} ";
93
94 $or__sql_child_bookings_4_parent = ( ! $params['as_single_resource'] ) ? " OR bt.parent IN ( {$resource_id__csd} ) " : '' ;
95
96 $where_dates = wpbc_get__sql_where__for__dates( $params );
97
98 /**
99 * Description:
100 * OR dt.type_id IN ( {$resource_id__csd} )
101 * It is means that sometimes bookings can be started in one booking resource,
102 * and in future dates can be finished in other 'child' booking resource(s).
103 * It's possible, when 'main' booking resource, where booking was started
104 * has future dates as 'unavailable' or booked
105 *
106 * OR dt.type_id IN ( {$resource_id__csd} )
107 * It's means that this booking belong to child booking resource, and do not belong to parent booking resource!
108 */
109
110 if ( class_exists('wpdev_bk_biz_l') ) {
111
112 $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
113 FROM {$wpdb->prefix}bookingdates as dt
114
115 INNER JOIN {$wpdb->prefix}booking as bk
116 ON bk.booking_id = dt.booking_id
117
118 INNER JOIN {$wpdb->prefix}bookingtypes as bt
119 ON bk.booking_type = bt.booking_type_id
120
121 WHERE 1 = 1
122 {$where_dates}
123 AND (
124 bk.booking_type IN ( {$resource_id__csd} )
125 OR dt.type_id IN ( {$resource_id__csd} )
126 {$or__sql_child_bookings_4_parent}
127 )
128 {$sql_approved_bookings}
129 {$sql_trash_bookings}
130 {$sql_skip_bookings}
131 ORDER BY dt.booking_date";
132
133 // Explanation:
134 // OR bt.parent IN ( ... ) -> Bookings from CHILD booking resources
135 // OR dt.type_id IN ( ... ) -> Dates from other booking resources, which belong to this booking resource
136
137 } else if ( class_exists('wpdev_bk_biz_m') ) { // Here we get form for booking details.
138
139 $my_sql = "SELECT DISTINCT dt.booking_date, dt.approved, dt.booking_id, bk.booking_type as type, bk.form
140 FROM {$wpdb->prefix}bookingdates as dt
141
142 INNER JOIN {$wpdb->prefix}booking as bk
143 ON bk.booking_id = dt.booking_id
144
145 WHERE 1 = 1
146 {$where_dates}
147 AND bk.booking_type IN ( {$resource_id__csd} )
148 {$sql_approved_bookings}
149 {$sql_trash_bookings}
150 {$sql_skip_bookings}
151 ORDER BY dt.booking_date";
152
153 } else { // Fast request only for dates
154 $my_sql = "SELECT DISTINCT dt.booking_date, dt.approved, dt.booking_id, bk.booking_type as type
155 FROM {$wpdb->prefix}bookingdates as dt
156
157 INNER JOIN {$wpdb->prefix}booking as bk
158 ON bk.booking_id = dt.booking_id
159
160 WHERE 1 = 1
161 {$where_dates}
162 AND bk.booking_type IN ( {$resource_id__csd} )
163 {$sql_approved_bookings}
164 {$sql_trash_bookings}
165 {$sql_skip_bookings}
166 ORDER BY dt.booking_date";
167 }
168
169
170
171 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
172 $sql__dates_obj__arr = $wpdb->get_results( $my_sql );
173
174
175 // <editor-fold defaultstate="collapsed" desc=" = CACHE - SAVE :: = " >
176 $cache_result = wpbc_cache__save( 'wpbc__sql__get_booking_dates', $params_for_cache, $sql__dates_obj__arr );
177 // </editor-fold>
178
179 return $sql__dates_obj__arr;
180 }
181
182
183 /**
184 * Get SQL WHERE condition for Dates
185 *
186 * @param array $params [ 'dates_to_check' => 'CURDATE' ] | [ 'dates_to_check' => 'ALL' ] | [ 'dates_to_check' => [ '2023-07-15' , '2023-07-21' ] ]
187 *
188 * @return string ' AND ( dt.booking_date >= C URDATE() ) '
189 */
190 function wpbc_get__sql_where__for__dates( $params ){
191
192 $defaults = array(
193 'dates_to_check' => 'CURDATE' // 'CURDATE' | 'ALL' | [ '2023-07-15' , '2023-07-21' ]
194 );
195 $params = wp_parse_args( $params, $defaults );
196
197
198 if ( 'ALL' == $params['dates_to_check'] ) { // All dates -> ''
199
200 return '';
201
202 } else if ( 'CURDATE' == $params['dates_to_check'] ) { // Current dates -> CURDATE
203
204 return ' AND ( dt.booking_date >= ' . wpbc_sql_date_math_expr_explicit('', 'curdate') . ' ) ' ;
205
206 } else if ( is_array( $params['dates_to_check'] ) ) { // Specific Date(s).
207
208 // FixIn: 10.14.9.1.
209
210 // Sanitize and validate all incoming dates first.
211 $dates_to_check = wpbc_sanitize_dates_to_check( $params['dates_to_check'] );
212
213 // If nothing valid left – do not add any date filter (or return empty string).
214 if ( empty( $dates_to_check ) ) {
215 return '';
216 }
217
218 global $wpdb;
219
220 $count_dates = count( $dates_to_check );
221
222 // Case 1: date range (2 items: start / end).
223 if ( 2 === $count_dates ) {
224 $start = $dates_to_check[0] . ' 00:00:00';
225 $end = $dates_to_check[1] . ' 23:59:59';
226
227 // %s will be properly escaped and quoted by $wpdb->prepare().
228 $dates_sql_str = $wpdb->prepare( ' ( ( dt.booking_date >= %s ) AND ( dt.booking_date <= %s ) ) ', $start, $end );
229
230 // Case 2: one date – from that day forward.
231 } else if ( 1 === $count_dates ) {
232
233 $start = $dates_to_check[0] . ' 00:00:00';
234
235 $dates_sql_str = $wpdb->prepare( ' ( dt.booking_date >= %s ) ', $start );
236
237 // Case 3: list of specific separate dates – OR between each day.
238 } else {
239
240 $conditions = array();
241 $values = array();
242
243 foreach ( $dates_to_check as $date ) {
244
245 $conditions[] = '( ( dt.booking_date >= %s ) AND ( dt.booking_date <= %s ) )';
246
247 $values[] = $date . ' 00:00:00';
248 $values[] = $date . ' 23:59:59';
249 }
250
251 $conditions_sql = implode( ' OR ', $conditions );
252
253 // $values is an array; $wpdb->prepare() will expand it safely.
254 $dates_sql_str = $wpdb->prepare( $conditions_sql, $values ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
255 }
256
257 return ' AND ( ' . $dates_sql_str . ' ) ';
258 }
259
260 // Default CURDATE
261 return ' AND ( dt.booking_date >= ' . wpbc_sql_date_math_expr_explicit('', 'curdate') . ' ) ';
262 }
263
264
265
266 /**
267 * Get array of "Booked Dates" as: ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
268 *
269 * @param array $params array(
270 * 'approved' => 'all' // 'all' | 0 | 1
271 * , 'resource_id' => '1' // arrays | CSD | int
272 * , 'additional_bk_types' => array() OPTIONAL // arrays | CSD | int
273 * , 'skip_booking_id' => '' // CSD '3,5'
274 * )
275 *
276 * @return array [ [2023-08-09]: [ [3]: [ '43211 - 86392': object( 'booking_date' => 2023-08-09 12:00:01 ... ), ... ], ... ], [2023-08-10]: ... ]
277 *
278 * Explanation:
279 * [2023-08-09]: [
280 * [3]: [
281 * '43211 - 86392': object(
282 * [booking_date] => 2023-08-09 12:00:01
283 * [approved] => 0
284 * [date_res_type] =>
285 * [booking_id] => 65
286 * [form] => text^selected_short_dates_hint3^August 10...
287 * [parent] => 0
288 * [prioritet] => 30
289 * [type] => 3
290 * [__summary__booking] : [
291 *
292 * [sql__booking_dates__arr] : [
293 * [1691668811] => 2023-08-10 12:00:01
294 * [1691675992] => 2023-08-10 14:00:02
295 * ]
296 * [__dates_obj] => WPBC_BOOKING_DATE Object(
297 * [readable_dates]: [ '2023-08-10': [ 12:00:01 - 14:00:02 ] ]
298 * [is_debug] => 0
299 * )
300 * [__dates_obj__bm__extended] => WPBC_BOOKING_DATE_EXTENDED Object (
301 * [readable_dates] : [
302 * [2023-08-09] : [ 12:00:01 - 24:00:00 ]
303 * [2023-08-10] : [ 00:00:00 - 24:00:00 ]
304 * [2023-08-11] : [ 00:00:00 - 24:00:00 ]
305 * [2023-08-12] : [ 00:00:00 - 24:00:00 ]
306 * [2023-08-13] : [ 00:00:00 - 14:00:02 ]
307 * ]
308 * [is_debug] => 0
309 * [extended_dates_times_arr] : []
310 * [debug_dates_times_arr] : []
311 * )
312 * [sql__booking_dates__arr__extended] : [
313 * [1691582401] => 2023-08-09 12:00:01
314 * [1691625600] => 2023-08-10 00:00:00
315 * [1691712000] => 2023-08-11 00:00:00
316 * [1691798400] => 2023-08-12 00:00:00
317 * [1691935202] => 2023-08-13 14:00:02
318 * ]
319 *
320 * ]
321 * )
322 * '64811 - 86392': object(
323 * [booking_date] => 2023-08-09 18:00:01
324 * [approved] => 0
325 * [date_res_type] =>
326 * [booking_id] => 66
327 * ....
328 * )
329 *
330 * ]
331 *
332 * ]
333 *
334 * [2023-08-10]: [ ... ]
335 * ...
336 *
337 * Example 1:
338 * $booked_dates__per_resources__arr = wpbc_get__booked_dates__per_resources__arr( array( 'resource_id' => $type_id ) );
339 * Example 2:
340 * $booked_dates__per_resources__arr = wpbc_get__booked_dates__per_resources__arr(
341 * 'approved' => 'all' // 'all' | 0 | 1
342 * , 'resource_id' => '1' // arrays | CSD | int
343 * , 'additional_bk_types' => array() // arrays | CSD | int
344 * , 'skip_booking_id' => '' // int | '' // CSD
345 * );
346 *
347 *
348 *
349 *
350 * $booked_dates__resources__seconds__arr[ '2023-08-08' ][ 'resource_id' ][ 'time_seconds_range' ] = Booking Date Object()
351 *
352 * Seconds: [36011 - 43192] - [start_time_second - end_time_second]
353 * Seconds: [0] - FULL DAY Booking
354 *
355 * Day start at ( 10 + 1 ) second
356 * Day End at ( ( 24 * 60 * 60 ) - 10 + 2 ) second
357 *
358 * To prevent intersections:
359 * Each booking Start time has +10 seconds
360 * Each booking End time has -10 seconds
361 * So real time here [36011 - 43192] is [ 36001 - 43202 ]
362 *
363 * Full day booking end with 0
364 * Start time booking end with 1
365 * End time booking end with 2
366 */
367 function wpbc_get__booked_dates__per_resources__arr( $params ){
368
369 $defaults = array(
370 'dates_to_check' => 'CURDATE' // 'CURDATE' | 'ALL' | [ '2023-07-15' , '2023-07-21' ]
371 , 'approved' => ( ( get_bk_option( 'booking_is_show_pending_days_as_available' ) == 'On' ) ? '1' : 'all' ) // 'all' | 0 | 1
372 , 'resource_id' => '1' // arrays | CSD | int
373 , 'additional_bk_types' => array() // arrays | CSD | int // OPTIONAL
374 , 'skip_booking_id' => wpbc_get_booking_id__from_hash_in_url() // int | '' // CSD '3,5'
375 , 'as_single_resource' => false // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'
376 , 'is_days_always_available' => ( ( 'On' == get_bk_option( 'booking_is_days_always_available' ) ) ? true : false )
377
378 , 'aggregate_params' => array() //Optional. It can contain: [ 'aggregate_resource_id_arr' => [ 4 ] , 'resource_id__with_children__arr' => [3,25] ]
379 );
380 $params_for_dates = wp_parse_args( $params, $defaults );
381
382
383 // $params_for_dates['is_days_always_available'] = in_array( $params_for_dates['resource_id'], array( '1' ) ); // Set some resources as always avavailable.
384
385 if ( $params_for_dates['is_days_always_available'] ) { // All bookings showing as available dates.
386 return array();
387 }
388
389
390 /**
391 * 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, .. }, .. ]
392 *
393 * Example: [
394 [0] => stdClass Object ( [booking_date] => 2023-08-08 10:00:01
395 [approved] => 0
396 [date_res_type] =>
397 [booking_id] => 45
398 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^selected_short_dates_hint2^...
399 [parent] => 0
400 [prioritet] => 20
401 [type] => 2
402 )
403 [1] => stdClass Object (
404 [booking_date] => 2023-08-08 10:00:01
405 [approved] => 0
406 [date_res_type] =>
407 [booking_id] => 46
408 [form] => selectbox-one^rangetime10^10:00 - 12:00~text^selected_short_dates_hint10^...
409 [parent] => 2
410 [prioritet] => 1
411 [type] => 10
412 ), ...
413 ]
414 */
415 $sql__b_dates__arr = wpbc__sql__get_booking_dates( $params_for_dates );
416
417
418 /**
419 * 2. From SQL dates into: [ > resource_id < ][ > booking_id < ] -> __summary__booking['sql__booking_dates__arr'] = [ [ '>seconds<' ]: '> SQL DATE <' , ... ]
420 * [1693303211] => 2023-08-29 10:00:01
421 * [1693353600] => 2023-08-30 00:00:00
422 * [1693483192] => 2023-08-31 12:00:02
423 * ]
424 */
425 $resources__booking_id__obj = wpbc_support__transform__into__resource_booking_dates__arr(
426 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 ) );
427
428
429 /**
430 * 2.0 Transfer AGGREGATE resource bookings to Main resources
431 *
432 *
433 */
434 if ( ! empty( $params['aggregate_params'] ) ) {
435 $resources__booking_id__obj = wpbc_aggregate__merge_bookings__from_aggregate__in_source_resource__arr(
436 $resources__booking_id__obj,
437 $params['aggregate_params']['resource_id__with_children__arr'],
438 $params['aggregate_params']['aggregate_resource_id_arr']
439 );
440 }
441
442
443 /**
444 * 2.1 Get [ > resource_id < ][ > booking_id < ] -> __summary__booking[ '_readable_dates' ] = [ '2023-08-01': [ 0: "10:00:01 - 12:00:02" ], ...
445 * '2023-08-05': [ 0: "10:00:01 - 12:00:02" ], ...
446 * ]
447 */
448 $resources__booking_id__obj = wpbc__in_all_bookings__create_WPBC_BOOKING_DATE( $resources__booking_id__obj );
449
450
451 /**
452 * 2.2 Extend check in/out dates [ > resource_id < ][ > booking_id < ] -> __summary__booking[ 'sql__booking_dates__arr__extended' ]
453 */
454 if ( function_exists( 'wpbc__extend_availability__before_after__check_in_out' ) ) {
455
456 $resources__booking_id__obj = wpbc__extend_availability__before_after__check_in_out( $resources__booking_id__obj );
457 }
458
459
460 /**
461 * 3. Into: ['2024-01-28'][ > resource_id < ][ > booking_id < ][ > only_time_seconds < ] => obj( booking_date: "2024-01-28 10:00:01", ... )
462 *
463 * From: [ > resource_id < ][ > booking_id < ] => obj( booking_date: "2024-01-28 10:00:01", ['__summary__booking']['sql__booking_dates__arr'][] , ... )
464 */
465 $dt__res__bk__seconds__arr = wpbc_support__transform__into__date_resource_booking_timesec__arr(
466 array( 'resource_booking_dates_arr' => $resources__booking_id__obj , 'is_apply__check_in_out__10s' => true ) );
467
468
469 /**
470 * 4. Into: ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
471 *
472 * , where 'time_seconds_range' can be: '0' | '36011 - 43192', ...
473 */
474 $dt__res__time_seconds_range__arr = wpbc_support__transform__into__date_resource_timesec_range__arr(
475 array( 'date_resource_booking_timesec_arr' => $dt__res__bk__seconds__arr , 'is_apply__check_in_out__10s' => true ) );
476
477 return $dt__res__time_seconds_range__arr;
478 }
479
480 // </editor-fold>
481
482
483 // -----------------------------------------------------------------------------------------------------------------
484 // Get Resource array filled by booked Dates
485 // -----------------------------------------------------------------------------------------------------------------
486
487
488 /**
489 * 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, ...
490 *
491 * @param int $single_or_parent__resource_id // 1 --- INT (currently it's works only for one resource (single or parent)
492 * 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
493 *
494 * @return array {
495 * calendar_2: {
496 * id: 2
497 * dates: { "2023-07-21": {…}
498 * "2023-07-22": {
499 * ['summary']['status_for_bookings']: "pending"
500 * ['summary']['status_for_day']: "available"
501 * day_availability: 4
502 * max_capacity: 4
503 * statuses: Object { day: "check_in|check_in|available|available", bookings: "approved|pending||" }
504 *
505 * 2: Object { is_day_unavailable: false, _day_status: "check_in", check_in_out: "check_in", … }
506 * 10: Object { is_day_unavailable: false, _day_status: "check_in", check_in_out: "check_in", … }
507 * 11: Object { is_day_unavailable: false, _day_status: "available", pending_approved: [] }
508 * 12: Object { is_day_unavailable: false, _day_status: "available", pending_approved: [] }
509 * }
510 * , "2023-07-23": {…}
511 * , …
512 * }
513 * }
514 * calendar_5: {...}
515 * , ...
516 * }
517 *
518 *
519 * Important Dates properties:
520 *
521 * ['summary']['status_for_bookings']: "" | "pending" | "approved"
522 * ['summary']['status_for_day']: | 'available';
523 * | 'time_slots_booking';
524 * | 'full_day_booking';
525 * | 'season_filter';
526 * | 'resource_availability';
527 * | 'weekday_unavailable'; 'from_today_unavailable' | 'limit_available_from_today'
528 * | 'change_over';
529 * | 'check_in';
530 * | 'check_out';
531 * | 'change_over check_out' .... variations....
532 *
533 *
534 * @return array array(
535 'dates' => $availability_per_day like ['2023-08-17'] = ...
536 , 'resources_id_arr__in_dates' => $source__resource_id_arr like [ 1,10,11,12,14]
537 )
538 */
539 function wpbc_get_availability_per_days_arr( $params ) {
540
541 if ( 0 ) { // FixIn: 9.8.3.1 ?
542 wpbc_set_limit_php( 300 ); // Set 300 seconds for php execution.
543 }
544
545 $server_request_uri = ( ( isset( $_SERVER['REQUEST_URI'] ) ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */
546 $server_http_referer_uri = ( ( isset( $_SERVER['HTTP_REFERER'] ) ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */
547
548 $defaults = array(
549 'dates_to_check' => 'CURDATE', // v: 'CURDATE' | 'ALL' | arr: '2023-07-15' , '2023-07-21'.
550 'approved' => ( ( 'On' === get_bk_option( 'booking_is_show_pending_days_as_available' ) ) ? '1' : 'all' ), // v: 'all' | 0 | 1.
551 'resource_id' => '1', // Single or parent booking resource!!!! // arrays | CSD | int ???.
552 'additional_bk_types' => array(), // arrays | CSD | int // OPTIONAL -> aggregate_resource_id_arr ... it is array of booking resources from aggregate shortcode parameter.
553 'skip_booking_id' => wpbc_get_booking_id__from_hash_in_url(), // int | '' // CSD '3,5'.
554 'as_single_resource' => false, // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'.
555 'max_days_count' => wpbc_get_max_visible_days_in_calendar(), // 365.
556 'timeslots_to_check_intersect' => array(), // arr: '12:20 - 12:55', '13:00 - 14:00' ) // TODO: ? do we really need it, because below we get it from function.
557 'request_uri' => ( ( ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) ? $server_http_referer_uri : $server_request_uri ), // front-end: $server_request_uri | ajax: $server_http_referer_uri // It different in Ajax requests. It's used for change-over days to detect for exception at specific pages.
558 'allow_past' => false,
559 'custom_form' => '', // Required for checking all available time-slots and compare with booked time slots.
560 'force_check_from_today_unavailable' => false, // Optional admin tools can force relative availability checks inside explicit date ranges.
561 );
562
563 $params = wp_parse_args( $params, $defaults );
564
565 // FixIn: 10.7.1.2. //FixIn: 10.10.3.2.
566 if (
567 ( ! empty( $params['allow_past'] ) ) ||
568 ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ||
569 (
570 wpbc_is_new_booking_page_url( $params['request_uri'] ) &&
571 ( false !== strpos( $params['request_uri'], 'booking_hash' ) )
572 )
573 ) {
574 $params['dates_to_check'] = 'ALL';
575 }
576
577 // -----------------------------------------------------------------------------------------------------------------
578 // R e s o u r c e (s) D a t a
579 // -----------------------------------------------------------------------------------------------------------------
580 // Get array of booking resource ID [1, 13, 8, 6, 7] or default: [ 1 ]
581 $source__resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'] ); // [1, 13, 8, 6, 7]
582 //$source__resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'], $params['additional_bk_types'] ); // [1, 13, 8, 6, 7]
583 $first_resource_id = $source__resource_id_arr[0]; // First from the list, or 1 if not provided.
584
585 // Get here Obj. of booking resource (which can include CHILD booking resources)
586 $resources_obj = new WPBC_RESOURCE_SUPPORT( array(
587 'resource_id' => $source__resource_id_arr, //CSD | D
588 'as_single_resource' => $params['as_single_resource'] // If true, then skip child booking resources
589 ));
590 // Resource ID arr (Can be Parent and Child resource ID)
591 $resource_id__with_children__arr = $resources_obj->get_resource_id_arr(); // [ 2, 10, 11, 12 ]
592
593 // Get Maximum capacity of resource
594 $resource_obj = $resources_obj->get__booking_resource_obj( $first_resource_id );
595 $max_resource_capacity_int = empty( $resource_obj ) ? 1 : $resource_obj->capacity; // 1 | 4
596
597 // Get base cost of resource
598 $resource_base_cost = $resources_obj->get_resources_base_cost_arr(); // [ 0, 25, 100, 99]
599
600
601
602
603 // -----------------------------------------------------------------------------------------------------------------
604 // Get real AGGREGATE resource ID arr
605 // -----------------------------------------------------------------------------------------------------------------
606 $real_resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['resource_id'] ); // [ 1 ]
607 if ( empty( $params['additional_bk_types'] ) ) {
608 $aggregate_resource_id_arr = array();
609 } else {
610 $aggregate_resource_id_arr = wpbc_get_unique_array_of_resources_id( $params['additional_bk_types'] ); // [1, 13, 8, 6, 7]
611 }
612 // Excluding from 'additional_bk_types' all resources in 'resource_id'
613 $aggregate_resource_id_arr = array_diff( $aggregate_resource_id_arr, $real_resource_id_arr ); // [ 13, 8, 6, 7 ]
614 $aggregate_resource_id_arr = array_values( $aggregate_resource_id_arr ); // reindex array, for ability to transfer array instead of obj to JS client side.
615
616 $params['aggregate_params'] = array(
617 'aggregate_resource_id_arr' => $aggregate_resource_id_arr,
618 'resource_id__with_children__arr' => $resource_id__with_children__arr
619 );
620
621 // -----------------------------------------------------------------------------------------------------------------
622 // B o o k i n g s
623 // -----------------------------------------------------------------------------------------------------------------
624 // Main function to get "Bookings": ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
625 $bookings__in_dates = wpbc_get__booked_dates__per_resources__arr( $params );
626
627 // -----------------------------------------------------------------------------------------------------------------
628 // Time slots availability blocks.
629 // -----------------------------------------------------------------------------------------------------------------
630 $availability_timeslots__in_dates = array(); // FixIn: 10.16.1.
631
632
633
634 // -----------------------------------------------------------------------------------------------------------------
635 // Booking > Availability page
636 // -----------------------------------------------------------------------------------------------------------------
637 $search_dates = $params['dates_to_check']; // 'CURDATE' | 'ALL' | [ "2023-08-03" , "2023-08-04" , "2023-08-05" ]
638
639 //FixIn: 9.8.15.10 Aggregate or not Aggregate Booking > Availability ? aggregate_type = 'all' | 'bookings_only'
640 if ( ( ! empty( $params['aggregate_type'] ) ) && ( 'bookings_only' === $params['aggregate_type'] ) ) { // FixIn: 9.9.0.16.
641 $unavailable_dates__per_resources__arr = wpbc_for_resources_arr__get_unavailable_dates(
642 $resource_id__with_children__arr, // Only One Primary Resource !!
643 $search_dates
644 ); // [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
645 } else {
646 $unavailable_dates__per_resources__arr = wpbc_for_resources_arr__get_unavailable_dates(
647 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
648 $search_dates
649 ); // [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
650 }
651 $unavailable_dates__per_resources__arr = wpbc_aggregate_merge_availability( $unavailable_dates__per_resources__arr,
652 $resource_id__with_children__arr,
653 $aggregate_resource_id_arr );
654 // FixIn: 10.16.1.
655 if ( function_exists( 'wpbc_availability_timeslots__get_intervals_for_resources' ) ) {
656 $availability_timeslots__resource_ids = wpbc_get_unique_array_of_resources_id( $resource_id__with_children__arr, $aggregate_resource_id_arr );
657 $availability_timeslots__in_dates = wpbc_availability_timeslots__get_intervals_for_resources(
658 array(
659 'resource_id' => $availability_timeslots__resource_ids,
660 'dates_to_check' => $search_dates,
661 'max_days_count' => $params['max_days_count'],
662 )
663 );
664
665 if ( function_exists( 'wpbc_availability_timeslots__aggregate_merge_intervals' ) ) {
666 $availability_timeslots__in_dates = wpbc_availability_timeslots__aggregate_merge_intervals(
667 $availability_timeslots__in_dates,
668 $resource_id__with_children__arr,
669 $aggregate_resource_id_arr
670 );
671 }
672 }
673
674 // -----------------------------------------------------------------------------------------------------------------
675 // Booking > Resources > Availability page
676 // -----------------------------------------------------------------------------------------------------------------
677 $season_filters_availability = array();
678 if ( class_exists('wpdev_bk_biz_m') ) {
679 foreach ( $resource_id__with_children__arr as $resource_id_for_season ) {
680 $season_filters_availability[ $resource_id_for_season ] = apply_bk_filter( 'get_available_days', $resource_id_for_season );
681 }
682 }
683
684
685
686
687 // -----------------------------------------------------------------------------------------------------------------
688 // P a r a m e t e r s f o r L O O P
689 // -----------------------------------------------------------------------------------------------------------------
690
691 // - Is this Booking > Add booking page ? --------------------------------------------------------------------------
692 $is_this_bap_page = wpbc_is_new_booking_page_url( $params['request_uri'] );
693 $is_this_hash_page = ( false !== strpos( $params['request_uri'], 'booking_hash' ) ) ? true : false; // Set it to TRUE for adding booking in past at Booking > Add booking page
694
695 // FixIn: 10.7.1.2.
696 if ( ! $is_this_hash_page ) {
697 $is_this_hash_page = ( ( ! empty( $params['allow_past'] ) ) || ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ) ? true : false;
698 }
699
700 if ( ( $is_this_bap_page ) && ( $is_this_hash_page ) ) { // Start days in calendar from = PAST
701 $params['dates_to_check'] = 'ALL';
702 }
703
704 if ( 'ALL' == $params['dates_to_check'] ) { // All dates -> ''
705
706 $start_day_number = - 1 * $params['max_days_count'];
707 //$today_inix_timestamp = strtotime( '-' . intval( $params['max_days_count'] ) . ' days' ); // - 300 days
708
709 // Get time, relative to Timezone from WordPress > Settings General page // FixIn: 9.9.0.17.
710 $start_date_unix = strtotime( '-' . intval( $params['max_days_count'] ) . ' days' ); // - 365 days
711 $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( gmdate( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' );
712 $today_inix_timestamp = strtotime( $date_with_wp_timezone );
713
714 } else if ( 'CURDATE' == $params['dates_to_check'] ) { // Current dates -> CURDATE
715
716 $start_day_number = 1;
717 // $today_inix_timestamp = strtotime( gmdate( 'Y-m-d 00:00:00', strtotime( 'now' ) ) ); // Today 00:00:00
718
719 // Get time, relative to Timezone from WordPress > Settings General page // FixIn: 9.9.0.17.
720 $start_date_unix = strtotime( 'now' );
721 $date_with_wp_timezone = wpbc_datetime_localized__use_wp_timezone( gmdate( 'Y-m-d H:i:s', $start_date_unix ), 'Y-m-d 00:00:00' );
722 $today_inix_timestamp = strtotime( $date_with_wp_timezone );
723
724 } else if ( is_array( $params['dates_to_check'] ) ) {
725
726 $start_day_number = 1;
727
728 $today_inix_timestamp = strtotime( $params['dates_to_check'][0] . ' 00:00:00' ); // '2023-09-03 00:00:00'
729
730 $dif_in_days = strtotime( $params['dates_to_check'][ ( count( $params['dates_to_check'] ) - 1 ) ] . ' 00:00:00' )
731 - strtotime( $params['dates_to_check'][0] . ' 00:00:00' );
732
733 $dif_in_days = $dif_in_days / ( 24 * 60 * 60 );
734 $params['max_days_count'] = ceil( $dif_in_days ) + 1;
735 }
736
737
738 // Get Time Slots from booking form for Each date: [ '2023-10-25' => [ '12:20 - 12:55', '13:00 - 14:00' ], '2023-10-26' => [ ... ], ... ]
739 $readable_timeslots_arr__in_dates_arr__to_check_intersect = wpbc_get_times_fields_configuration__by_dates(
740 $first_resource_id, // Resource ID (used in case of MultiUser version for getting specific form for regular users)
741 $params['custom_form'], // Form name for getting time slots configuration
742 $today_inix_timestamp, // start_date_unix_timestamp
743 ( $params['max_days_count'] - $start_day_number ) // days_count
744 );
745
746 // =================================================================================================================
747 // -- Here are GO
748 // =================================================================================================================
749 $availability_per_day = array();
750
751 for ( $day_num = $start_day_number; $day_num <= $params['max_days_count']; $day_num ++ ) {
752
753 $my_day_tag = gmdate( 'Y-m-d', $today_inix_timestamp ); // '2023-07-19'
754
755
756 //--------------------------------------------------------------------------------------------------------------
757 // Get Time-Slots from booking form to CHECK INTERSECT :: Convert readable time slot to time slot as seconds [ '12:20 - 12:55', '13:00 - 14:00' ] OR [] if not time slots
758 $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 );
759 /*
760 // TODO: check this, if it's required ? // If empty, maybe get default 'timeslots_to_check_intersect' from root of this function parameters ????
761 if ( empty( $as_seconds_timeslots_arr__to_check_intersect ) ) {
762
763
764 if ( ! is_array( $params[ 'timeslots_to_check_intersect' ] ) ) { // Root parameters from this function
765 $params[ 'timeslots_to_check_intersect' ] = array( $params[ 'timeslots_to_check_intersect' ] );
766 }
767
768 $as_seconds_timeslots_arr__to_check_intersect = array();
769 foreach ( $params[ 'timeslots_to_check_intersect' ] as $time_slot_readable ) {
770 $as_seconds_timeslots_arr__to_check_intersect[] = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $time_slot_readable );
771 }
772 }
773 */
774 //--------------------------------------------------------------------------------------------------------------
775
776
777 $availability_per_day[ $my_day_tag ] = array();
778
779 // 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
780 $availability_per_day[ $my_day_tag ]['day_availability'] = $max_resource_capacity_int; // 4
781 $availability_per_day[ $my_day_tag ]['max_capacity'] = $max_resource_capacity_int; // 4
782 $availability_per_day[ $my_day_tag ]['statuses'] = array();
783 $availability_per_day[ $my_day_tag ]['statuses']['day_status'] = array(); // per each child booking resource
784 $availability_per_day[ $my_day_tag ]['statuses']['bookings_status'] = array(); // per each child booking resource
785 $availability_per_day[ $my_day_tag ]['summary'] = array();
786 $availability_per_day[ $my_day_tag ]['summary']['status_for_day'] = ''; // available | time_slots_booking | full_day_booking | ...
787 $availability_per_day[ $my_day_tag ]['summary']['status_for_bookings'] = ''; // pending | approved | CO: pending_pending | pending_approved | approved_pending | approved_approved
788 $availability_per_day[ $my_day_tag ]['summary']['status_for_bookings_arr'] = array(); // Structured statuses array, e.g. array( 'approved', 'approved_approved' ).
789 $availability_per_day[ $my_day_tag ]['summary']['tooltip_times'] = '';
790 $availability_per_day[ $my_day_tag ]['summary']['tooltip_availability'] = '';
791 $availability_per_day[ $my_day_tag ]['summary']['tooltip_day_cost'] = '';
792 $availability_per_day[ $my_day_tag ]['summary']['tooltip_booking_details'] = '';
793
794
795 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
796 // R E S O U R C E S - S t a r t
797 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
798 foreach ( $resource_id__with_children__arr as $resource_id ) { // [1, 13, 8, 6, 7]
799
800 $availability_per_day[ $my_day_tag ][ $resource_id ] = new stdClass();
801 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = false;
802 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'available';
803 $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array();
804 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips = array(
805 'resource_title' => $resources_obj->get_resource_title( $resource_id ),
806 'times' => '',
807 'details' => array()
808 );
809 $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots = array(
810 'in_seconds' => array(), // seconds
811 'readable24h' => array(), // readable 24H - for debug only
812 'merged_seconds' => array(), // seconds (reduced number of time_ranges)
813 'merged_readable' => array() // readable 12AM
814 );
815 // Day Cost / Rates ---------------------------------------------------------------------------------------
816 $fin_day_cost = wpbc_support_capacity__get_day_cost( $my_day_tag, $resource_id, $resource_base_cost[ $resource_id ] );
817 $availability_per_day[ $my_day_tag ][ $resource_id ]->date_cost_rate = $fin_day_cost;
818
819
820 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
821 // B O O K I N G S - S t a r t
822 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
823
824 if ( ( isset( $bookings__in_dates[ $my_day_tag ] ) )
825 && ( isset( $bookings__in_dates[ $my_day_tag ][ $resource_id ] ) ) ){
826
827 $this_date_bookings = $bookings__in_dates[ $my_day_tag ][ $resource_id ]; // [ [36011 - 86392] => stdClass Object( [approved] => 1 , ... ) ,... ]
828 ksort( $this_date_bookings );
829 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = $this_date_bookings;
830
831 } else {
832 $this_date_bookings = array();
833 }
834
835
836 /**
837 * If bookings exist then:
838 * 1. Removing some properties here to hide personal details,
839 * 2. Set Approved / Pending status of the bookings
840 * 3. By default, set "_day_status" as 'time_slots_booking' ( later we will change to 'full_day_booking', if applied )
841 */
842 if ( ! empty( $this_date_bookings ) ) {
843
844 // =====================================================================================================
845 // T i m e s - Start
846 // =====================================================================================================
847 foreach ( $this_date_bookings as $booked_times__key => $booked_times__value ) {
848
849 // By default, set "_day_status" as 'time_slots_booking' ( later we will change to 'full_day_booking', if applied )
850 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'time_slots_booking';
851
852 // -------------------------------------------------------------------------------------------------
853 // Get Time-Slot
854 if ( false === strpos( $booked_times__key, '-' ) ) { // Full day ? - 0 == $booked_times__key
855 $time_range__seconds__arr = array( 0, 86400 ); // 24 * 60 * 60
856 } else {
857 $time_range__seconds__arr = wpbc_transform_timerange__s_range__in__seconds_arr( $booked_times__key ); // '43211 - 86392' into [43211, 86400]
858 }
859
860 // Real time: [43211, 86400]
861 $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['in_seconds'][] = $time_range__seconds__arr;
862
863 // For DEBUG only -- Readable 24H: '10:00:01 - 12:30:02'
864 $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 );
865
866 // -------------------------------------------------------------------------------------------------
867 // 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
868 $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved[ $time_range__seconds__arr[0] ] = ( '1' == $booked_times__value->approved ) ? 'approved' : 'pending';
869
870
871 // T O O L T I P :: Booking Details
872 $booked_time_title = ( ( 0 == $time_range__seconds__arr[0] ) && ( $time_range__seconds__arr[1] >= 86400 ) )
873 ? __( 'Full day', 'booking' )
874 : wpbc_transform_timerange__seconds_arr__in__formated_hours( $time_range__seconds__arr );
875 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip__set_for_details( $availability_per_day, $my_day_tag, $resource_id,
876 $this_date_bookings, $booked_times__key, $resources_obj, $booked_time_title );
877
878 // Unset ...->form and other fields...
879 $this_date_bookings[ $booked_times__key ] = wpbc_support_capacity__unset_some_fields( $this_date_bookings[ $booked_times__key ] );
880
881 } // T i m e s - E n d Booked Times Loop - for current resource
882
883
884 // =====================================================================================================
885 // Merge intersected time intervals =
886 // =====================================================================================================
887 $merged_seconds_arr = wpbc_merge_intersected_intervals( $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['in_seconds'] );
888
889 $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_seconds'] = $merged_seconds_arr;
890
891 foreach ( $merged_seconds_arr as $booked_time_slots__in_seconds ) {
892 $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 );
893 }
894
895 // T O O L T I P :: Times
896 $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 );
897
898 // =====================================================================================================
899 // End times
900 // =====================================================================================================
901
902
903 // 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...
904 ksort( $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved );
905
906 // array_keys( $booked_time_slots ) can be: [0] -> 'Full day' | ['36011 - 43192', '56011 - 86392'] -> '10:00 - 12:00', '15:55 - 24:00'
907 $booked_time_slots = array_keys( $this_date_bookings );
908
909
910 // =====================================================================================================
911 // Full day booking ----------------------------------------------------------------------------------- full_by_bookings
912 // =====================================================================================================
913 if ( in_array( '0', $booked_time_slots ) ) {
914
915 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
916 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'full_day_booking';
917
918 // Reset all other possible time slot statuses, in general they must not exist, but for some case
919 $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array();
920
921 // Pending or approved, for full day booking: $this_date_bookings['0']
922 $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved[] = ( '1' == $this_date_bookings['0']->approved ) ? 'approved' : 'pending';
923
924 // T O O L T I P :: Times - Full Day Booked
925 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
926 , $resource_id__with_children__arr, __( 'Full day', 'booking' ) );
927
928 } // end 'full day' if
929
930
931 // =====================================================================================================
932 // All time slots booked ? -----------------------------------------------------------------------------
933 // =====================================================================================================
934 if (
935 ( ! empty( $as_seconds_timeslots_arr__to_check_intersect ) ) // We need to check intersection with some time slot '36011 - 43192'
936 && ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) // And this date still free false
937 ){
938
939 $is_some_timeslot_available = wpbc_is_some_timeslot__available__in_arr( $as_seconds_timeslots_arr__to_check_intersect, $booked_time_slots );
940
941 // ------------------------------------------------------------------------------------------------- full_by_bookings
942 if ( ! $is_some_timeslot_available ) {
943 // All time slots booked !!!
944
945 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
946 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'full_day_booking';
947 $availability_per_day[ $my_day_tag ][ $resource_id ]->_booking_form_timeslots_unavailable = implode( '|', $params[ 'timeslots_to_check_intersect' ] );
948
949 // T O O L T I P :: Times - Full Day Booked
950 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
951 , $resource_id__with_children__arr, __( 'Full day', 'booking' ) );
952 } else {
953 // Some time slots available or there is no time slot passed in this function
954 }
955
956 } // end 'all time slots booked' if
957
958
959
960 // =====================================================================================================
961 // Change over days =
962 // =====================================================================================================
963 if (
964 ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) )
965 && ( wpbc_is_booking_used_check_in_out_time( $params[ 'request_uri' ], $resource_id ) )
966 && ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) // And this date still free false
967 ) {
968
969 /**
970 * "Change over days" - possible situations: check_in | check_out | change_over | ...
971 *
972 * $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = check_in
973 * | check_out
974 * | change_over
975 * | 'mixed'
976 * 'mixed' - e.g. 'change_over check_out' where several child resources and some is 'change_over' and others are 'check_out'
977 *
978 *
979 * Possible situations for change-over days:
980 *
981 * // A. If in $booked_time_slots array one of values (or in $this_date_bookings one of keys)
982 * // 1. Started with time that is ended with 1 second
983 * // 2. and Ended with '24:00' it is means '86392', like this: '28811 - 86392'
984 * // then it's means that we have 'check_in' time here
985 *
986 * // B. If in $booked_time_slots array one of values (or in $this_date_bookings one of keys)
987 * // 1. Started with '00:00' it is means '1'
988 * // 2. and Ended time that is ended with 2 second
989 * // like this: '1 - 32402'
990 * // then it's means that we have 'check_out' time here
991 *
992 * // C. If we have A. and B. then we have 'change_over' here
993 */
994
995 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array();
996
997 foreach ( $this_date_bookings as $booked_times__key => $booked_times__value ) {
998
999 if ( false === strpos( $booked_times__key, '-' ) ) {
1000 continue; // for situation with FULL day booking, here $booked_times__key = 0
1001 }
1002
1003 $rangeA_arr = explode( '-', $booked_times__key );
1004 $rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
1005 $rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
1006
1007 // start time
1008 $is_starttime__check_in = $rangeA_arr[0] % 10; // 0, 1, 2
1009 $is_starttime__check_in = ( 1 == $is_starttime__check_in ) ? true : false;
1010
1011 // end time
1012 $is_endtime__check_out = $rangeA_arr[1] % 10;
1013 $is_endtime__check_out = ( 2 == $is_endtime__check_out ) ? true : false;
1014
1015
1016 if ( ( $is_starttime__check_in ) && ( WPBC_FULL_DAY_TIME_OUT == $rangeA_arr[1] ) ) { // A :: start_time - 86392 e.g. 14:00 - 24:00
1017 // only "check in" time here
1018 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out[] = 'check_in';
1019
1020 } else if ( ( WPBC_FULL_DAY_TIME_IN == $rangeA_arr[0] ) && ( $is_endtime__check_out ) ) { // B :: 1 - end_time e.g. 00:00 - 10:00
1021 // only "check out" time here
1022 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out[] = 'check_out';
1023 }
1024
1025 }
1026 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array_unique( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );
1027 $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.
1028
1029 if (
1030 ( in_array( 'check_in', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) )
1031 && ( in_array( 'check_out', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) )
1032 ) {
1033 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array( 'change_over' ); // both check in / out times here
1034 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1035
1036 // Possible statuses: pending_pending | pending_approved | approved_pending | approved_approved
1037 $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array( implode( '_', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved ) );
1038 }
1039
1040 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );
1041
1042 if ( ! empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) ) {
1043 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out;
1044 }
1045 } // end change-over if
1046
1047
1048 }
1049 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1050 // B O O K I N G S - E n d
1051 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1052 // Working Time applies only to time-based booking forms: rangetime, start/end, or start/duration.
1053 $working_time__timeslots_to_check_intersect = $as_seconds_timeslots_arr__to_check_intersect;
1054 if ( empty( $working_time__timeslots_to_check_intersect ) && ! empty( $params['timeslots_to_check_intersect'] ) ) {
1055 if ( ! is_array( $params['timeslots_to_check_intersect'] ) ) {
1056 $params['timeslots_to_check_intersect'] = array( $params['timeslots_to_check_intersect'] );
1057 }
1058 $working_time__timeslots_to_check_intersect = array();
1059 foreach ( $params['timeslots_to_check_intersect'] as $time_slot_readable ) {
1060 $working_time__timeslots_to_check_intersect[] = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $time_slot_readable );
1061 }
1062 }
1063
1064 if (
1065 ! empty( $working_time__timeslots_to_check_intersect )
1066 && function_exists( 'wpbc_working_time__get_non_working_intervals_for_date' )
1067 && function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' )
1068 ) {
1069 $working_time__blocked_intervals = wpbc_working_time__get_non_working_intervals_for_date( $resource_id, $my_day_tag );
1070
1071 if ( ! empty( $working_time__blocked_intervals ) ) {
1072 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj(
1073 $availability_per_day[ $my_day_tag ][ $resource_id ],
1074 $working_time__blocked_intervals,
1075 $working_time__timeslots_to_check_intersect
1076 );
1077 }
1078 }
1079
1080 // FixIn: 10.16.1.
1081 if (
1082 function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' )
1083 && isset( $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ] )
1084 ) {
1085 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj(
1086 $availability_per_day[ $my_day_tag ][ $resource_id ],
1087 $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ],
1088 $as_seconds_timeslots_arr__to_check_intersect
1089 );
1090 }
1091
1092 //==========================================================================================================
1093 // $availability_per_day[..]->_day_status = 'season_filter' | ...
1094 //==========================================================================================================
1095 // Booking > Resources > Availability page >>> 'season_filter'
1096 $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 );
1097
1098 // Booking > Availability page >>> 'resource_availability'
1099 $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 );
1100
1101 if ( empty( $params['skip_general_availability'] ) ) {
1102 // Week Days unavailable >>> 'weekday_unavailable'
1103 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id );
1104 }
1105
1106 // if ( ( ! $is_this_bap_page ) || ( ! $is_this_hash_page ) ) {
1107 if ( empty( $params['skip_general_availability'] ) && ( ! $is_this_bap_page ) && ( ! $is_this_hash_page ) ) {
1108 // Do not apply these settings at Booking > Add booking page, when we edit booking - e.g. exist 'booking_hash'
1109
1110 // Skip checking unavailable from today, if defined the calendar_dates_start='2025-02-10' calendar_dates_end='2025-12-31' in shortcode. // FixIn: 10.13.1.4.
1111 $is_skip_check__from_today_unavailable = false;
1112 if ( is_array( $params['dates_to_check'] ) && empty( $params['force_check_from_today_unavailable'] ) ) {
1113 if ( ( ( count( $params['dates_to_check'] ) ) > 0 ) && ( wpbc_is_date_less_than( $params['dates_to_check'][0], $my_day_tag ) ) ) {
1114 $is_skip_check__from_today_unavailable = true;
1115 }
1116 if ( ( ( count( $params['dates_to_check'] ) ) > 1 ) && ( wpbc_is_date_higher_than( $params['dates_to_check'][1], $my_day_tag ) ) ) {
1117 $is_skip_check__from_today_unavailable = true;
1118 }
1119 }
1120
1121 if ( ! $is_skip_check__from_today_unavailable ) {
1122
1123 // Unavailable days from today >>> 'from_today_unavailable'.
1124 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id );
1125
1126 // Limit available days from today >>> 'limit_available_from_today'.
1127 $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 );
1128 }
1129 }
1130 //==========================================================================================================
1131
1132
1133 // T O O L T I P :: Times - Unavailable Day
1134 if ( in_array( $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status, array( 'season_filter',
1135 'resource_availability',
1136 'weekday_unavailable',
1137 'from_today_unavailable',
1138 'limit_available_from_today'
1139 ) )
1140 ){
1141 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
1142 , $resource_id__with_children__arr, __( 'Unavailable', 'booking' ) );
1143 }
1144
1145
1146 // =========================================================================================================
1147 // Entire D A Y statuses
1148 // =========================================================================================================
1149
1150 if ( $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) {
1151 // Set merged time interval as fully unavailable.
1152 $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_seconds'] = array( array( 0, 86400 ) ); // FixIn: 10.11.5.1.
1153 // Reduce DAY day_availability, if some season or days unavailable or full by bookings.
1154 --$availability_per_day[ $my_day_tag ]['day_availability'];
1155 }
1156
1157 // 'resource_availability' | 'weekday_unavailable' | 'from_today_unavailable' | 'limit_available_from_today' | 'season_filter' | 'full_day_booking' | 'time_slots_booking' | 'available'.
1158 $availability_per_day[ $my_day_tag ]['statuses']['day_status'][] = $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status;
1159
1160 // 'approved' | 'pending'.
1161 $availability_per_day[ $my_day_tag ]['statuses']['bookings_status'][] = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved );
1162
1163 // Go to next child booking resource.
1164 }
1165
1166 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1167 // R E S O U R C E S - E n d
1168 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1169
1170
1171 // -------------------------------------------------------------------------------------------------------------
1172 // Day summary :
1173 // -------------------------------------------------------------------------------------------------------------
1174 $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 );
1175
1176 // Go next day + 1 day
1177 $today_inix_timestamp += 24 * 60 * 60;
1178 }
1179
1180
1181 return array(
1182 'dates' => $availability_per_day
1183 , 'resources_id_arr__in_dates' => $resource_id__with_children__arr
1184 , 'aggregate_resource_id_arr' => $aggregate_resource_id_arr
1185 );
1186 }
1187
1188
1189 // <editor-fold defaultstate="collapsed" desc=" == S U P P O R T == " >
1190
1191
1192 // S U P P O R T
1193
1194 /**
1195 * Update Summary statuses for the Day
1196 *
1197 * @param $availability_per_this_day
1198 * @param $my_day_tag
1199 * @param $resource_id_arr
1200 *
1201 * @return mixed
1202 *
1203 *
1204 * Dates Status Concept Strategy ::
1205 *
1206 * Check date booking status based on 'all booking resources':
1207 * ( and as one common situation, when we have only 1 resource )
1208 *
1209 * | 'approved' - when all booking resources has approved FULL day bookings or some booking resource unavailable
1210 * | 'pending' - when at least one booking in one booking resource has pending status and there is no available booking resources
1211 * | 'times_partially_booked' - when at least one booking in one booking resource has time bookings and there is no available booking resources
1212 * and if all time slot approved then status approved
1213 * otherwise if at least one time slot booking has pending status then it has pending status
1214 *
1215 * if all 'time_slots' booked (it's time slot passed into function as parameter)
1216 * then such date in specific booking resource has pending or approved status, based on 'pending'|'approved' rule
1217 *
1218 * | 'check_in' - if activated 'change over days' and all bookings have 'check-in' status
1219 * | 'check_out' - if activated 'change over days' and all bookings have 'check-out' status
1220 * | if in booking resource exist both check in/out bookings, and activated 'change over days'
1221 * then such booking resource date has approved or pending status depends on from status of these bookings
1222 * | 'season_unavailable' - if all booking resources defined as unavailable at Booking > Resources > Availability page
1223 * | 'resource_unavailable' - if all booking resources defined as unavailable at Booking > Availability page
1224 * | 'other_unavailable' - if all booking resources defined as unavailable at Booking > Settings General page in "Availability" section
1225 *
1226 */
1227 function wpbc_update_summary_availability_per_this_day( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1228
1229 // -------------------------------------------------------------------------------------------------------------
1230 // Summary Tooltips
1231 // -------------------------------------------------------------------------------------------------------------
1232 $availability_per_this_day['summary']['tooltip_times'] = wpbc_support_capacity__tooltip__summary__times( $availability_per_this_day, $my_day_tag, $resource_id_arr );
1233 $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 );
1234 $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 );
1235 $availability_per_this_day['summary']['tooltip_availability'] = wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr );
1236
1237
1238 $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 );
1239 $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.
1240
1241 // -------------------------------------------------------------------------------------------------------------
1242 // ['summary']['status_for_day']
1243 // -------------------------------------------------------------------------------------------------------------
1244 $temp_status = array();
1245 foreach ( $availability_per_this_day['statuses']['day_status'] as $bookings_status_arr ) {
1246 $bookings_status_arr = explode( '|', $bookings_status_arr );
1247 foreach ( $bookings_status_arr as $bookings_status_element ) {
1248 $temp_status[] = $bookings_status_element;
1249 }
1250 }
1251 $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1252 $temp_status_counts = array_count_values( $temp_status );
1253 $temp_status = array_unique( $temp_status ); // Erase duplicates
1254 $availability_per_this_day['summary']['status_for_day'] = $temp_status;
1255
1256 /**
1257 * Possible day statuses (searched by value of _day_status):
1258 *
1259 * available
1260 * time_slots_booking
1261 * full_day_booking
1262 *
1263 * limit_available_from_today
1264 * from_today_unavailable
1265 * weekday_unavailable
1266 * resource_availability
1267 * season_filter
1268 *
1269 * change_over
1270 * check_out
1271 * check_in
1272 * 'mixed' from check_in/check_out/change_over
1273 */
1274
1275 // Priority: available > time_slots_booking > full_day_booking
1276 // > season_filter > resource_availability
1277 // > weekday_unavailable > from_today_unavailable > limit_available_from_today
1278
1279 // Capacity resources can be available even when every child has a check-in/out or full-day status.
1280 $max_capacity = isset( $availability_per_this_day['max_capacity'] ) ? intval( $availability_per_this_day['max_capacity'] ) : 1;
1281 $blocking_statuses = array(
1282 'full_day_booking',
1283 'season_filter',
1284 'resource_availability',
1285 'weekday_unavailable',
1286 'from_today_unavailable',
1287 'limit_available_from_today',
1288 'change_over',
1289 );
1290 $blocked_capacity = 0;
1291 foreach ( $blocking_statuses as $blocking_status ) {
1292 $blocked_capacity += isset( $temp_status_counts[ $blocking_status ] ) ? intval( $temp_status_counts[ $blocking_status ] ) : 0;
1293 }
1294 $booked_capacity__before_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_out'] ) ? intval( $temp_status_counts['check_out'] ) : 0 );
1295 $booked_capacity__after_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_in'] ) ? intval( $temp_status_counts['check_in'] ) : 0 );
1296 $is_capacity_available_during_change_over = (
1297 ( $max_capacity > 1 )
1298 && ( $max_capacity > max( $booked_capacity__before_check_in, $booked_capacity__after_check_in ) )
1299 && ( ! in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) )
1300 );
1301
1302 // if at least one resource is available then day has this status
1303 if ( in_array( 'available', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'available';
1304 } else if ( $is_capacity_available_during_change_over ) { $availability_per_this_day['summary']['status_for_day'] = 'available';
1305 } 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';
1306 } else if ( ( ! in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) )
1307 && ( in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) ) ) { $availability_per_this_day['summary']['status_for_day'] = 'check_in';
1308 } else if ( ( ! in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) )
1309 && ( in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) ) ) { $availability_per_this_day['summary']['status_for_day'] = 'check_out';
1310 } 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';
1311 } else if ( in_array( 'season_filter', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'season_filter';
1312 } else if ( in_array( 'resource_availability', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'resource_availability';
1313 } else if ( in_array( 'weekday_unavailable', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'weekday_unavailable';
1314 } 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';
1315 } 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';
1316 } else {
1317 $availability_per_this_day['summary']['status_for_day'] = implode( ' ', $availability_per_this_day['summary']['status_for_day'] );
1318 }
1319
1320
1321 // -------------------------------------------------------------------------------------------------------------
1322 // ['summary']['status_for_bookings']
1323 // -------------------------------------------------------------------------------------------------------------
1324 $temp_status = array();
1325 foreach ( $availability_per_this_day['statuses']['bookings_status'] as $bookings_status_arr ) {
1326 $bookings_status_arr = explode( '|', $bookings_status_arr );
1327 foreach ( $bookings_status_arr as $bookings_status_element ) {
1328 $temp_status[] = $bookings_status_element;
1329 }
1330 }
1331 $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1332 $temp_status = array_values( array_unique( $temp_status ) );
1333
1334 // Structured booking statuses contract. Keep numeric keys sequential so JSON encodes this as a JS array.
1335 $availability_per_this_day['summary']['status_for_bookings_arr'] = $temp_status;
1336
1337 // Priority: pending > approved > ''
1338
1339 // if at least one booking pending then day is pending
1340 if ( in_array( 'pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending';
1341 } else if ( in_array( 'pending_pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending';
1342 // Usual situations for change over days: pending_pending | pending_approved | approved_pending | approved_approved
1343 } else {
1344 $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ', $temp_status );
1345 }
1346
1347
1348 // -------------------------------------------------------------------------------------------------------------
1349 return $availability_per_this_day;
1350 }
1351
1352
1353 // T O O L T I P s
1354
1355 /**
1356 * Set tooltip summary -- Time-Slots
1357 *
1358 * @param $availability_per_this_day
1359 * @param $my_day_tag
1360 * @param $resource_id_arr
1361 *
1362 * @return string - tooltip content or ''
1363 */
1364 function wpbc_support_capacity__tooltip__summary__times( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1365
1366 $tooltip = '';
1367
1368 if ( 'On' != get_bk_option( 'booking_disable_timeslots_in_tooltip' ) ) { //FixIn: 9.5.0.2.2
1369
1370 $tooltip_title_word = get_bk_option( 'booking_highlight_timeslot_word' );
1371 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1372 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1373 ? ''
1374 : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';
1375
1376 $status_summary_tooltip_times = array();
1377 foreach ( $resource_id_arr as $resource_id ) {
1378 if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['times'] ) ) {
1379 $status_summary_tooltip_times[] = $availability_per_this_day[ $resource_id ]->tooltips['times'];
1380 }
1381 }
1382
1383 if ( ! empty( $status_summary_tooltip_times ) ) {
1384
1385 $tooltip = '<div class="wpbc_tooltip_section tooltip__times">'
1386 . $tooltip_title_word
1387 . implode( '', $status_summary_tooltip_times )
1388 . '</div>';
1389 }
1390 }
1391
1392 return $tooltip;
1393 }
1394
1395 function wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1396
1397 $tooltip = '';
1398
1399 if ( ( 'On' == get_bk_option( 'booking_is_show_availability_in_tooltips' ) ) && ( $availability_per_this_day['max_capacity'] > 1 ) ) {
1400
1401 $tooltip_title_word = get_bk_option( 'booking_highlight_availability_word' );
1402 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1403 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1404 ? ''
1405 : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';
1406
1407 $tooltip_content_header = '';
1408
1409 if ( ! empty( $availability_per_this_day['day_availability'] ) ) {
1410
1411 $tooltip = '<div class="wpbc_tooltip_section tooltip__availability">'
1412 . $tooltip_title_word
1413 . '<div class="wpbc_tooltip_resource_container">'
1414 . $tooltip_content_header
1415 . '<div class="wpbc_tooltip_item">'
1416 . $availability_per_this_day['day_availability']
1417 . '</div>'
1418 . '</div>'
1419 . '</div>';
1420 }
1421 }
1422 return $tooltip;
1423 }
1424
1425 function wpbc_support_capacity__tooltip__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1426
1427 $tooltip = '';
1428 if (
1429 ( ! empty( $availability_per_this_day['day_availability'] ) )
1430 && ( 'On' == get_bk_option( 'booking_is_show_cost_in_tooltips' ) )
1431 ){
1432
1433 $tooltip_title_word = get_bk_option( 'booking_highlight_cost_word' );
1434 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1435 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1436 ? ''
1437 : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';
1438
1439 if ( isset( $resource_id_arr[0] ) ) {
1440
1441 $id_of_first_resource = $resource_id_arr[0];
1442 $tooltip_content_header = '';
1443
1444 if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) {
1445
1446 $cur_sym = get_bk_option( 'booking_cost_in_date_cell_currency' ); // in Booking > Settings General page in "Calendar" section
1447 //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page
1448
1449 $cost_text = wpbc_formate_cost_hint__no_html( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate, $cur_sym );
1450 $cost_text = html_entity_decode( $cost_text );
1451
1452 $tooltip = '<div class="wpbc_tooltip_section tooltip__day_cost">'
1453 . $tooltip_title_word
1454 . '<div class="wpbc_tooltip_resource_container">'
1455 . $tooltip_content_header
1456 . '<div class="wpbc_tooltip_item">'
1457 . $cost_text
1458 . '</div>'
1459 . '</div>'
1460 . '</div>';
1461 }
1462
1463 }
1464 }
1465 return $tooltip;
1466 }
1467
1468
1469 function wpbc_support_capacity__in_day_hint__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1470
1471 $tooltip = '';
1472 if (
1473 ( ! empty( $availability_per_this_day['day_availability'] ) )
1474 && ( 'On' == get_bk_option( 'booking_is_show_cost_in_date_cell' ) )
1475 ){
1476
1477 $id_of_first_resource = $resource_id_arr[0];
1478
1479 if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) {
1480
1481 $cur_sym = get_bk_option( 'booking_cost_in_date_cell_currency' ); // in Booking > Settings General page in "Calendar" section
1482 //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page
1483
1484 $cost_text = $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate;
1485 $cost_text = number_format( floatval( $cost_text ), wpbc_get_cost_decimals(), '.', '' );
1486 $cost_text = wp_strip_all_tags( wpbc_cost_show( $cost_text, array( 'currency' => 'CURRENCY_SYMBOL' ) ) );
1487 $cost_text = str_replace( array( 'CURRENCY_SYMBOL', '&' ), array( $cur_sym, '&amp;' ), $cost_text );
1488 $cost_text = html_entity_decode($cost_text);
1489
1490 $tooltip = '<span class="wpbc_in_date_hint__cost">' . $cost_text . '</span>';;
1491 }
1492 }
1493 return $tooltip;
1494 }
1495
1496 // FixIn: 10.6.4.1.
1497 /**
1498 * Get availability for in Day cells
1499 *
1500 * @param $availability_per_this_day
1501 * @param $my_day_tag
1502 * @param $resource_id_arr
1503 *
1504 * @return string
1505 */
1506 function wpbc_support_capacity__in_day_hint__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1507
1508 $tooltip = '';
1509
1510 if (
1511 ( 'On' == get_bk_option( 'booking_is_show_availability_in_date_cell' ) ) &&
1512 ( $availability_per_this_day['max_capacity'] > 1 )
1513 ) {
1514
1515 $tooltip_title_word = get_bk_option( 'booking_highlight_availability_word_in_date_cell' );
1516 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1517 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1518 ? ''
1519 : '<span class="wpbc_in_date_hint__availability_title">' . $tooltip_title_word . '</span>';
1520
1521
1522 if ( ! empty( $availability_per_this_day['day_availability'] ) ) {
1523
1524 $tooltip = '<span class="wpbc_in_date_hint__availability">'
1525 . '<span class="wpbc_in_date_hint__availability_number">'
1526 . intval( $availability_per_this_day['day_availability'] )
1527 . '&nbsp;'
1528 . '</span>'
1529 . $tooltip_title_word
1530 . '</span>';
1531 $tooltip = html_entity_decode($tooltip);
1532 }
1533 }
1534 return $tooltip;
1535 }
1536
1537
1538
1539 /**
1540 * Set tooltip summary -- Booking Details
1541 *
1542 * @param $availability_per_this_day
1543 * @param $my_day_tag
1544 * @param $resource_id_arr
1545 *
1546 * @return string - tooltip content or ''
1547 */
1548 function wpbc_support_capacity__tooltip__summary__booked_details( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1549
1550 $tooltip = '';
1551
1552 if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) { //FixIn: 9.5.0.2.2
1553
1554 $tooltip_title_word = '<div class="wpbc_tooltip_title">' . esc_html__('Booking details','booking') . '</div>';
1555
1556 $status_summary_tooltip_times = array();
1557 foreach ( $resource_id_arr as $resource_id ) {
1558 if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['details'] ) ) {
1559
1560 if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['resource_title'] ) ){
1561 $tooltip_content_header = '<div class="wpbc_tooltip_header">'
1562 . $availability_per_this_day[ $resource_id ]->tooltips['resource_title'] . ': '
1563 . '</div>';
1564 } else{
1565 $tooltip_content_header = '';
1566 }
1567
1568 $booking_details_text = '<div class="wpbc_tooltip_resource_container">'
1569 . $tooltip_content_header
1570 . implode( ' ', $availability_per_this_day[ $resource_id ]->tooltips['details'] )
1571 . '</div>';
1572
1573 $status_summary_tooltip_times[] = $booking_details_text;
1574 }
1575 }
1576
1577 if ( ! empty( $status_summary_tooltip_times ) ) {
1578
1579 $tooltip = '<div class="wpbc_tooltip_section tooltip__booking_details">'
1580 . $tooltip_title_word
1581 . implode( '', $status_summary_tooltip_times )
1582 . '</div>';
1583 }
1584 }
1585 return $tooltip;
1586 }
1587
1588 /**
1589 * Set Tooltip -- Booking Details
1590 *
1591 * @param $availability_per_day
1592 * @param $my_day_tag
1593 * @param $resource_id
1594 * @param $this_date_bookings
1595 * @param $booked_times__key
1596 * @param $resources_obj
1597 *
1598 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
1599 */
1600 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 ) {
1601
1602 // Get booking details for tooltip, if needed
1603 if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) {
1604
1605 $booking_id = $this_date_bookings[ $booked_times__key ]->booking_id;
1606 $this_booking_resource_id = $this_date_bookings[ $booked_times__key ]->type;
1607
1608 $booking_details_text = wpbc_support_capacity__get_booking_details(
1609 $this_date_bookings[ $booked_times__key ],
1610 $resources_obj->get__booking_resource_obj( $this_booking_resource_id )
1611 );
1612 $tooltip_text = '';
1613 $tooltip_text .= '<div class="wpbc_tooltip_item tooltip_booked_time">' . $booked_time . '</div>'; // Booked time
1614 $tooltip_text .= '<div class="wpbc_tooltip_item">' . $booking_details_text . '</div>'; // Booking details
1615
1616 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['details'][ $booking_id ] = $tooltip_text;
1617 }
1618
1619 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1620 }
1621
1622 /**
1623 * Set Tooltip Times -- Time-Slots
1624 *
1625 * @param $availability_per_day
1626 * @param $my_day_tag
1627 * @param $resource_id
1628 * @param $resource_id_arr
1629 *
1630 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
1631 */
1632 function wpbc_support_capacity__tooltip_times__set_for_times( $availability_per_day, $my_day_tag, $resource_id, $resource_id_arr ){
1633
1634 // Times Tooltip - time slot list --------------------------------------------------------------------
1635 $tooltip_content_header = '';
1636
1637 if ( count( $resource_id_arr ) > 1 ) {
1638
1639 $class_name = 'tooltip_items_count_' . count( $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable'] );
1640
1641 $tooltip_content_header = '<div class="wpbc_tooltip_header ' . $class_name . ' ">'
1642 . $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['resource_title'] . ': '
1643 . '</div>';
1644 }
1645
1646 $tooltip_content_arr = array_map( function ( $item ) {
1647 return '<div class="wpbc_tooltip_item">' . $item . '</div>';
1648 }
1649 , $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable']
1650 );
1651
1652 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['times'] = '<div class="wpbc_tooltip_resource_container">'
1653 . $tooltip_content_header
1654 . implode( '', $tooltip_content_arr )
1655 . '</div>';
1656 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1657 }
1658
1659 /**
1660 * Set Tooltip Times -- Full Day
1661 *
1662 * @param $availability_per_day
1663 * @param $my_day_tag
1664 * @param $resource_id
1665 * @param $resource_id_arr
1666 * @param $status_title
1667 *
1668 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
1669 */
1670 function wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id, $resource_id_arr, $status_title ){
1671
1672 // Times Tooltip - FULL DAY --------------------------------------------------------------------
1673 $tooltip_content_header = '';
1674
1675 if ( count( $resource_id_arr ) > 1 ) {
1676
1677 $class_name = 'tooltip_items_count_1';
1678
1679 $tooltip_content_header = '<div class="wpbc_tooltip_header ' . $class_name . ' ">'
1680 . $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['resource_title'] . ': '
1681 . '</div>';
1682 }
1683
1684 $tooltip_content_text = '<div class="wpbc_tooltip_item">' . $status_title . '</div>';
1685
1686 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['times'] = '<div class="wpbc_tooltip_resource_container">'
1687 . $tooltip_content_header
1688 . $tooltip_content_text
1689 . '</div>';
1690 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1691 }
1692
1693
1694
1695 /**
1696 * Get parsed booking data, if required
1697 *
1698 * @param object $this_date_bookings
1699 * @param object $resource_obj
1700 *
1701 * @return string
1702 */
1703 function wpbc_support_capacity__get_booking_details( $this_date_bookings, $resource_obj ) {
1704
1705 if ( ( ! class_exists( 'wpdev_bk_biz_m' ) )
1706 || ( 'On' !== get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) )
1707 ){
1708 return '';
1709 }
1710
1711 $booking_details_for_hint = '';
1712
1713 if ( isset( $this_date_bookings->form ) ) {
1714
1715 // Get shortcodes
1716 $booking_shortcodes_in_tooltips = get_bk_option( 'booking_booked_data_in_tooltips' ); // '[name] [secondname]'
1717
1718 $resource_id = $this_date_bookings->type;
1719
1720 // Get parsed booking data field values -- e.g.: [ "rangetime":"12:00 - 14:00", "secondname":"Smith",... ]
1721 $booking_data_arr = wpbc_get_parsed_booking_data_arr( $this_date_bookings->form, $resource_id, array( 'get' => 'value' ) );
1722 $booking_data_arr['booking_id'] = $this_date_bookings->booking_id;
1723 $booking_data_arr['resource_id'] = $resource_id;
1724 $booking_data_arr['resource_title'] = ( ! empty( $resource_obj ) ) ? wpbc_lang( $resource_obj->title ) : '';
1725
1726 // Replace existing shortcodes
1727 foreach ( $booking_data_arr as $replace_shortcode => $replace_value ) {
1728
1729 if ( is_null( $replace_value ) ) { $replace_value = ''; };
1730
1731 $replace_value = wpbc_replace__true_false__to__yes_no( $replace_value ); // FixIn: 9.8.9.1.
1732
1733 $booking_shortcodes_in_tooltips = str_replace( array(
1734 '[' . $replace_shortcode . ']'
1735 , '{' . $replace_shortcode . '}'
1736 )
1737 , $replace_value
1738 , $booking_shortcodes_in_tooltips
1739 );
1740 }
1741
1742 $booking_details_for_hint = $booking_shortcodes_in_tooltips;
1743
1744 // Remove all shortcodes, which is not replaced early.
1745 $booking_details_for_hint = preg_replace( '/[\[\{][a-zA-Z0-9.,_-]{0,}[\]\}]/', '', $booking_details_for_hint );
1746 }
1747
1748 return $booking_details_for_hint;
1749 }
1750
1751
1752 /**
1753 * Unset some fields from booking data for do not show personal data at front-end side
1754 *
1755 * @param object $this_date_bookings
1756 *
1757 * @return object
1758 */
1759 function wpbc_support_capacity__unset_some_fields( $this_date_bookings ) {
1760
1761 if ( isset( $this_date_bookings->form ) ) {
1762 unset( $this_date_bookings->form ); // Hide booking details
1763 }
1764
1765 if ( isset( $this_date_bookings->booking_date ) ) {
1766 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
1767 }
1768
1769 return $this_date_bookings;
1770 }
1771
1772
1773 // D A Y S T A T U S U N A V A I L A B L E
1774
1775 /**
1776 * Set > _day_status = 'limit_available_from_today' depends on Booking > Settings General page ---> "Limit available days from today"
1777 *
1778 * @param $availability_per_day [ ... ]
1779 * @param $my_day_tag - '2023-08-08'
1780 * @param $resource_id - 2
1781 *
1782 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1783 */
1784 function wpbc_support_capacity__day_status__limit_available_from_today( $availability_per_day, $my_day_tag, $resource_id ){
1785
1786 // ----------------------------------------------------------------------------------------------------- // limit_available_from_today
1787 // 3. Limit available days from today
1788 if ( function_exists( 'wpbc_is_day_available__relative__limit_available_from_today' ) ) {
1789 if ( ! wpbc_is_day_available__relative__limit_available_from_today( $my_day_tag ) ) {
1790 // this date unavailable
1791 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1792 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'limit_available_from_today';
1793
1794 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1795 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1796 }
1797 }
1798 }
1799
1800 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1801 }
1802
1803
1804 /**
1805 * Set > _day_status = 'from_today_unavailable' depends on Booking > Settings General page ---> "Unavailable days from today"
1806 *
1807 * @param $availability_per_day [ ... ]
1808 * @param $my_day_tag - '2023-08-08'
1809 * @param $resource_id - 2
1810 *
1811 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1812 */
1813 function wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id ){
1814
1815 // FixIn: 10.8.1.4.
1816
1817 // ----------------------------------------------------------------------------------------------------- // from_today_unavailable
1818 // 2. Unavailable days from today
1819 $unavailable_days_num_from_today = get_bk_option( 'booking_unavailable_days_num_from_today' );
1820
1821 // FixIn: 10.8.1.4.
1822 if ( ! empty( $unavailable_days_num_from_today ) ) {
1823 if ( 'm' === substr( $unavailable_days_num_from_today, - 1 ) ) {
1824 $start_date_unix = strtotime( '+' . ( intval( $unavailable_days_num_from_today ) - 1 ) . ' minutes' ); // + 0 days
1825 } else {
1826 $start_date_unix = strtotime( '+' . intval( $unavailable_days_num_from_today ) . ' days' ); // + 0 days
1827 }
1828 } else {
1829 $start_date_unix = strtotime( 'now' );
1830 }
1831
1832 $date_start__gmt = gmdate( 'Y-m-d H:i:s', $start_date_unix ); // '2025-01-25 12:50:10'
1833 $date_start__midnight__wp_timezone = wpbc_datetime_localized__use_wp_timezone( $date_start__gmt, 'Y-m-d 00:00:00' ); // Local Midnight.
1834
1835 // 'Today Midnight' - 'Calendar Day Cell' .
1836 $days_number = intval( ( strtotime( $date_start__midnight__wp_timezone ) - strtotime( $my_day_tag ) ) / 86400 );
1837
1838 if ( $days_number > 0 ) {
1839 // This date Unavailable.
1840 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1841 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'from_today_unavailable';
1842
1843 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1844 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1845 }
1846 }
1847
1848 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1849 }
1850
1851
1852 /**
1853 * Set > _day_status = 'weekday_unavailable' depends on Booking > Settings General page ---> "Week Days unavailable"
1854 *
1855 * @param $availability_per_day [ ... ]
1856 * @param $my_day_tag - '2023-08-08'
1857 * @param $resource_id - 2
1858 *
1859 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1860 */
1861 function wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id ){
1862
1863 // 1. Week Days unavailable -------------------------------------------------------------------------------- // weekday_unavailable
1864 $unavailable_weekdays = array();
1865 foreach ( range( 0, 6 ) as $week_day_num ) {
1866 $unavailable_weekdays[ $week_day_num ] = ( 'On' == get_bk_option( 'booking_unavailable_day' . $week_day_num ) ) ? true : false;
1867 }
1868
1869 $this_day_week_num = gmdate( 'w', strtotime( $my_day_tag ) ); // 0 - 6
1870
1871 if ( $unavailable_weekdays[ $this_day_week_num ] ) {
1872 // this date unavailable
1873 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1874 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'weekday_unavailable';
1875
1876 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1877 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1878 }
1879 }
1880
1881 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1882 }
1883
1884
1885 /**
1886 * Set > _day_status = 'resource_availability' depends on Booking > Availability page
1887 *
1888 * @param $availability_per_day [ ... ]
1889 * @param $my_day_tag - '2023-08-08'
1890 * @param $resource_id - 2
1891 * @param array $unavailable_dates__per_resources__arr - [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
1892 *
1893 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1894 */
1895 function wpbc_support_capacity__day_status__resource_availability( $availability_per_day, $my_day_tag, $resource_id, $unavailable_dates__per_resources__arr ){
1896
1897 // Booking > Availability page ----------------------------------------------------------------------------- // resource_availability
1898 /**
1899 * $unavailable_dates__per_resources__arr = Array ( [2] => Array( [0] => 2023-08-01
1900 [1] => 2023-08-02
1901 )
1902 [10] => Array( [0] => 2023-08-05
1903 [1] => 2023-08-06
1904 )
1905 )
1906 */
1907 if (
1908 ( isset( $unavailable_dates__per_resources__arr[ $resource_id ] ) )
1909 && ( in_array( $my_day_tag, $unavailable_dates__per_resources__arr[ $resource_id ] ) )
1910 ) {
1911
1912 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1913 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'resource_availability';
1914
1915 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1916 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1917 }
1918 }
1919
1920 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1921 }
1922
1923
1924 /**
1925 * Set > _day_status = 'season_filter' depends on Booking > Resources > Availability page
1926 *
1927 * @param $availability_per_day [ ... ]
1928 * @param $my_day_tag - '2023-08-08'
1929 * @param $resource_id - 2
1930 * @param array $season_filters_availability - [...]
1931 *
1932 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1933 */
1934 function wpbc_support_capacity__day_status__season_filter( $availability_per_day, $my_day_tag, $resource_id, $season_filters_availability ){
1935
1936 if ( function_exists( 'wpbc_is_this_day_available_in_season_filters' ) ) { // BM and higher
1937
1938 $is_date_available = wpbc_is_this_day_available_in_season_filters( $my_day_tag, $resource_id, $season_filters_availability[ $resource_id ] ); // Get availability
1939 if ( ! $is_date_available ) {
1940
1941 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1942 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'season_filter';
1943
1944 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1945 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1946 }
1947 }
1948 }
1949
1950 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1951 }
1952
1953
1954 // D A Y C O S T
1955
1956 /**
1957 * Get day cost depend on Rates
1958 * @param $my_day_tag - '2023-08-08'
1959 * @param $resource_id - 2
1960 * @param $base_cost - 25
1961 *
1962 * @return int|string
1963 */
1964 function wpbc_support_capacity__get_day_cost( $my_day_tag, $resource_id, $base_cost ) {
1965
1966 $fin_day_cost = 0;
1967 if ( function_exists( 'wpbc_get_1_day_cost_apply_rates' ) ) {
1968
1969 list( $year, $month, $day ) = explode( '-', $my_day_tag );
1970
1971 $day = intval( $day );
1972 $month = intval( $month );
1973 $year = intval( $year );
1974
1975 $fin_day_cost = wpbc_get_1_day_cost_apply_rates( $resource_id, $base_cost, $day, $month, $year );
1976 }
1977
1978 return $fin_day_cost;
1979 }
1980
1981
1982 // </editor-fold>
1983
1984
1985
1986 //TODO: M I G R A T E to 9.8
1987 // .
1988 // instead of this: <script type="text/javascript"> wpbc_settings.set_option( 'pending_days_selectable', true ); </script>
1989 // use this: <script type="text/javascript"> _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'pending_days_selectable' , true ); </script>
1990 // Booking Calendar - JavaScript Settings
1991 // Example or redefine some settings:
1992 // <script type="text/javascript"> wpbc_settings.set_option( 'pending_days_selectable', true ); </script>
1993 // [booking type=1]
1994 // .
1995 // .
1996 // 1. Define parameters for calendar(s):
1997 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'single'} );
1998 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'multiple'} );
1999 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'fixed'} );
2000 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'fixed__days_num' : 7 } );
2001 // _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 }
2002 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'dynamic'} );
2003 // _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_min' , 7 );
2004 // _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_max' , 14 );
2005 // _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_specific' , [] ); // Example [5,7]
2006 // _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 }
2007 // JavaScript functions changes:
2008 // wpbc_unselect_all_days( resource_id ) -> wpbc_calendar__unselect_all_dates( resource_id )
2009 // showErrorMessage( element , errorMessage , isScrollStop ); -> wpbc_front_end__show_message__warning( jq_node, message );
2010 // showMessageUnderElement( element , errorMessage , message_type); -> wpbc_front_end__show_message__warning_under_element( jq_node, message );
2011 // makeScroll( object_name ); -> wpbc_do_scroll( jq_node );
2012 // .
2013 // JavaScript hooks changes:
2014 // jQuery( ".booking_form_div" ).trigger( "date_selected", [ resource_id, date ] );
2015 // become
2016 // jQuery( ".booking_form_div" ).trigger( "date_selected", [ resource_id, mouse_clicked_dates, all_selected_dates_arr ] );
2017 // where:
2018 // mouse_clicked_dates Can be: "05.10.2023 - 07.10.2023" | "10.10.2023 - 10.10.2023" |
2019 // all_selected_dates_arr Can be: [ "2023-10-05", "2023-10-06", "2023-10-07", … ]
2020 // PHP actions:
2021 // from: make_bk_action('wpdev_booking_post_inserted', $booking_id, $bktype, $str_dates__dd_mm_yyyy, array($start_time, $end_time ) , $formdata );
2022 // removed!
2023 // . // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
2024 // from: apply_filters('wpdev_booking_form_content', $form , $resource_id);
2025 // to: apply_filters( 'wpbc_booking_form_html__update__append_change_over_times', $form, $resource_id );
2026 // .
2027 // Removed PHP actions:
2028 // . 'show_payment_forms__for_ajax'
2029 // * make_bk_action('wpbc_ add_new_booking' , array(
2030 // * 'bktype' => 1
2031 // * , 'dates' => '27.08.2014, 28.08.2014, 29.08.2014'
2032 // * , 'form' => 'selectbox-one^rangetime1^10:00 - 12:00~text^name1^Jo~text^secondname1^Smith~email^email1^smith@gmail.com~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'
2033 // * , 'is_send_emeils' => 0
2034 // * // , 'booking_form_type' => ''
2035 // * // , 'wpdev_active_locale' => 'en_US'
2036 // * ) );
2037 // .
2038 // add_bk_filter('wpbc_add_new_booking_filter' , 'wpbc_add_new_booking' );
2039 // TODO: recheck hooks in wpbc-dev-api.php
2040