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

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

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