PluginProbe
Booking Calendar / 11.3
Booking Calendar v11.3
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 10.11.3 10.11.4 10.12.0 10.12.1 All 199 releases
booking / includes / _capacity / capacity.php

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

2,049 lines 109.8 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 UTC' ); // '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 UTC' )
731 - strtotime( $params['dates_to_check'][0] . ' 00:00:00 UTC' );
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 $is_booking_used_check_in_out_time = null;
964 if ( function_exists( 'wpbc_settings_calendar__preview_is_changeover_enabled' ) ) {
965 $is_booking_used_check_in_out_time = wpbc_settings_calendar__preview_is_changeover_enabled( $resource_id, $params['request_uri'] );
966 }
967 if ( null === $is_booking_used_check_in_out_time ) {
968 $is_booking_used_check_in_out_time = (
969 ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) )
970 && ( wpbc_is_booking_used_check_in_out_time( $params['request_uri'], $resource_id ) )
971 );
972 }
973 if (
974 $is_booking_used_check_in_out_time
975 && ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) // And this date still free false
976 ) {
977
978 /**
979 * "Change over days" - possible situations: check_in | check_out | change_over | ...
980 *
981 * $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = check_in
982 * | check_out
983 * | change_over
984 * | 'mixed'
985 * 'mixed' - e.g. 'change_over check_out' where several child resources and some is 'change_over' and others are 'check_out'
986 *
987 *
988 * Possible situations for change-over days:
989 *
990 * // A. If in $booked_time_slots array one of values (or in $this_date_bookings one of keys)
991 * // 1. Started with time that is ended with 1 second
992 * // 2. and Ended with '24:00' it is means '86392', like this: '28811 - 86392'
993 * // then it's means that we have 'check_in' time here
994 *
995 * // B. If in $booked_time_slots array one of values (or in $this_date_bookings one of keys)
996 * // 1. Started with '00:00' it is means '1'
997 * // 2. and Ended time that is ended with 2 second
998 * // like this: '1 - 32402'
999 * // then it's means that we have 'check_out' time here
1000 *
1001 * // C. If we have A. and B. then we have 'change_over' here
1002 */
1003
1004 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array();
1005
1006 foreach ( $this_date_bookings as $booked_times__key => $booked_times__value ) {
1007
1008 if ( false === strpos( $booked_times__key, '-' ) ) {
1009 continue; // for situation with FULL day booking, here $booked_times__key = 0
1010 }
1011
1012 $rangeA_arr = explode( '-', $booked_times__key );
1013 $rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
1014 $rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
1015
1016 // start time
1017 $is_starttime__check_in = $rangeA_arr[0] % 10; // 0, 1, 2
1018 $is_starttime__check_in = ( 1 == $is_starttime__check_in ) ? true : false;
1019
1020 // end time
1021 $is_endtime__check_out = $rangeA_arr[1] % 10;
1022 $is_endtime__check_out = ( 2 == $is_endtime__check_out ) ? true : false;
1023
1024
1025 if ( ( $is_starttime__check_in ) && ( WPBC_FULL_DAY_TIME_OUT == $rangeA_arr[1] ) ) { // A :: start_time - 86392 e.g. 14:00 - 24:00
1026 // only "check in" time here
1027 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out[] = 'check_in';
1028
1029 } else if ( ( WPBC_FULL_DAY_TIME_IN == $rangeA_arr[0] ) && ( $is_endtime__check_out ) ) { // B :: 1 - end_time e.g. 00:00 - 10:00
1030 // only "check out" time here
1031 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out[] = 'check_out';
1032 }
1033
1034 }
1035 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array_unique( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );
1036 $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.
1037
1038 if (
1039 ( in_array( 'check_in', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) )
1040 && ( in_array( 'check_out', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) )
1041 ) {
1042 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = array( 'change_over' ); // both check in / out times here
1043 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1044
1045 // Possible statuses: pending_pending | pending_approved | approved_pending | approved_approved
1046 $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved = array( implode( '_', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved ) );
1047 }
1048
1049 $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out );
1050
1051 if ( ! empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out ) ) {
1052 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = $availability_per_day[ $my_day_tag ][ $resource_id ]->check_in_out;
1053 }
1054 } // end change-over if
1055
1056
1057 }
1058 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1059 // B O O K I N G S - E n d
1060 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1061 // Working Time applies only to time-based booking forms: rangetime, start/end, or start/duration.
1062 $working_time__timeslots_to_check_intersect = $as_seconds_timeslots_arr__to_check_intersect;
1063 if ( empty( $working_time__timeslots_to_check_intersect ) && ! empty( $params['timeslots_to_check_intersect'] ) ) {
1064 if ( ! is_array( $params['timeslots_to_check_intersect'] ) ) {
1065 $params['timeslots_to_check_intersect'] = array( $params['timeslots_to_check_intersect'] );
1066 }
1067 $working_time__timeslots_to_check_intersect = array();
1068 foreach ( $params['timeslots_to_check_intersect'] as $time_slot_readable ) {
1069 $working_time__timeslots_to_check_intersect[] = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $time_slot_readable );
1070 }
1071 }
1072
1073 if (
1074 ! empty( $working_time__timeslots_to_check_intersect )
1075 && function_exists( 'wpbc_working_time__get_non_working_intervals_for_date' )
1076 && function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' )
1077 ) {
1078 $working_time__blocked_intervals = wpbc_working_time__get_non_working_intervals_for_date( $resource_id, $my_day_tag );
1079
1080 if ( ! empty( $working_time__blocked_intervals ) ) {
1081 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj(
1082 $availability_per_day[ $my_day_tag ][ $resource_id ],
1083 $working_time__blocked_intervals,
1084 $working_time__timeslots_to_check_intersect
1085 );
1086 }
1087 }
1088
1089 // FixIn: 10.16.1.
1090 if (
1091 function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' )
1092 && isset( $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ] )
1093 ) {
1094 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj(
1095 $availability_per_day[ $my_day_tag ][ $resource_id ],
1096 $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ],
1097 $as_seconds_timeslots_arr__to_check_intersect
1098 );
1099 }
1100
1101 //==========================================================================================================
1102 // $availability_per_day[..]->_day_status = 'season_filter' | ...
1103 //==========================================================================================================
1104 // Booking > Resources > Availability page >>> 'season_filter'
1105 $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 );
1106
1107 // Booking > Availability page >>> 'resource_availability'
1108 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__resource_availability( $availability_per_day, $my_day_tag, $resource_id, $unavailable_dates__per_resources__arr );
1109
1110 if ( empty( $params['skip_general_availability'] ) ) {
1111 // Week Days unavailable >>> 'weekday_unavailable'
1112 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id );
1113 }
1114
1115 // if ( ( ! $is_this_bap_page ) || ( ! $is_this_hash_page ) ) {
1116 if ( empty( $params['skip_general_availability'] ) && ( ! $is_this_bap_page ) && ( ! $is_this_hash_page ) ) {
1117 // Do not apply these settings at Booking > Add booking page, when we edit booking - e.g. exist 'booking_hash'
1118
1119 // Skip checking unavailable from today, if defined the calendar_dates_start='2025-02-10' calendar_dates_end='2025-12-31' in shortcode. // FixIn: 10.13.1.4.
1120 $is_skip_check__from_today_unavailable = false;
1121 if ( is_array( $params['dates_to_check'] ) && empty( $params['force_check_from_today_unavailable'] ) ) {
1122 if ( ( ( count( $params['dates_to_check'] ) ) > 0 ) && ( wpbc_is_date_less_than( $params['dates_to_check'][0], $my_day_tag ) ) ) {
1123 $is_skip_check__from_today_unavailable = true;
1124 }
1125 if ( ( ( count( $params['dates_to_check'] ) ) > 1 ) && ( wpbc_is_date_higher_than( $params['dates_to_check'][1], $my_day_tag ) ) ) {
1126 $is_skip_check__from_today_unavailable = true;
1127 }
1128 }
1129
1130 if ( ! $is_skip_check__from_today_unavailable ) {
1131
1132 // Unavailable days from today >>> 'from_today_unavailable'.
1133 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id );
1134
1135 // Limit available days from today >>> 'limit_available_from_today'.
1136 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__limit_available_from_today( $availability_per_day, $my_day_tag, $resource_id );
1137 }
1138 }
1139 //==========================================================================================================
1140
1141
1142 // T O O L T I P :: Times - Unavailable Day
1143 if ( in_array( $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status, array( 'season_filter',
1144 'resource_availability',
1145 'weekday_unavailable',
1146 'from_today_unavailable',
1147 'limit_available_from_today'
1148 ) )
1149 ){
1150 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id
1151 , $resource_id__with_children__arr, __( 'Unavailable', 'booking' ) );
1152 }
1153
1154
1155 // =========================================================================================================
1156 // Entire D A Y statuses
1157 // =========================================================================================================
1158
1159 if ( $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) {
1160 // Set merged time interval as fully unavailable.
1161 $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_seconds'] = array( array( 0, 86400 ) ); // FixIn: 10.11.5.1.
1162 // Reduce DAY day_availability, if some season or days unavailable or full by bookings.
1163 --$availability_per_day[ $my_day_tag ]['day_availability'];
1164 }
1165
1166 // 'resource_availability' | 'weekday_unavailable' | 'from_today_unavailable' | 'limit_available_from_today' | 'season_filter' | 'full_day_booking' | 'time_slots_booking' | 'available'.
1167 $availability_per_day[ $my_day_tag ]['statuses']['day_status'][] = $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status;
1168
1169 // 'approved' | 'pending'.
1170 $availability_per_day[ $my_day_tag ]['statuses']['bookings_status'][] = implode( '|', $availability_per_day[ $my_day_tag ][ $resource_id ]->pending_approved );
1171
1172 // Go to next child booking resource.
1173 }
1174
1175 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1176 // R E S O U R C E S - E n d
1177 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1178
1179
1180 // -------------------------------------------------------------------------------------------------------------
1181 // Day summary :
1182 // -------------------------------------------------------------------------------------------------------------
1183 $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 );
1184
1185 // Go next day + 1 day
1186 $today_inix_timestamp += 24 * 60 * 60;
1187 }
1188
1189
1190 return array(
1191 'dates' => $availability_per_day
1192 , 'resources_id_arr__in_dates' => $resource_id__with_children__arr
1193 , 'aggregate_resource_id_arr' => $aggregate_resource_id_arr
1194 );
1195 }
1196
1197
1198 // <editor-fold defaultstate="collapsed" desc=" == S U P P O R T == " >
1199
1200
1201 // S U P P O R T
1202
1203 /**
1204 * Update Summary statuses for the Day
1205 *
1206 * @param $availability_per_this_day
1207 * @param $my_day_tag
1208 * @param $resource_id_arr
1209 *
1210 * @return mixed
1211 *
1212 *
1213 * Dates Status Concept Strategy ::
1214 *
1215 * Check date booking status based on 'all booking resources':
1216 * ( and as one common situation, when we have only 1 resource )
1217 *
1218 * | 'approved' - when all booking resources has approved FULL day bookings or some booking resource unavailable
1219 * | 'pending' - when at least one booking in one booking resource has pending status and there is no available booking resources
1220 * | 'times_partially_booked' - when at least one booking in one booking resource has time bookings and there is no available booking resources
1221 * and if all time slot approved then status approved
1222 * otherwise if at least one time slot booking has pending status then it has pending status
1223 *
1224 * if all 'time_slots' booked (it's time slot passed into function as parameter)
1225 * then such date in specific booking resource has pending or approved status, based on 'pending'|'approved' rule
1226 *
1227 * | 'check_in' - if activated 'change over days' and all bookings have 'check-in' status
1228 * | 'check_out' - if activated 'change over days' and all bookings have 'check-out' status
1229 * | if in booking resource exist both check in/out bookings, and activated 'change over days'
1230 * then such booking resource date has approved or pending status depends on from status of these bookings
1231 * | 'season_unavailable' - if all booking resources defined as unavailable at Booking > Resources > Availability page
1232 * | 'resource_unavailable' - if all booking resources defined as unavailable at Booking > Availability page
1233 * | 'other_unavailable' - if all booking resources defined as unavailable at Booking > Settings General page in "Availability" section
1234 *
1235 */
1236 function wpbc_update_summary_availability_per_this_day( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1237
1238 // -------------------------------------------------------------------------------------------------------------
1239 // Summary Tooltips
1240 // -------------------------------------------------------------------------------------------------------------
1241 $availability_per_this_day['summary']['tooltip_times'] = wpbc_support_capacity__tooltip__summary__times( $availability_per_this_day, $my_day_tag, $resource_id_arr );
1242 $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 );
1243 $availability_per_this_day['summary']['tooltip_day_cost'] = wpbc_support_capacity__tooltip__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr );
1244 $availability_per_this_day['summary']['tooltip_availability'] = wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr );
1245
1246
1247 $availability_per_this_day['summary']['hint__in_day__cost'] = wpbc_support_capacity__in_day_hint__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr );
1248 $availability_per_this_day['summary']['hint__in_day__availability'] = wpbc_support_capacity__in_day_hint__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ); // FixIn: 10.6.4.1.
1249
1250 // -------------------------------------------------------------------------------------------------------------
1251 // ['summary']['status_for_day']
1252 // -------------------------------------------------------------------------------------------------------------
1253 $temp_status = array();
1254 foreach ( $availability_per_this_day['statuses']['day_status'] as $bookings_status_arr ) {
1255 $bookings_status_arr = explode( '|', $bookings_status_arr );
1256 foreach ( $bookings_status_arr as $bookings_status_element ) {
1257 $temp_status[] = $bookings_status_element;
1258 }
1259 }
1260 $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1261 $temp_status_counts = array_count_values( $temp_status );
1262 $temp_status = array_unique( $temp_status ); // Erase duplicates
1263 $availability_per_this_day['summary']['status_for_day'] = $temp_status;
1264
1265 /**
1266 * Possible day statuses (searched by value of _day_status):
1267 *
1268 * available
1269 * time_slots_booking
1270 * full_day_booking
1271 *
1272 * limit_available_from_today
1273 * from_today_unavailable
1274 * weekday_unavailable
1275 * resource_availability
1276 * season_filter
1277 *
1278 * change_over
1279 * check_out
1280 * check_in
1281 * 'mixed' from check_in/check_out/change_over
1282 */
1283
1284 // Priority: available > time_slots_booking > full_day_booking
1285 // > season_filter > resource_availability
1286 // > weekday_unavailable > from_today_unavailable > limit_available_from_today
1287
1288 // Capacity resources can be available even when every child has a check-in/out or full-day status.
1289 $max_capacity = isset( $availability_per_this_day['max_capacity'] ) ? intval( $availability_per_this_day['max_capacity'] ) : 1;
1290 $blocking_statuses = array(
1291 'full_day_booking',
1292 'season_filter',
1293 'resource_availability',
1294 'weekday_unavailable',
1295 'from_today_unavailable',
1296 'limit_available_from_today',
1297 'change_over',
1298 );
1299 $blocked_capacity = 0;
1300 foreach ( $blocking_statuses as $blocking_status ) {
1301 $blocked_capacity += isset( $temp_status_counts[ $blocking_status ] ) ? intval( $temp_status_counts[ $blocking_status ] ) : 0;
1302 }
1303 $booked_capacity__before_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_out'] ) ? intval( $temp_status_counts['check_out'] ) : 0 );
1304 $booked_capacity__after_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_in'] ) ? intval( $temp_status_counts['check_in'] ) : 0 );
1305 $is_capacity_available_during_change_over = (
1306 ( $max_capacity > 1 )
1307 && ( $max_capacity > max( $booked_capacity__before_check_in, $booked_capacity__after_check_in ) )
1308 && ( ! in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) )
1309 );
1310
1311 // if at least one resource is available then day has this status
1312 if ( in_array( 'available', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'available';
1313 } else if ( $is_capacity_available_during_change_over ) { $availability_per_this_day['summary']['status_for_day'] = 'available';
1314 } else if ( in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'time_slots_booking';
1315 } else if ( ( ! in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) )
1316 && ( in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) ) ) { $availability_per_this_day['summary']['status_for_day'] = 'check_in';
1317 } else if ( ( ! in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) )
1318 && ( in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) ) ) { $availability_per_this_day['summary']['status_for_day'] = 'check_out';
1319 } 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';
1320 } else if ( in_array( 'season_filter', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'season_filter';
1321 } else if ( in_array( 'resource_availability', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'resource_availability';
1322 } else if ( in_array( 'weekday_unavailable', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'weekday_unavailable';
1323 } 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';
1324 } 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';
1325 } else {
1326 $availability_per_this_day['summary']['status_for_day'] = implode( ' ', $availability_per_this_day['summary']['status_for_day'] );
1327 }
1328
1329
1330 // -------------------------------------------------------------------------------------------------------------
1331 // ['summary']['status_for_bookings']
1332 // -------------------------------------------------------------------------------------------------------------
1333 $temp_status = array();
1334 foreach ( $availability_per_this_day['statuses']['bookings_status'] as $bookings_status_arr ) {
1335 $bookings_status_arr = explode( '|', $bookings_status_arr );
1336 foreach ( $bookings_status_arr as $bookings_status_element ) {
1337 $temp_status[] = $bookings_status_element;
1338 }
1339 }
1340 $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1341 $temp_status = array_values( array_unique( $temp_status ) );
1342
1343 // Structured booking statuses contract. Keep numeric keys sequential so JSON encodes this as a JS array.
1344 $availability_per_this_day['summary']['status_for_bookings_arr'] = $temp_status;
1345
1346 // Priority: pending > approved > ''
1347
1348 // if at least one booking pending then day is pending
1349 if ( in_array( 'pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending';
1350 } else if ( in_array( 'pending_pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending';
1351 // Usual situations for change over days: pending_pending | pending_approved | approved_pending | approved_approved
1352 } else {
1353 $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ', $temp_status );
1354 }
1355
1356
1357 // -------------------------------------------------------------------------------------------------------------
1358 return $availability_per_this_day;
1359 }
1360
1361
1362 // T O O L T I P s
1363
1364 /**
1365 * Set tooltip summary -- Time-Slots
1366 *
1367 * @param $availability_per_this_day
1368 * @param $my_day_tag
1369 * @param $resource_id_arr
1370 *
1371 * @return string - tooltip content or ''
1372 */
1373 function wpbc_support_capacity__tooltip__summary__times( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1374
1375 $tooltip = '';
1376
1377 if ( 'On' != get_bk_option( 'booking_disable_timeslots_in_tooltip' ) ) { //FixIn: 9.5.0.2.2
1378
1379 $tooltip_title_word = get_bk_option( 'booking_highlight_timeslot_word' );
1380 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1381 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1382 ? ''
1383 : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';
1384
1385 $status_summary_tooltip_times = array();
1386 foreach ( $resource_id_arr as $resource_id ) {
1387 if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['times'] ) ) {
1388 $status_summary_tooltip_times[] = $availability_per_this_day[ $resource_id ]->tooltips['times'];
1389 }
1390 }
1391
1392 if ( ! empty( $status_summary_tooltip_times ) ) {
1393
1394 $tooltip = '<div class="wpbc_tooltip_section tooltip__times">'
1395 . $tooltip_title_word
1396 . implode( '', $status_summary_tooltip_times )
1397 . '</div>';
1398 }
1399 }
1400
1401 return $tooltip;
1402 }
1403
1404 function wpbc_support_capacity__tooltip__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1405
1406 $tooltip = '';
1407
1408 if ( ( 'On' == get_bk_option( 'booking_is_show_availability_in_tooltips' ) ) && ( $availability_per_this_day['max_capacity'] > 1 ) ) {
1409
1410 $tooltip_title_word = get_bk_option( 'booking_highlight_availability_word' );
1411 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1412 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1413 ? ''
1414 : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';
1415
1416 $tooltip_content_header = '';
1417
1418 if ( ! empty( $availability_per_this_day['day_availability'] ) ) {
1419
1420 $tooltip = '<div class="wpbc_tooltip_section tooltip__availability">'
1421 . $tooltip_title_word
1422 . '<div class="wpbc_tooltip_resource_container">'
1423 . $tooltip_content_header
1424 . '<div class="wpbc_tooltip_item">'
1425 . $availability_per_this_day['day_availability']
1426 . '</div>'
1427 . '</div>'
1428 . '</div>';
1429 }
1430 }
1431 return $tooltip;
1432 }
1433
1434 function wpbc_support_capacity__tooltip__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1435
1436 $tooltip = '';
1437 if (
1438 ( ! empty( $availability_per_this_day['day_availability'] ) )
1439 && ( 'On' == get_bk_option( 'booking_is_show_cost_in_tooltips' ) )
1440 ){
1441
1442 $tooltip_title_word = get_bk_option( 'booking_highlight_cost_word' );
1443 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1444 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1445 ? ''
1446 : '<div class="wpbc_tooltip_title">' . $tooltip_title_word . '</div>' . ' ';
1447
1448 if ( isset( $resource_id_arr[0] ) ) {
1449
1450 $id_of_first_resource = $resource_id_arr[0];
1451 $tooltip_content_header = '';
1452
1453 if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) {
1454
1455 $cur_sym = get_bk_option( 'booking_cost_in_date_cell_currency' ); // in Booking > Settings General page in "Calendar" section
1456 //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page
1457
1458 $cost_text = wpbc_formate_cost_hint__no_html( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate, $cur_sym );
1459 $cost_text = html_entity_decode( $cost_text );
1460
1461 $tooltip = '<div class="wpbc_tooltip_section tooltip__day_cost">'
1462 . $tooltip_title_word
1463 . '<div class="wpbc_tooltip_resource_container">'
1464 . $tooltip_content_header
1465 . '<div class="wpbc_tooltip_item">'
1466 . $cost_text
1467 . '</div>'
1468 . '</div>'
1469 . '</div>';
1470 }
1471
1472 }
1473 }
1474 return $tooltip;
1475 }
1476
1477
1478 function wpbc_support_capacity__in_day_hint__summary__day_cost( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1479
1480 $tooltip = '';
1481 if (
1482 ( ! empty( $availability_per_this_day['day_availability'] ) )
1483 && ( 'On' == get_bk_option( 'booking_is_show_cost_in_date_cell' ) )
1484 ){
1485
1486 $id_of_first_resource = $resource_id_arr[0];
1487
1488 if ( ! empty( $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate ) ) {
1489
1490 $cur_sym = get_bk_option( 'booking_cost_in_date_cell_currency' ); // in Booking > Settings General page in "Calendar" section
1491 //$cur_sym = wpbc_get_currency_symbol(); // in Booking > Settings > Payment page
1492
1493 $cost_text = $availability_per_this_day[ $id_of_first_resource ]->date_cost_rate;
1494 $cost_text = number_format( floatval( $cost_text ), wpbc_get_cost_decimals(), '.', '' );
1495 $cost_text = wp_strip_all_tags( wpbc_cost_show( $cost_text, array( 'currency' => 'CURRENCY_SYMBOL' ) ) );
1496 $cost_text = str_replace( array( 'CURRENCY_SYMBOL', '&' ), array( $cur_sym, '&amp;' ), $cost_text );
1497 $cost_text = html_entity_decode($cost_text);
1498
1499 $tooltip = '<span class="wpbc_in_date_hint__cost">' . $cost_text . '</span>';;
1500 }
1501 }
1502 return $tooltip;
1503 }
1504
1505 // FixIn: 10.6.4.1.
1506 /**
1507 * Get availability for in Day cells
1508 *
1509 * @param $availability_per_this_day
1510 * @param $my_day_tag
1511 * @param $resource_id_arr
1512 *
1513 * @return string
1514 */
1515 function wpbc_support_capacity__in_day_hint__summary__availability( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1516
1517 $tooltip = '';
1518
1519 if (
1520 ( 'On' == get_bk_option( 'booking_is_show_availability_in_date_cell' ) ) &&
1521 ( $availability_per_this_day['max_capacity'] > 1 )
1522 ) {
1523
1524 $tooltip_title_word = get_bk_option( 'booking_highlight_availability_word_in_date_cell' );
1525 $tooltip_title_word = wpbc_lang( $tooltip_title_word );
1526 $tooltip_title_word = ( empty( $tooltip_title_word ) )
1527 ? ''
1528 : '<span class="wpbc_in_date_hint__availability_title">' . $tooltip_title_word . '</span>';
1529
1530
1531 if ( ! empty( $availability_per_this_day['day_availability'] ) ) {
1532
1533 $tooltip = '<span class="wpbc_in_date_hint__availability">'
1534 . '<span class="wpbc_in_date_hint__availability_number">'
1535 . intval( $availability_per_this_day['day_availability'] )
1536 . '&nbsp;'
1537 . '</span>'
1538 . $tooltip_title_word
1539 . '</span>';
1540 $tooltip = html_entity_decode($tooltip);
1541 }
1542 }
1543 return $tooltip;
1544 }
1545
1546
1547
1548 /**
1549 * Set tooltip summary -- Booking Details
1550 *
1551 * @param $availability_per_this_day
1552 * @param $my_day_tag
1553 * @param $resource_id_arr
1554 *
1555 * @return string - tooltip content or ''
1556 */
1557 function wpbc_support_capacity__tooltip__summary__booked_details( $availability_per_this_day, $my_day_tag, $resource_id_arr ){
1558
1559 $tooltip = '';
1560
1561 if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) { //FixIn: 9.5.0.2.2
1562
1563 $tooltip_title_word = '<div class="wpbc_tooltip_title">' . esc_html__('Booking details','booking') . '</div>';
1564
1565 $status_summary_tooltip_times = array();
1566 foreach ( $resource_id_arr as $resource_id ) {
1567 if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['details'] ) ) {
1568
1569 if ( ! empty( $availability_per_this_day[ $resource_id ]->tooltips['resource_title'] ) ){
1570 $tooltip_content_header = '<div class="wpbc_tooltip_header">'
1571 . $availability_per_this_day[ $resource_id ]->tooltips['resource_title'] . ': '
1572 . '</div>';
1573 } else{
1574 $tooltip_content_header = '';
1575 }
1576
1577 $booking_details_text = '<div class="wpbc_tooltip_resource_container">'
1578 . $tooltip_content_header
1579 . implode( ' ', $availability_per_this_day[ $resource_id ]->tooltips['details'] )
1580 . '</div>';
1581
1582 $status_summary_tooltip_times[] = $booking_details_text;
1583 }
1584 }
1585
1586 if ( ! empty( $status_summary_tooltip_times ) ) {
1587
1588 $tooltip = '<div class="wpbc_tooltip_section tooltip__booking_details">'
1589 . $tooltip_title_word
1590 . implode( '', $status_summary_tooltip_times )
1591 . '</div>';
1592 }
1593 }
1594 return $tooltip;
1595 }
1596
1597 /**
1598 * Set Tooltip -- Booking Details
1599 *
1600 * @param $availability_per_day
1601 * @param $my_day_tag
1602 * @param $resource_id
1603 * @param $this_date_bookings
1604 * @param $booked_times__key
1605 * @param $resources_obj
1606 *
1607 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
1608 */
1609 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 ) {
1610
1611 // Get booking details for tooltip, if needed
1612 if ( 'On' == get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) ) {
1613
1614 $booking_id = $this_date_bookings[ $booked_times__key ]->booking_id;
1615 $this_booking_resource_id = $this_date_bookings[ $booked_times__key ]->type;
1616
1617 $booking_details_text = wpbc_support_capacity__get_booking_details(
1618 $this_date_bookings[ $booked_times__key ],
1619 $resources_obj->get__booking_resource_obj( $this_booking_resource_id )
1620 );
1621 $tooltip_text = '';
1622 $tooltip_text .= '<div class="wpbc_tooltip_item tooltip_booked_time">' . $booked_time . '</div>'; // Booked time
1623 $tooltip_text .= '<div class="wpbc_tooltip_item">' . $booking_details_text . '</div>'; // Booking details
1624
1625 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['details'][ $booking_id ] = $tooltip_text;
1626 }
1627
1628 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1629 }
1630
1631 /**
1632 * Set Tooltip Times -- Time-Slots
1633 *
1634 * @param $availability_per_day
1635 * @param $my_day_tag
1636 * @param $resource_id
1637 * @param $resource_id_arr
1638 *
1639 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
1640 */
1641 function wpbc_support_capacity__tooltip_times__set_for_times( $availability_per_day, $my_day_tag, $resource_id, $resource_id_arr ){
1642
1643 // Times Tooltip - time slot list --------------------------------------------------------------------
1644 $tooltip_content_header = '';
1645
1646 if ( count( $resource_id_arr ) > 1 ) {
1647
1648 $class_name = 'tooltip_items_count_' . count( $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable'] );
1649
1650 $tooltip_content_header = '<div class="wpbc_tooltip_header ' . $class_name . ' ">'
1651 . $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['resource_title'] . ': '
1652 . '</div>';
1653 }
1654
1655 $tooltip_content_arr = array_map( function ( $item ) {
1656 return '<div class="wpbc_tooltip_item">' . $item . '</div>';
1657 }
1658 , $availability_per_day[ $my_day_tag ][ $resource_id ]->booked_time_slots['merged_readable']
1659 );
1660
1661 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['times'] = '<div class="wpbc_tooltip_resource_container">'
1662 . $tooltip_content_header
1663 . implode( '', $tooltip_content_arr )
1664 . '</div>';
1665 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1666 }
1667
1668 /**
1669 * Set Tooltip Times -- Full Day
1670 *
1671 * @param $availability_per_day
1672 * @param $my_day_tag
1673 * @param $resource_id
1674 * @param $resource_id_arr
1675 * @param $status_title
1676 *
1677 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ];
1678 */
1679 function wpbc_support_capacity__tooltip_times__set_full_day( $availability_per_day, $my_day_tag, $resource_id, $resource_id_arr, $status_title ){
1680
1681 // Times Tooltip - FULL DAY --------------------------------------------------------------------
1682 $tooltip_content_header = '';
1683
1684 if ( count( $resource_id_arr ) > 1 ) {
1685
1686 $class_name = 'tooltip_items_count_1';
1687
1688 $tooltip_content_header = '<div class="wpbc_tooltip_header ' . $class_name . ' ">'
1689 . $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['resource_title'] . ': '
1690 . '</div>';
1691 }
1692
1693 $tooltip_content_text = '<div class="wpbc_tooltip_item">' . $status_title . '</div>';
1694
1695 $availability_per_day[ $my_day_tag ][ $resource_id ]->tooltips['times'] = '<div class="wpbc_tooltip_resource_container">'
1696 . $tooltip_content_header
1697 . $tooltip_content_text
1698 . '</div>';
1699 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1700 }
1701
1702
1703
1704 /**
1705 * Get parsed booking data, if required
1706 *
1707 * @param object $this_date_bookings
1708 * @param object $resource_obj
1709 *
1710 * @return string
1711 */
1712 function wpbc_support_capacity__get_booking_details( $this_date_bookings, $resource_obj ) {
1713
1714 if ( ( ! class_exists( 'wpdev_bk_biz_m' ) )
1715 || ( 'On' !== get_bk_option( 'booking_is_show_booked_data_in_tooltips' ) )
1716 ){
1717 return '';
1718 }
1719
1720 $booking_details_for_hint = '';
1721
1722 if ( isset( $this_date_bookings->form ) ) {
1723
1724 // Get shortcodes
1725 $booking_shortcodes_in_tooltips = get_bk_option( 'booking_booked_data_in_tooltips' ); // '[name] [secondname]'
1726
1727 $resource_id = $this_date_bookings->type;
1728
1729 // Get parsed booking data field values -- e.g.: [ "rangetime":"12:00 - 14:00", "secondname":"Smith",... ]
1730 $booking_data_arr = wpbc_get_parsed_booking_data_arr( $this_date_bookings->form, $resource_id, array( 'get' => 'value' ) );
1731 $booking_data_arr['booking_id'] = $this_date_bookings->booking_id;
1732 $booking_data_arr['resource_id'] = $resource_id;
1733 $booking_data_arr['resource_title'] = ( ! empty( $resource_obj ) ) ? wpbc_lang( $resource_obj->title ) : '';
1734
1735 // Replace existing shortcodes
1736 foreach ( $booking_data_arr as $replace_shortcode => $replace_value ) {
1737
1738 if ( is_null( $replace_value ) ) { $replace_value = ''; };
1739
1740 $replace_value = wpbc_replace__true_false__to__yes_no( $replace_value ); // FixIn: 9.8.9.1.
1741
1742 $booking_shortcodes_in_tooltips = str_replace( array(
1743 '[' . $replace_shortcode . ']'
1744 , '{' . $replace_shortcode . '}'
1745 )
1746 , $replace_value
1747 , $booking_shortcodes_in_tooltips
1748 );
1749 }
1750
1751 $booking_details_for_hint = $booking_shortcodes_in_tooltips;
1752
1753 // Remove all shortcodes, which is not replaced early.
1754 $booking_details_for_hint = preg_replace( '/[\[\{][a-zA-Z0-9.,_-]{0,}[\]\}]/', '', $booking_details_for_hint );
1755 }
1756
1757 return $booking_details_for_hint;
1758 }
1759
1760
1761 /**
1762 * Unset some fields from booking data for do not show personal data at front-end side
1763 *
1764 * @param object $this_date_bookings
1765 *
1766 * @return object
1767 */
1768 function wpbc_support_capacity__unset_some_fields( $this_date_bookings ) {
1769
1770 if ( isset( $this_date_bookings->form ) ) {
1771 unset( $this_date_bookings->form ); // Hide booking details
1772 }
1773
1774 if ( isset( $this_date_bookings->booking_date ) ) {
1775 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
1776 }
1777
1778 return $this_date_bookings;
1779 }
1780
1781
1782 // D A Y S T A T U S U N A V A I L A B L E
1783
1784 /**
1785 * Set > _day_status = 'limit_available_from_today' depends on Booking > Settings General page ---> "Limit available days from today"
1786 *
1787 * @param $availability_per_day [ ... ]
1788 * @param $my_day_tag - '2023-08-08'
1789 * @param $resource_id - 2
1790 *
1791 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1792 */
1793 function wpbc_support_capacity__day_status__limit_available_from_today( $availability_per_day, $my_day_tag, $resource_id ){
1794
1795 // ----------------------------------------------------------------------------------------------------- // limit_available_from_today
1796 // 3. Limit available days from today
1797 if ( function_exists( 'wpbc_is_day_available__relative__limit_available_from_today' ) ) {
1798 if ( ! wpbc_is_day_available__relative__limit_available_from_today( $my_day_tag ) ) {
1799 // this date unavailable
1800 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1801 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'limit_available_from_today';
1802
1803 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1804 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1805 }
1806 }
1807 }
1808
1809 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1810 }
1811
1812
1813 /**
1814 * Set > _day_status = 'from_today_unavailable' depends on Booking > Settings General page ---> "Unavailable days from today"
1815 *
1816 * @param $availability_per_day [ ... ]
1817 * @param $my_day_tag - '2023-08-08'
1818 * @param $resource_id - 2
1819 *
1820 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1821 */
1822 function wpbc_support_capacity__day_status__from_today_unavailable( $availability_per_day, $my_day_tag, $resource_id ){
1823
1824 // FixIn: 10.8.1.4.
1825
1826 // ----------------------------------------------------------------------------------------------------- // from_today_unavailable
1827 // 2. Unavailable days from today
1828 $unavailable_days_num_from_today = get_bk_option( 'booking_unavailable_days_num_from_today' );
1829
1830 // FixIn: 10.8.1.4.
1831 if ( ! empty( $unavailable_days_num_from_today ) ) {
1832 if ( 'm' === substr( $unavailable_days_num_from_today, - 1 ) ) {
1833 $start_date_unix = strtotime( '+' . ( intval( $unavailable_days_num_from_today ) - 1 ) . ' minutes' ); // + 0 days
1834 } else {
1835 $start_date_unix = strtotime( '+' . intval( $unavailable_days_num_from_today ) . ' days' ); // + 0 days
1836 }
1837 } else {
1838 $start_date_unix = strtotime( 'now' );
1839 }
1840
1841 $date_start__gmt = gmdate( 'Y-m-d H:i:s', $start_date_unix ); // '2025-01-25 12:50:10'
1842 $date_start__midnight__wp_timezone = wpbc_datetime_localized__use_wp_timezone( $date_start__gmt, 'Y-m-d 00:00:00' ); // Local Midnight.
1843
1844 // 'Today Midnight' - 'Calendar Day Cell' .
1845 $days_number = intval( ( strtotime( $date_start__midnight__wp_timezone ) - strtotime( $my_day_tag ) ) / 86400 );
1846
1847 if ( $days_number > 0 ) {
1848 // This date Unavailable.
1849 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1850 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'from_today_unavailable';
1851
1852 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1853 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1854 }
1855 }
1856
1857 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1858 }
1859
1860
1861 /**
1862 * Set > _day_status = 'weekday_unavailable' depends on Booking > Settings General page ---> "Week Days unavailable"
1863 *
1864 * @param $availability_per_day [ ... ]
1865 * @param $my_day_tag - '2023-08-08'
1866 * @param $resource_id - 2
1867 *
1868 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1869 */
1870 function wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id ){
1871
1872 // 1. Week Days unavailable -------------------------------------------------------------------------------- // weekday_unavailable
1873 $unavailable_weekdays = array();
1874 foreach ( range( 0, 6 ) as $week_day_num ) {
1875 $unavailable_weekdays[ $week_day_num ] = ( 'On' == get_bk_option( 'booking_unavailable_day' . $week_day_num ) ) ? true : false;
1876 }
1877
1878 $this_day_week_num = gmdate( 'w', strtotime( $my_day_tag ) ); // 0 - 6
1879
1880 if ( $unavailable_weekdays[ $this_day_week_num ] ) {
1881 // this date unavailable
1882 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1883 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'weekday_unavailable';
1884
1885 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1886 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1887 }
1888 }
1889
1890 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1891 }
1892
1893
1894 /**
1895 * Set > _day_status = 'resource_availability' depends on Booking > Availability page
1896 *
1897 * @param $availability_per_day [ ... ]
1898 * @param $my_day_tag - '2023-08-08'
1899 * @param $resource_id - 2
1900 * @param array $unavailable_dates__per_resources__arr - [ 2: ['2023-08-01', '2023-08-02'], 10: ['2023-08-05', '2023-08-06'] ]
1901 *
1902 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1903 */
1904 function wpbc_support_capacity__day_status__resource_availability( $availability_per_day, $my_day_tag, $resource_id, $unavailable_dates__per_resources__arr ){
1905
1906 // Booking > Availability page ----------------------------------------------------------------------------- // resource_availability
1907 /**
1908 * $unavailable_dates__per_resources__arr = Array ( [2] => Array( [0] => 2023-08-01
1909 [1] => 2023-08-02
1910 )
1911 [10] => Array( [0] => 2023-08-05
1912 [1] => 2023-08-06
1913 )
1914 )
1915 */
1916 if (
1917 ( isset( $unavailable_dates__per_resources__arr[ $resource_id ] ) )
1918 && ( in_array( $my_day_tag, $unavailable_dates__per_resources__arr[ $resource_id ] ) )
1919 ) {
1920
1921 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1922 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'resource_availability';
1923
1924 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1925 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1926 }
1927 }
1928
1929 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1930 }
1931
1932
1933 /**
1934 * Set > _day_status = 'season_filter' depends on Booking > Resources > Availability page
1935 *
1936 * @param $availability_per_day [ ... ]
1937 * @param $my_day_tag - '2023-08-08'
1938 * @param $resource_id - 2
1939 * @param array $season_filters_availability - [...]
1940 *
1941 * @return array - $availability_per_day[ $my_day_tag ][ $resource_id ]
1942 */
1943 function wpbc_support_capacity__day_status__season_filter( $availability_per_day, $my_day_tag, $resource_id, $season_filters_availability ){
1944
1945 if ( function_exists( 'wpbc_is_this_day_available_in_season_filters' ) ) { // BM and higher
1946
1947 $is_date_available = wpbc_is_this_day_available_in_season_filters( $my_day_tag, $resource_id, $season_filters_availability[ $resource_id ] ); // Get availability
1948 if ( ! $is_date_available ) {
1949
1950 $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable = true;
1951 $availability_per_day[ $my_day_tag ][ $resource_id ]->_day_status = 'season_filter';
1952
1953 if ( empty( $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details ) ) {
1954 $availability_per_day[ $my_day_tag ][ $resource_id ]->__booked__times__details = array(); // Reset bookings details
1955 }
1956 }
1957 }
1958
1959 return $availability_per_day[ $my_day_tag ][ $resource_id ];
1960 }
1961
1962
1963 // D A Y C O S T
1964
1965 /**
1966 * Get day cost depend on Rates
1967 * @param $my_day_tag - '2023-08-08'
1968 * @param $resource_id - 2
1969 * @param $base_cost - 25
1970 *
1971 * @return int|string
1972 */
1973 function wpbc_support_capacity__get_day_cost( $my_day_tag, $resource_id, $base_cost ) {
1974
1975 $fin_day_cost = 0;
1976 if ( function_exists( 'wpbc_get_1_day_cost_apply_rates' ) ) {
1977
1978 list( $year, $month, $day ) = explode( '-', $my_day_tag );
1979
1980 $day = intval( $day );
1981 $month = intval( $month );
1982 $year = intval( $year );
1983
1984 $fin_day_cost = wpbc_get_1_day_cost_apply_rates( $resource_id, $base_cost, $day, $month, $year );
1985 }
1986
1987 return $fin_day_cost;
1988 }
1989
1990
1991 // </editor-fold>
1992
1993
1994
1995 //TODO: M I G R A T E to 9.8
1996 // .
1997 // instead of this: <script type="text/javascript"> wpbc_settings.set_option( 'pending_days_selectable', true ); </script>
1998 // use this: <script type="text/javascript"> _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'pending_days_selectable' , true ); </script>
1999 // Booking Calendar - JavaScript Settings
2000 // Example or redefine some settings:
2001 // <script type="text/javascript"> wpbc_settings.set_option( 'pending_days_selectable', true ); </script>
2002 // [booking type=1]
2003 // .
2004 // .
2005 // 1. Define parameters for calendar(s):
2006 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'single'} );
2007 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'multiple'} );
2008 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'fixed'} );
2009 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'fixed__days_num' : 7 } );
2010 // _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 }
2011 // _wpbc.calendar__set_parameters( " . intval( $resource_id ) . ", {'days_select_mode': 'dynamic'} );
2012 // _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_min' , 7 );
2013 // _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_max' , 14 );
2014 // _wpbc.calendar__set_param_value( " . intval( $resource_id ) . ", 'dynamic__days_specific' , [] ); // Example [5,7]
2015 // _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 }
2016 // JavaScript functions changes:
2017 // wpbc_unselect_all_days( resource_id ) -> wpbc_calendar__unselect_all_dates( resource_id )
2018 // showErrorMessage( element , errorMessage , isScrollStop ); -> wpbc_front_end__show_message__warning( jq_node, message );
2019 // showMessageUnderElement( element , errorMessage , message_type); -> wpbc_front_end__show_message__warning_under_element( jq_node, message );
2020 // makeScroll( object_name ); -> wpbc_do_scroll( jq_node );
2021 // .
2022 // JavaScript hooks changes:
2023 // jQuery( ".booking_form_div" ).trigger( "date_selected", [ resource_id, date ] );
2024 // become
2025 // jQuery( ".booking_form_div" ).trigger( "date_selected", [ resource_id, mouse_clicked_dates, all_selected_dates_arr ] );
2026 // where:
2027 // mouse_clicked_dates Can be: "05.10.2023 - 07.10.2023" | "10.10.2023 - 10.10.2023" |
2028 // all_selected_dates_arr Can be: [ "2023-10-05", "2023-10-06", "2023-10-07", … ]
2029 // PHP actions:
2030 // from: make_bk_action('wpdev_booking_post_inserted', $booking_id, $bktype, $str_dates__dd_mm_yyyy, array($start_time, $end_time ) , $formdata );
2031 // removed!
2032 // . // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
2033 // from: apply_filters('wpdev_booking_form_content', $form , $resource_id);
2034 // to: apply_filters( 'wpbc_booking_form_html__update__append_change_over_times', $form, $resource_id );
2035 // .
2036 // Removed PHP actions:
2037 // . 'show_payment_forms__for_ajax'
2038 // * make_bk_action('wpbc_ add_new_booking' , array(
2039 // * 'bktype' => 1
2040 // * , 'dates' => '27.08.2014, 28.08.2014, 29.08.2014'
2041 // * , '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'
2042 // * , 'is_send_emeils' => 0
2043 // * // , 'booking_form_type' => ''
2044 // * // , 'wpdev_active_locale' => 'en_US'
2045 // * ) );
2046 // .
2047 // add_bk_filter('wpbc_add_new_booking_filter' , 'wpbc_add_new_booking' );
2048 // TODO: recheck hooks in wpbc-dev-api.php
2049