PluginProbe
Booking Calendar / 10.1.3
Booking Calendar v10.1.3
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 10.1.3, at includes/_capacity/capacity.php

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