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 / dates_times_support.php

dates_times_support.php in Booking Calendar 10.1.3, at includes/_capacity/dates_times_support.php

1,616 lines 69.7 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 if ( ! defined( 'WPBC_FULL_DAY_TIME_IN' ) ) { define( 'WPBC_FULL_DAY_TIME_IN' , 1 ); } // = +1 sec. '00:00:01'
7 if ( ! defined( 'WPBC_FULL_DAY_TIME_OUT' ) ) { define( 'WPBC_FULL_DAY_TIME_OUT' , 86392 ); } // = 24 * 60 * 60 = 86400 - 10 sec. + 2 sec. '23:59:52'
8
9 // ---------------------------------------------------------------------------------------------------------------------
10 // Intervals
11 // ---------------------------------------------------------------------------------------------------------------------
12
13 /**
14 * Merge several intersected intervals or return not intersected: [[1,3],[2,6],[8,10],[15,18]] -> [[1,6],[8,10],[15,18]]
15 *
16 * @param array $intervals [ [1,3],[2,4],[6,8],[9,10],[3,7] ]
17 *
18 * @return array [ [1,8],[9,10] ]
19 *
20 * Example: wpbc_merge_intersected_intervals( array( array(1,3), array(2,4), array(6,8), array(9,10), array(3,7) ); -> array( array(1,8), array(9,10) )
21 */
22 function wpbc_merge_intersected_intervals( $intervals ){
23
24 if ( empty( $intervals ) ) {
25 return array();
26 }
27
28 $merged = array();
29
30 // Sort array by first value in a list [[8,10],[1,3],[15,18],[2,6]] -> [[1,3],[2,6],[8,10],[15,18]]
31 usort( $intervals, function ( $compare_A, $compare_B ) {
32 if ( $compare_A[0] > $compare_B[0] ) {
33 return 1;
34 } elseif ( $compare_A[0] < $compare_B[0] ) {
35 return - 1;
36 }
37 return 0;
38 } );
39
40
41 $merged_interval = $intervals[0]; // [1,3]
42
43 for ( $i = 1; $i < count( $intervals ); $i ++ ) {
44 $next_element = $intervals[ $i ]; // [2,6]
45
46 if ( $next_element[0] <= $merged_interval[1] ) {
47 $merged_interval[1] = max( $merged_interval[1], $next_element[1] );
48 } else {
49 $merged[] = $merged_interval;
50 $merged_interval = $next_element;
51 }
52 }
53
54 $merged[] = $merged_interval;
55
56 return $merged;
57 }
58
59
60 /**
61 * Is 2 intervals intersected: [36011, 86392] <=> [1, 43192] => true ( intersected )
62 *
63 * Good explanation here https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
64 *
65 * @param array $interval_A array( 36011, 86392 )
66 * @param array $interval_B array( 1, 43192 )
67 *
68 * @return bool
69 */
70 function wpbc_is__intervals__intersected( $interval_A, $interval_B ) {
71
72 if (
73 ( empty( $interval_A ) )
74 || ( empty( $interval_B ) )
75 ){
76 return false;
77 }
78
79 $is_intersected = max( $interval_A[0], $interval_B[0] ) - min( $interval_A[1], $interval_B[1] );
80
81 // if ( 0 == $is_intersected ) {
82 // // Such ranges going one after other, e.g.: [ 12, 15 ] and [ 15, 21 ]
83 // }
84
85 if ( $is_intersected < 0 ) {
86 return true; // INTERSECTED
87 }
88
89 return false; // Not intersected
90 }
91
92
93
94 // ---------------------------------------------------------------------------------------------------------------------
95 // Time - Slots functions
96 // ---------------------------------------------------------------------------------------------------------------------
97
98 /**
99 * Get time in seconds from SQL date format '2024-01-28 12:00:02' -> 1706443192
100 *
101 * @param $sql_date__ymd_his '2024-01-28 12:00:02' Date in SQL format
102 * @param bool $is_apply__check_in_out__10s : check_in_time = +10sec check_out_time = -10sec
103 *
104 * @return int
105 *
106 * if $is_apply__check_in_out__10s == true (it's default)
107 *
108 * then apply +10 seconds for check in time it's time, that ended with 1
109 * and apply -10 seconds for check out time it's time, that ended with 2
110
111 */
112 function wpbc_convert__sql_date__to_seconds( $sql_date__ymd_his, $is_apply__check_in_out__10s = true ){
113
114 list( $sql_date_ymd, $sql_time_his ) = explode( ' ', $sql_date__ymd_his ); // '2024-01-28', '12:00:02'
115
116 $date_in_seconds = wpbc_convert__date_ymd__to_seconds( $sql_date_ymd );
117 $time_in_seconds = wpbc_convert__time_his__to_seconds( $sql_time_his, $is_apply__check_in_out__10s );
118
119 $in_seconds = $date_in_seconds + $time_in_seconds;
120
121 return $in_seconds;
122 }
123
124
125 /**
126 * Get date in seconds from SQL only_date format '2024-01-28' -> 1706400000
127 *
128 * @param $sql_date_ymd '2024-01-28'
129 *
130 * @return int
131 */
132 function wpbc_convert__date_ymd__to_seconds( $sql_date_ymd ){
133
134 // DATE
135 $sql_date_time = $sql_date_ymd . ' 00:00:00';
136
137 $in_seconds = strtotime( $sql_date_time );
138
139 return $in_seconds;
140 }
141
142
143 /**
144 * Get time in seconds from SQL time format '12:00:02' -> 43192
145 *
146 * @param string $sql_time_his '12:00:02'
147 * @param bool $is_apply__check_in_out__10s : check_in_time = +10sec check_out_time = -10sec
148 *
149 * @return int
150 *
151 * if $is_apply__check_in_out__10s == true (it's default)
152 *
153 * then apply +10 seconds for check in time it's time, that ended with 1
154 * and apply -10 seconds for check out time it's time, that ended with 2
155 */
156 function wpbc_convert__time_his__to_seconds( $sql_time_his, $is_apply__check_in_out__10s = true ){
157
158 // TIME
159 $in_seconds = explode( ':', $sql_time_his );
160
161 $in_seconds = intval( $in_seconds[0] ) * 60 * 60 + intval( $in_seconds[1] ) * 60 + intval( $in_seconds[2] ); // 43202
162
163 if ( $is_apply__check_in_out__10s ) {
164
165 $is_check_in_out__or_full = $in_seconds % 10; // 0, 1, 2
166
167 if ( 1 == $is_check_in_out__or_full ) {
168 $in_seconds += 10;
169 }
170 if ( 2 == $is_check_in_out__or_full ) {
171 $in_seconds -= 10;
172 }
173 }
174
175 $in_seconds = intval( $in_seconds );
176
177 return $in_seconds;
178 }
179
180
181 /**
182 * Get time in SQL time format from seconds 43192 -> '12:00:02'
183 *
184 * @param int $in_seconds 43192
185 * @param bool $is_apply__check_in_out__10s : check_in_time = +10sec check_out_time = -10sec
186 *
187 * @return int
188 *
189 * if $is_apply__check_in_out__10s == true (it's default)
190 *
191 * then apply +10 seconds for check in time it's time, that ended with 1
192 * and apply -10 seconds for check out time it's time, that ended with 2
193 */
194 function wpbc_convert__seconds__to_time_his( $in_seconds, $is_apply__check_in_out__10s = true ){
195
196 //$is_check_in_out__or_full = $seconds__this__booking % 10; // 1, 2 (not 0)
197 $is_check_in_out__or_full = substr( ( (string) $in_seconds ), -1 ); // '1', '2' (not '0')
198
199 if ( '1' == $is_check_in_out__or_full ) {
200 if ( WPBC_FULL_DAY_TIME_IN == $in_seconds ) { // situation: 00:00 e.g. 1 sec.
201 $in_seconds = 0;
202 } else {
203 $in_seconds = $in_seconds - 10 - 1;
204 }
205 }
206 if ( '2' == $is_check_in_out__or_full ) {
207 if ( WPBC_FULL_DAY_TIME_OUT == $in_seconds ) { // situation: 24:00 e.g. 86400 -10 +2 sec.
208 $in_seconds = 86400;
209 } else {
210 $in_seconds = $in_seconds + 10 - 2;
211 }
212 }
213
214 $rest_without_hours_as_seconds = $in_seconds % ( 60 * 60 );
215
216 $in_hours = ( $in_seconds - $rest_without_hours_as_seconds ) / ( 60 * 60 ); // 43200
217 $in_hours = intval( $in_hours ); // from 20.99 hours get 20 // round( $in_hours, 0, PHP_ROUND_HALF_DOWN );
218
219 $in_minutes = $rest_without_hours_as_seconds / 60; // 43200
220 $in_minutes = intval( $in_minutes ); // from 55.99 minutes get 55 // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN ); // making 1.5 into 1 and -1.5 into -1.
221
222 $in_only_seconds = $in_seconds - ( $in_hours * 60 * 60 ) - ( $in_minutes * 60 ); // 43200
223 $in_only_seconds = intval( $in_only_seconds ); // from 55.99 minutes get 55 // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN ); // making 1.5 into 1 and -1.5 into -1.
224
225 if ( '1' == $is_check_in_out__or_full ) {
226 $in_only_seconds += 1;
227 }
228 if ( '2' == $is_check_in_out__or_full ) {
229 $in_only_seconds += 2;
230 }
231
232
233 $in_hours = ( $in_hours < 10 ) ? '0' . $in_hours : $in_hours;
234 $in_minutes = ( $in_minutes < 10 ) ? '0' . $in_minutes : $in_minutes;
235 $in_only_seconds = ( $in_only_seconds < 10 ) ? '0' . $in_only_seconds : $in_only_seconds;
236
237 $sql_time_his = $in_hours . ':' . $in_minutes . ':'. $in_only_seconds;
238
239 return $sql_time_his;
240 }
241
242
243 /**
244 * Convert date timestamp (date in seconds) to SQL date format 1706400000 -> '2024-01-28 00:00:00'
245 *
246 * @param int $in_seconds 1706400000
247 * @param bool $is_apply__check_in_out__10s true : check_in_time = -10sec check_out_time = +10sec
248 * @param string $sql_date_format 'Y-m-d H:i:s' : sometimes need to have ''Y-m-d 00:00:01' or other...
249 *
250 * @return false|string '2024-01-28 00:00:00'
251 */
252 function wpbc_convert__seconds__to_sql_date( $in_seconds, $is_apply__check_in_out__10s = true, $sql_date_format = 'Y-m-d H:i:s' ){
253
254 if ( $is_apply__check_in_out__10s ) {
255
256 $is_check_in_out__or_full = $in_seconds % 10; // 0, 1, 2
257
258 if ( 1 == $is_check_in_out__or_full ) {
259 $in_seconds -= 10;
260 }
261 if ( 2 == $is_check_in_out__or_full ) {
262 $in_seconds += 10;
263 }
264 }
265
266 $sql_date = date( $sql_date_format, $in_seconds );
267
268 return $sql_date;
269 }
270
271 // -----------------------------------------------------------------------------------------------------------------
272
273 /**
274 * Convert usual to seconds time range "10:15 - 12:00" -> "36911 - 43192"
275 *
276 * It's means that "10:15 - 12:00" in seconds "36900 - 43200" and with intersection fix: "(36900 +10 +1) - (43200 -10 +2)" e.g. "36911 - 43192"
277 *
278 * @param string $readable_time_slot "10:15 - 12:00"
279 *
280 * @return string time_range_in_seconds "36911 - 43192"
281 */
282 function wpbc_convert__readable_time_slot__to__time_range_in_seconds( $readable_time_slot ) {
283
284 $rangeA_arr = explode( '-', $readable_time_slot );
285 $rangeA_arr[0] = trim( $rangeA_arr[0] );
286 $rangeA_arr[1] = trim( $rangeA_arr[1] );
287
288 $time_range_in_seconds = array();
289
290 foreach ( $rangeA_arr as $is_end_time => $only_time ) { // $is_end_time = 0 | 1
291
292 $in_seconds = explode( ':', $only_time );
293 $in_seconds = intval( $in_seconds[0] ) * 60 * 60 + intval( $in_seconds[1] ) * 60; // 43200
294
295 if ( ! $is_end_time ) {
296
297 if ( 0 == $in_seconds ) { // situation: 00:00 e.g. 0 sec.
298 $in_seconds = WPBC_FULL_DAY_TIME_IN;
299 } else {
300 $in_seconds = $in_seconds + 10 + 1;
301 }
302
303 } else {
304
305 if ( 86400 == $in_seconds ) { // situation: 24:00 e.g. 86400 sec.
306 $in_seconds = WPBC_FULL_DAY_TIME_OUT;
307 } else {
308 $in_seconds = $in_seconds - 10 + 2;
309 }
310
311 }
312
313 $time_range_in_seconds[] = $in_seconds;
314 }
315
316 $time_range_in_seconds = implode( ' - ', $time_range_in_seconds );
317
318 return $time_range_in_seconds;
319 }
320
321
322 /**
323 * Convert seconds to usual time range: "36911 - 43192" -> "10:15 - 12:00"
324 *
325 * It's means "36911 - 43192" with intersection fix: "(36900 +10 +1) - (43200 -10 +2)" e.g. in seconds "36900 - 43200" is equal to "10:15 - 12:00"
326 *
327 * @param string $time_range_in_seconds "36911 - 43192"
328 *
329 * @return string $time_slot "10:15 - 12:00"
330 */
331 function wpbc_convert__time_range_in_seconds__to__readable_time_slot( $time_range_in_seconds ) {
332
333 $rangeA_arr = explode( '-', $time_range_in_seconds );
334 $rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
335 $rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
336
337 $time_slot = array();
338
339 foreach ( $rangeA_arr as $is_end_time => $in_seconds ) { // $is_end_time = 0 | 1
340
341 if ( ! $is_end_time ) {
342
343 if ( WPBC_FULL_DAY_TIME_IN == $in_seconds ) { // situation: 00:00 e.g. 1 sec.
344 $in_seconds = 0;
345 } else {
346 $in_seconds = $in_seconds - 10 - 1;
347 }
348
349 } else {
350
351 if ( WPBC_FULL_DAY_TIME_OUT == $in_seconds ) { // situation: 24:00 e.g. 86400 -10 +2 sec.
352 $in_seconds = 86400;
353 } else {
354 $in_seconds = $in_seconds + 10 - 2;
355 }
356 }
357
358 $just_minutes_as_seconds = $in_seconds % ( 60 * 60 );
359
360 $in_hours = ( $in_seconds - $just_minutes_as_seconds ) / ( 60 * 60 ); // 43200
361 $in_minutes = $just_minutes_as_seconds / 60; // 43200
362
363 $in_hours = intval($in_hours); // from 20.99 hours get 20 // round( $in_hours, 0, PHP_ROUND_HALF_DOWN );
364 $in_minutes = intval($in_minutes); // from 55.99 minutes get 55 // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN ); // making 1.5 into 1 and -1.5 into -1.
365
366 $in_hours = ( $in_hours < 10 ) ? '0' . $in_hours : $in_hours;
367 $in_minutes = ( $in_minutes < 10 ) ? '0' . $in_minutes : $in_minutes;
368
369 $time_slot[] = $in_hours . ':' . $in_minutes;
370 }
371
372 $time_slot = implode( ' - ', $time_slot );
373
374 return $time_slot;
375 }
376
377
378 /**
379 * Get SQL TIME from SECONDS 43211 -> '12:00:11'
380 *
381 * @param int $in_seconds 43201
382 *
383 * @return string '10:00:02'
384 */
385 function wpbc_transform__seconds__in__24_hours_his( $in_seconds ){
386
387 $rest_without_hours_as_seconds = $in_seconds % ( 60 * 60 );
388
389 $in_hours = ( $in_seconds - $rest_without_hours_as_seconds ) / ( 60 * 60 ); // 12
390 $in_hours = intval( $in_hours ); // from 20.99 hours get 20 // round( $in_hours, 0, PHP_ROUND_HALF_DOWN );
391
392 $in_minutes = $rest_without_hours_as_seconds / 60; // 43200
393 $in_minutes = intval( $in_minutes ); // from 55.99 minutes get 55 // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN ); // making 1.5 into 1 and -1.5 into -1.
394
395 $in_only_seconds = $in_seconds - ( $in_hours * 60 * 60 ) - ( $in_minutes * 60 ); // 43200
396 $in_only_seconds = intval( $in_only_seconds ); // from 55.99 minutes get 55 // round( $in_minutes, 0, PHP_ROUND_HALF_DOWN ); // making 1.5 into 1 and -1.5 into -1.
397
398
399 $in_hours = ( $in_hours < 10 ) ? '0' . $in_hours : $in_hours;
400 $in_minutes = ( $in_minutes < 10 ) ? '0' . $in_minutes : $in_minutes;
401 $in_only_seconds = ( $in_only_seconds < 10 ) ? '0' . $in_only_seconds : $in_only_seconds;
402
403 $sql_time_his = $in_hours . ':' . $in_minutes . ':'. $in_only_seconds;
404
405 return $sql_time_his;
406 }
407
408
409 /**
410 * Get time in seconds from SQL time format '12:00:02' -> 43192
411 *
412 * @param string $sql_time_his '12:00:02'
413 *
414 * @return int
415 */
416 function wpbc_transform__24_hours_his__in__seconds( $in_24_hours_his ) {
417
418 $is_apply__check_in_out__10s = false;
419
420 return wpbc_convert__time_his__to_seconds( $in_24_hours_his, $is_apply__check_in_out__10s );
421 }
422
423 /**
424 * Get AM/PM or 24 hour TIME from SECONDS 43211 -> '12:00 PM' | 86400 -> '12:00 AM'
425 *
426 * @param int $in_seconds 43201
427 * @param string $time_format '' (optional) time format, like 'H:i:s' otherwise get from Booking > Settings General
428 *
429 * @return string '10:00:02' | '10:00 AM'
430 */
431 function wpbc_transform__seconds__in__formated_hours( $in_seconds, $time_format = '' ) {
432
433 if ( empty( $time_format ) ) {
434 $time_format = get_bk_option( 'booking_time_format' ); // get from Booking Calendar
435 if ( empty( $time_format ) ) {
436 $time_format = get_option( 'time_format' ); // Get WordPress default
437 }
438 }
439
440 if ( $in_seconds >= 86400 ) {
441 // if we have 24:00 then instead of 00:00 show 24:00 ... Please check more here https://www.php.net/manual/en/datetime.format.php
442 $time_format = str_replace( array( 'H', 'G' ), '24', $time_format );
443 }
444
445 $s_tm = date_i18n( $time_format, $in_seconds );
446
447 return $s_tm;
448 }
449
450 // -----------------------------------------------------------------------------------------------------------------
451
452
453 /**
454 * Union 2 time-slot ranges: "100 - 900" & "500 - 3500" -> [ "100 - 3500" ] OR "10 - 70" & "100 - 500" -> [ "10 - 70", "100 - 500" ]
455 *
456 * @param $timeslot_A_in_range_seconds '36011 - 86392' it is means: "'Start time1 in seconds' - 'End time1 in seconds'" e.g. "10:00 - 24:00"
457 * @param $timeslot_B_in_range_seconds '1 - 43192' it is means: "'Start time2 in seconds' - 'End time2 in seconds'" e.g. "00:00 - 12:00"
458 *
459 * @return array [ "1 - 86392" ] one or two ranges
460 *
461 */
462 function wpbc_union__timeslots_seconds( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds ) {
463
464 if ( ! wpbc_is__timeslots_seconds__intersected( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds ) ) {
465 return array( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds );
466 }
467
468 if ( ( '0' == $timeslot_A_in_range_seconds ) || ( '0' == $timeslot_B_in_range_seconds ) ) {
469 return array( '0 - 86400' ); // Old Full day booking, it is means always intersect.
470 }
471
472 $rangeA_arr = explode( '-', $timeslot_A_in_range_seconds );
473 $rangeB_arr = explode( '-', $timeslot_B_in_range_seconds );
474
475 $rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
476 $rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
477 $rangeB_arr[0] = intval( trim( $rangeB_arr[0] ) );
478 $rangeB_arr[1] = intval( trim( $rangeB_arr[1] ) );
479
480 $start = min( $rangeA_arr[0], $rangeB_arr[0] );
481 $end = max( $rangeA_arr[1], $rangeB_arr[1] );
482 $result = array( $start . ' - ' . $end );
483
484 return $result;
485 }
486
487
488 /**
489 * Is 2 time-slots ranges intersected: "36011 - 86392" <=> "1 - 43192" = true ( intersected )
490 *
491 * Good explanation here https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
492 *
493 * @param $timeslot_A_in_range_seconds '36011 - 86392' it is means: "'Start time1 in seconds' - 'End time1 in seconds'" e.g. "10:00 - 24:00"
494 * @param $timeslot_B_in_range_seconds '1 - 43192' it is means: "'Start time2 in seconds' - 'End time2 in seconds'" e.g. "00:00 - 12:00"
495 *
496 * @return bool
497 *
498 *
499 * Some exceptions:
500 * if range = '0' - it is means Full day booking, it's always intersected !
501 * all start times ended with "1" second and previously was added +10 seconds, that's why 36011 is means 36011 - 10 - 1 = 36000 e.g. = 10:00
502 * all end times ended with "2" second and previously was -10 seconds, that's why 43192 is means 43192 + 10 - 2 = 43200 e.g. = 12:00
503 *
504 * When in some date we have ONLY start time or end time, it's means that this time start from 00:00 or end at 24:00 (because usually such bookings for SEVERAL days)
505 * and we autofill such times by adding start time or end time:
506 * Autofilled start time is always 1 = 0 +1 - 00:01
507 * Autofilled end time is always 86392 = 86400 -10 +2 - 23:59:58
508 */
509 function wpbc_is__timeslots_seconds__intersected( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds ) {
510
511 // Full day booking, it is means always intersect.
512 if ( ( '0' == $timeslot_A_in_range_seconds ) || ( '0' == $timeslot_B_in_range_seconds ) ) {
513 return true; // Time ranges INTERSECTED
514 }
515
516 $rangeA_arr = explode( '-', $timeslot_A_in_range_seconds );
517 $rangeB_arr = explode( '-', $timeslot_B_in_range_seconds );
518
519 $rangeA_arr[0] = intval( trim( $rangeA_arr[0] ) );
520 $rangeA_arr[1] = intval( trim( $rangeA_arr[1] ) );
521 $rangeB_arr[0] = intval( trim( $rangeB_arr[0] ) );
522 $rangeB_arr[1] = intval( trim( $rangeB_arr[1] ) );
523
524
525 $is_intersected = max( $rangeA_arr[0], $rangeB_arr[0] ) - min( $rangeA_arr[1], $rangeB_arr[1] );
526
527 // if ( 0 == $is_intersected ) {
528 // // Such ranges going one after other, e.g.: "12:00 - 15:00" and "15:00 - 21:00"
529 // }
530
531 if ( $is_intersected < 0 ) {
532 return true; // Time ranges INTERSECTED
533 }
534
535 return false; // Otherwise time slot not intersected
536 }
537
538
539 /**
540 * Is 2 time-slots ranges intersected: "10:00 - 24:00" <=> "00:00 - 12:00" = true ( intersected )
541 *
542 *
543 * @param $timeslot_A_readable '10:00 - 24:00'
544 * @param $timeslot_B_readable '00:00 - 12:00'
545 *
546 * @return bool
547 *
548 *
549 * See more here: wpbc_is__timeslots_seconds__intersected()
550 */
551 function wpbc_is__timeslots_readable__intersected( $timeslot_A_readable, $timeslot_B_readable ) {
552
553 // Full day booking, it is means always intersect.
554 if ( ( '0' == $timeslot_A_readable ) || ( '0' == $timeslot_B_readable ) ) {
555 return true; // Time ranges INTERSECTED
556 }
557
558 $timeslot_A_in_range_seconds = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $timeslot_A_readable );
559 $timeslot_B_in_range_seconds = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $timeslot_B_readable );
560
561 return wpbc_is__timeslots_seconds__intersected( $timeslot_A_in_range_seconds, $timeslot_B_in_range_seconds );
562 }
563
564
565 // -----------------------------------------------------------------------------------------------------------------
566
567 /**
568 * Check if BOOKING_FORM time-slots available and not intersect with booked time slots from bookings
569 *
570 *
571 * @param array $checking__timerange_sec__arr [ '36011 - 43192', '56011 - 86392' ]
572 * @param array $booked__timerange_sec__arr [ '36011 - 43192' ]
573 *
574 * @return bool true | false
575 *
576 *
577 * if $checking__timerange_sec__arr EMPTY then TRUE
578 *
579 */
580 function wpbc_is_some_timeslot__available__in_arr( $checking__timerange_sec__arr, $booked__timerange_sec__arr ) {
581
582 if ( empty( $checking__timerange_sec__arr ) ) {
583 return true;
584 }
585
586 $is_available__timeslots__arr = array();
587
588 // Available_Form time-slots: [ "10:00 - 12:00", "12:00 - 14:00", "14:00 - 16:00" ]
589 foreach ( $checking__timerange_sec__arr as $checking__timeslot__key => $checking__timeslot__value ) {
590
591 $is_available__timeslots__arr[ $checking__timeslot__key ] = true;
592
593 // Booked time-slots: [ "12:00 - 14:00", "14:00 - 16:00" ]
594 foreach ( $booked__timerange_sec__arr as $booked__timeslot_value ) {
595
596 $is_time_intersected = wpbc_is__timeslots_seconds__intersected( $booked__timeslot_value, $checking__timeslot__value ); // '36011 - 43192', '56011 - 86392'
597 if ( $is_time_intersected ) {
598 $is_available__timeslots__arr[ $checking__timeslot__key ] = false;
599 break;
600 }
601 }
602 }
603
604 // If at least one time slot available then day still available
605 $is_some_timeslot_available = false;
606 foreach ( $is_available__timeslots__arr as $is__timeslot_available ) {
607 if ( $is__timeslot_available ) {
608 $is_some_timeslot_available = true;
609 break;
610 }
611 }
612
613 return $is_some_timeslot_available;
614 }
615
616 // -----------------------------------------------------------------------------------------------------------------
617
618 /**
619 * '43211 - 86392' into [43201, 86400]
620 *
621 * @param string $booked_times__key_arr
622 * @param bool $is_apply_end_time_correction
623 *
624 * @return array|string[]
625 */
626 function wpbc_transform_timerange__s_range__in__seconds_arr( $booked_times__key_arr, $is_apply_end_time_correction = true ){
627
628 $booked_times__key_arr = explode( ' - ', $booked_times__key_arr );
629
630 $booked_times__key_arr[0] = intval( trim( $booked_times__key_arr[0] ) );
631 $booked_times__key_arr[1] = intval( trim( $booked_times__key_arr[1] ) );
632
633 if ( $is_apply_end_time_correction ) {
634
635 // Fix when we have 10:00:11 seconds, and we need to show the 14:00:02
636 if ( '1' == substr( (string) $booked_times__key_arr[0], - 1 ) ) {
637 $booked_times__key_arr[0] = $booked_times__key_arr[0] - 10;
638 }
639 $booked_times__key_arr[0] = ( $booked_times__key_arr[0] < 0 ) ? 1 : $booked_times__key_arr[0];
640
641 // Fix when we have 13:59:52 seconds, and we need to show the 14:00:02
642 if ( '2' == substr( (string) $booked_times__key_arr[1], - 1 ) ) {
643 $booked_times__key_arr[1] = $booked_times__key_arr[1] + 10;
644 }
645
646 $booked_times__key_arr[1] = ( $booked_times__key_arr[1] > 86400 ) ? 86400 : $booked_times__key_arr[1];
647 }
648
649 return $booked_times__key_arr;
650 }
651
652
653 /**
654 * [43211, 86400] -> '12:00:11 - 24:00:00'
655 *
656 * @param $booked_times__key_arr
657 *
658 * @return string
659 */
660 function wpbc_transform_timerange__seconds_arr__in__24_hours_range( $booked_times__key_arr ){
661
662 $readable_time_slot_formatted = wpbc_transform__seconds__in__24_hours_his( $booked_times__key_arr[0] )
663 . ' - '
664 . wpbc_transform__seconds__in__24_hours_his( $booked_times__key_arr[1] ) ;
665
666 return $readable_time_slot_formatted;
667 }
668
669
670 /**
671 * [43211, 86400] -> '12:00 PM - 12:00 AM' - transform time-range in General Settings - Time Format
672 *
673 * @param $booked_times__key_arr
674 *
675 * @return string
676 */
677 function wpbc_transform_timerange__seconds_arr__in__formated_hours( $booked_times__key_arr ){
678
679 $readable_time_slot_formatted = wpbc_transform__seconds__in__formated_hours( $booked_times__key_arr[0] )
680 . ' - '
681 . wpbc_transform__seconds__in__formated_hours( $booked_times__key_arr[1] ) ;
682
683 return $readable_time_slot_formatted;
684 }
685
686
687 /**
688 * Converts a period of time in seconds into a human-readable format representing the interval.
689 *
690 * @param int $time_interval_in_seconds : 90 - A period of time in seconds.
691 *
692 * @return string : '1 minute 30 seconds'
693 *
694 * Example:
695 *
696 * echo wpbc_get_readable_time_interval( 90 ); <- 1 minute 30 seconds
697 *
698 */
699 function wpbc_get_readable_time_interval( $time_interval_in_seconds ) {
700
701 // Array of time period chunks.
702 $chunks = array(
703 /* translators: 1: The number of years in an interval of time. */
704 array( 60 * 60 * 24 * 365, _n_noop( '%s year', '%s years', 'booking' ) ),
705 /* translators: 1: The number of months in an interval of time. */
706 array( 60 * 60 * 24 * 30, _n_noop( '%s month', '%s months', 'booking' ) ),
707 /* translators: 1: The number of weeks in an interval of time. */
708 array( 60 * 60 * 24 * 7, _n_noop( '%s week', '%s weeks', 'booking' ) ),
709 /* translators: 1: The number of days in an interval of time. */
710 array( 60 * 60 * 24, _n_noop( '%s day', '%s days', 'booking' ) ),
711 /* translators: 1: The number of hours in an interval of time. */
712 array( 60 * 60, _n_noop( '%s hour', '%s hours', 'booking' ) ),
713 /* translators: 1: The number of minutes in an interval of time. */
714 array( 60, _n_noop( '%s minute', '%s minutes', 'booking' ) ),
715 /* translators: 1: The number of seconds in an interval of time. */
716 array( 1, _n_noop( '%s second', '%s seconds', 'booking' ) ),
717 );
718
719 if ( ( $time_interval_in_seconds <= 0 ) || ( ! is_int( $time_interval_in_seconds ) ) ) {
720 return __( 'now', 'booking' );
721 }
722
723 /**
724 * We only want to output two chunks of time here, eg:
725 * x years, xx months
726 * x days, xx hours
727 * so there's only two bits of calculation below:
728 */
729 $j = count( $chunks );
730
731 // Step one: the first chunk.
732 for ( $i = 0; $i < $j; $i++ ) {
733 $seconds = $chunks[ $i ][0];
734 $name = $chunks[ $i ][1];
735
736 // Finding the biggest chunk (if the chunk fits, break).
737 $count = floor( $time_interval_in_seconds / $seconds );
738 if ( $count ) {
739 break;
740 }
741 }
742
743 // Set output var.
744 $output = sprintf( translate_nooped_plural( $name, $count, 'booking' ), $count );
745
746 // Step two: the second chunk.
747 if ( $i + 1 < $j ) {
748 $seconds2 = $chunks[ $i + 1 ][0];
749 $name2 = $chunks[ $i + 1 ][1];
750 $count2 = floor( ( $time_interval_in_seconds - ( $seconds * $count ) ) / $seconds2 );
751 if ( $count2 ) {
752 // Add to output var.
753 $output .= ' ' . sprintf( translate_nooped_plural( $name2, $count2, 'booking' ), $count2 );
754 }
755 }
756
757 return $output;
758 }
759
760
761 // =====================================================================================================================
762 // == D A T E S M a i n l y ===
763 // =====================================================================================================================
764
765
766 /**
767 * Conception: - Time-Slots A - B '10:00:01 - 12:00:02' '10:00:01 - 12:00:02'
768 *
769 * - Check in A - ... '14:00:01 - ... ' '14:00:01 - 24:00:00'
770 * - Check out ... - B ' ... - 12:00:02' '00:00:00 - 12:00:02'
771 *
772 * - Full day ... - ... ' ... - ... ' '00:00:00 - 24:00:00'
773 *
774 * - Full IN ..1 - ... '00:00:01 - ... ' '00:00:01 - 24:00:00'
775 * - Full OUT ... - ..2 ' ... - 24:00:02' '00:00:00 - 24:00:02'
776 *
777 *
778 * 1) Always in one specific date, can be start & end times.
779 * 2) Such start end times can define
780 *
781 */
782
783 // ---------------------------------------------------------------------------------------------------------------------
784 // Support Transformation functions for dates arrays
785 // ---------------------------------------------------------------------------------------------------------------------
786
787 /**
788 * From SQL dates array generate new Extended Dates Array: [ > resource_id < ][ > booking_id < ] => Obj( 'sql__booking_dates__arr':[
789 * [ >seconds< ] => > SQL DATE <
790 * [1693303211] => 2023-08-29 10:00:01
791 * [1693353600] => 2023-08-30 00:00:00
792 * [1693483192] => 2023-08-31 12:00:02
793 * ]
794 * , ... )
795 * @param array $params = array [
796 'sql_dates_arr' = [
797 [0] => stdClass Object (
798 [booking_date] => 2023-08-08 10:00:01
799 [approved] => 1
800 [date_res_type] =>
801 [booking_id] => 45
802 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^...
803 [parent] => 0
804 [prioritet] => 20
805 [type] => 2
806 )
807 [1] => stdClass Object (
808 [booking_date] => 2023-08-08 10:00:01
809 [approved] => 0
810 [date_res_type] =>
811 [booking_id] => 46
812 [form] => selectbox-one^rangetime10^10:00 - 12:00~text^...
813 [parent] => 2
814 [prioritet] => 1
815 [type] => 10
816 ), ...
817 , ...]
818 , 'is_sort__dates_arr' => true
819 , 'is_apply__check_in_out__10s' => true
820 ]
821 *
822 * @return array = [ > resource_id < ][ > booking_id < ] => obj( ... )
823
824 Example:
825 [
826 [3] = [
827 [64] = obj{
828 booking_date = "2023-09-26 14:00:01"
829 approved = "0"
830 date_res_type = null
831 booking_id = "64"
832 form = "text^selected_short_dates_hint3^...
833 parent = "0"
834 prioritet = "30"
835 type = "3"
836 __summary__booking = [
837 sql__booking_dates__arr = [ 1695736811 = "2023-09-26 14:00:01"
838 1695772800 = "2023-09-27 00:00:00"
839 1695902392 = "2023-09-28 12:00:02"
840 ]
841 ]
842 }
843 [47] => stdClass Object(...)
844 ...
845 ]
846 ...
847 ]
848 *
849 *
850 * Each such booking is date object with additional property: -> __summary__booking[ 'sql__booking_dates__arr' ]
851 * It is array of ALL Dates (in SQL date format) for specific booking
852 * Then if needed, we extend booked dates on specific number of times or hours/minutes
853 *
854 *
855 * Relative this: ['__summary__booking']['sql__booking_dates__arr'] = [
856 1695736811 = "2023-09-26 14:00:01"
857 1695772800 = "2023-09-27 00:00:00"
858 1695902392 = "2023-09-28 12:00:02"
859 ]
860 * '1695736811' - timestamp of check in/out dates on 10 seconds less/higher than SQL date '2023-09-26 14:00:01'
861 *
862 */
863 function wpbc_support__transform__into__resource_booking_dates__arr( $params ){
864
865 $defaults = array(
866 'sql_dates_arr' => array()
867 , 'is_sort__dates_arr' => true
868 , 'is_apply__check_in_out__10s' => true
869 );
870 $params = wp_parse_args( $params, $defaults );
871
872
873 $result_arr = array();
874
875 foreach ( $params['sql_dates_arr'] as $date_object ) {
876
877 $booking_id = $date_object->booking_id; // '43'
878 $resource_id = ( ! empty( $date_object->date_res_type ) ) ? $date_object->date_res_type : $date_object->type; // '12'
879
880 if ( empty( $result_arr[ $resource_id ] ) ) { $result_arr[ $resource_id ] = array(); }
881 if ( empty( $result_arr[ $resource_id ][$booking_id] ) ) {
882
883 $result_arr[ $resource_id ][$booking_id] = $date_object;
884 $result_arr[ $resource_id ][$booking_id]->__summary__booking = array( 'sql__booking_dates__arr' => array() ); // New '__summary__booking' property
885 }
886
887 // Get seconds timestamp
888 $in_seconds = wpbc_convert__sql_date__to_seconds( $date_object->booking_date, $params['is_apply__check_in_out__10s'] );
889
890 $result_arr[ $resource_id ][ $booking_id ]->__summary__booking[ 'sql__booking_dates__arr' ][ $in_seconds ] = $date_object->booking_date;
891
892
893 // Sort new array with dates
894 if ( $params['is_sort__dates_arr'] ) {
895 ksort( $result_arr[ $resource_id ][ $booking_id ]->__summary__booking[ 'sql__booking_dates__arr' ] );
896 }
897 }
898
899 return $result_arr;
900 }
901
902
903 /**
904 * Transform Into: ['2024-01-28'][ > resource_id < ][ > booking_id < ][ > only_time_seconds_int < ] => obj( booking_date: "2024-01-28 10:00:01", ... )
905 *
906 * @param array $params = [
907 * 'is_apply__check_in_out__10s' => true
908 * 'resource_booking_dates_arr' => array = [ > resource_id < ][ > booking_id < ] => obj( ... )
909 * ]
910 *
911 * Example:
912 *
913 * $params['resource_booking_dates_arr'] = [
914 * [3] = [
915 * [64] = obj{
916 * booking_date = "2023-09-26 14:00:01"
917 * approved = "0"
918 * date_res_type = null
919 * booking_id = "64"
920 * form = "text^selected_short_dates_hint3^...
921 * parent = "0"
922 * prioritet = "30"
923 * type = "3"
924 * __summary__booking = [
925 * sql__booking_dates__arr = [ 1695736811 = "2023-09-26 14:00:01"
926 * 1695772800 = "2023-09-27 00:00:00"
927 * 1695902392 = "2023-09-28 12:00:02"
928 * ]
929 * ]
930 * }
931 * [47] => stdClass Object(...)
932 * ...
933 * ]
934 * ...
935 * ]
936 *
937 * @return array - ['2024-01-28'][ > resource_id < ][ > booking_id < ][ > only_time_seconds < ] => obj( booking_date: "2024-01-28 10:00:01", ... )
938 *
939 * Example:
940 * result = [
941 * 2023-08-01 = [
942 * 3 = [
943 * 62 = [
944 * 36011 = {stdClass}
945 * 43192 = {
946 * booking_date = "2023-08-01 12:00:02"
947 * approved = "0"
948 * date_res_type = null
949 * booking_id = "62"
950 * form = "selectbox-multiple^rangetime3[]^10:00 - 12:00~...
951 * parent = "0"
952 * prioritet = "30"
953 * type = "3"
954 * __summary__booking = [
955 * sql__booking_dates__arr = [
956 * 1690884011 = "2023-08-01 10:00:01"
957 * 1690891192 = "2023-08-01 12:00:02"
958 * ]
959 * ]
960 * }
961 * ]
962 * ]
963 * ]
964 * 2023-08-05 = [ ... ]
965 * ]
966 */
967 function wpbc_support__transform__into__date_resource_booking_timesec__arr( $params ){
968
969 $defaults = array(
970 'resource_booking_dates_arr' => array()
971 , 'is_apply__check_in_out__10s' => true
972 );
973 $params = wp_parse_args( $params, $defaults );
974
975
976 $result__arr = array();
977 foreach ( $params['resource_booking_dates_arr'] as $resource_id => $bookings_arr ) {
978
979 foreach ( $bookings_arr as $booking_id => $booking_obj ) {
980
981 $extended_dates_arr = ( isset( $booking_obj->__summary__booking['sql__booking_dates__arr__extended'] ) )
982 ? $booking_obj->__summary__booking['sql__booking_dates__arr__extended']
983 : $booking_obj->__summary__booking['sql__booking_dates__arr'];
984
985 foreach ( $extended_dates_arr as $extended_date_time_stamp => $extended_date_sql ) {
986
987 $new_extended_date_obj = wpbc_clone_array_of_objects( $booking_obj );
988 $new_extended_date_obj->booking_date = $extended_date_sql;
989
990 list( $date_without_time, $only_time ) = explode( ' ', $new_extended_date_obj->booking_date ); // '2024-01-28', '12:00:02'
991 $seconds_int = wpbc_convert__time_his__to_seconds( $only_time, $params['is_apply__check_in_out__10s'] ); // 43202
992
993 if ( ! isset( $result__arr[ $date_without_time ] ) ) { $result__arr[ $date_without_time ] = array(); }
994 if ( ! isset( $result__arr[ $date_without_time ][ $resource_id ] ) ) { $result__arr[ $date_without_time ][ $resource_id ] = array(); }
995 if ( ! isset( $result__arr[ $date_without_time ][ $resource_id ][ $booking_id ] ) ) { $result__arr[ $date_without_time ][ $resource_id ][ $booking_id ] = array(); }
996
997 $result__arr[ $date_without_time ][ $resource_id ][ $booking_id ][ $seconds_int ] = $new_extended_date_obj;
998 }
999 }
1000 }
1001
1002 return $result__arr;
1003 /**
1004 2024-01-28 = [ > resource_id <
1005 12 => [ > booking_id <
1006 43 => [ > seconds <
1007 36001 => Obj[
1008 booking_date = "2024-01-28 10:00:01"
1009 date_res_type = null
1010 booking_id = "43"
1011 approved = "0"
1012 form = "selectbox-one^rangetime12^10:00 - 12:00~text^..."
1013 parent = "2"
1014 type = "12"
1015 ...
1016 ]
1017 43202 => Obj[
1018 type = "12"
1019 */
1020 }
1021
1022
1023 /**
1024 * Transform Into: ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
1025 *
1026 * @param array $params [
1027 * 'is_apply__check_in_out__10s' => true
1028 * 'date_resource_booking_timesec_arr' => [
1029 * 2023-08-01 = [
1030 * 3 = [
1031 * 62 = [
1032 * 36011 = {stdClass}
1033 * 43192 = {
1034 * booking_date = "2023-08-01 12:00:02"
1035 * approved = "0"
1036 * date_res_type = null
1037 * booking_id = "62"
1038 * form = "selectbox-multiple^rangetime3[]^10:00 - 12:00~...
1039 * parent = "0"
1040 * prioritet = "30"
1041 * type = "3"
1042 * __summary__booking = [
1043 * sql__booking_dates__arr = [
1044 * 1690884011 = "2023-08-01 10:00:01"
1045 * 1690891192 = "2023-08-01 12:00:02"
1046 * ]
1047 * ]
1048 * }
1049 * ]
1050 * ]
1051 * ]
1052 * 2023-08-05 = [ ... ]
1053 * ]
1054 *
1055 * @return array = ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
1056 *
1057 * Example: [
1058 [2023-08-08] => [
1059 [2] => [
1060 [36011 - 86392] => stdClass Object ( [booking_date] => 2023-08-08 10:00:01 , .... )
1061 ]
1062 [10] => [
1063 [36011 - 86392] => stdClass Object ( [booking_date] => 2023-08-08 10:00:01 , .... )
1064 ]
1065 ]
1066 [2023-08-09] => [
1067 [2] => [
1068 [0] => stdClass Object ( [booking_date] => 2023-08-09 00:00:00, .... )
1069 ]
1070 [10] => [
1071 [36011 - 43192] => stdClass Object ( [booking_date] => 2023-08-30 12:00:02
1072 , ....
1073 __summary__booking = [
1074 sql__booking_dates__arr = [
1075 1690884011 = "2023-08-01 10:00:01"
1076 1690891192 = "2023-08-01 12:00:02"
1077 ]
1078 ]
1079 )
1080 ]
1081 ]
1082 ]
1083
1084 */
1085 function wpbc_support__transform__into__date_resource_timesec_range__arr( $params ){
1086
1087 $defaults = array(
1088 'date_resource_booking_timesec_arr' => array()
1089 , 'is_apply__check_in_out__10s' => true
1090 );
1091 $params = wp_parse_args( $params, $defaults );
1092
1093
1094 $result__arr = array();
1095
1096 foreach ( $params[ 'date_resource_booking_timesec_arr' ] as $a_only_date => $a_resources_arr ) { // '2023-07-25' => array( resource_id => bookings_arr )
1097
1098 foreach ( $a_resources_arr as $a_resource_id => $a_bookings_arr ) { // 1 => array( booking_id => times_arr )
1099
1100 foreach ( $a_bookings_arr as $a_booking_id => $a_seconds_arr_in_1_booking ) { // 10 => array ( second => stdObj( booking_date obj from DB )
1101
1102 if ( ! isset( $result__arr[ $a_only_date ] ) ) { $result__arr[ $a_only_date ] = array(); }
1103 if ( ! isset( $result__arr[ $a_only_date ][ $a_resource_id ] ) ) { $result__arr[ $a_only_date ][ $a_resource_id ] = array(); }
1104
1105 // Check all TIMES for SAME booking:
1106 $all_seconds_for_this_booking_arr = array();
1107
1108 foreach ( $a_seconds_arr_in_1_booking as $a_second => $a_booking_obj ) { // 0 => stdObj( booking_date obj from DB )
1109 $all_seconds_for_this_booking_arr[] = $a_second;
1110 }
1111
1112 /**
1113 * [ 36011 ] -> '36011 - 86392' | [36011, 43192] -> '36011 - 43192'
1114 *
1115 * In case if we have only start time or end time for specific SAME Booking, then we need to fill times: .. - 10:00 or 14:00 - ..
1116 */
1117 $all_seconds__key__time_range = wpbc__get_time_range__from_times_arr( $all_seconds_for_this_booking_arr );
1118
1119
1120 // For debugging only ! -------------------------------------------------------------------------------
1121 $test_unexpected = explode( '-', $all_seconds__key__time_range );
1122 if ( count( $test_unexpected ) > 2 ) {
1123 echo "WPBC. Unexpected situation. We have more than 2 times for the booking {$a_booking_id}: {$all_seconds__key__time_range}";
1124 debuge( '$a_only_date, $a_resource_id, $a_booking_id, $all_seconds_for_this_booking_arr',
1125 $a_only_date, $a_resource_id, $a_booking_id, $all_seconds_for_this_booking_arr, __FILE__, __LINE__ );
1126 }
1127 // For debugging only ! -------------------------------------------------------------------------------
1128
1129 $result__arr[ $a_only_date ][ $a_resource_id ][ $all_seconds__key__time_range ] = $a_booking_obj;
1130 }
1131 }
1132 }
1133
1134 return $result__arr;
1135 }
1136
1137
1138 /**
1139 * Transform [ 36011 ] -> '36011 - 86392' | [36011, 43192] -> '36011 - 43192'
1140 *
1141 * @param array $all_seconds_for_this_booking_arr [ 36011 ] [36011, 43192]
1142 *
1143 * @return string '36011 - 86392' '36011 - 43192'
1144 */
1145 function wpbc__get_time_range__from_times_arr( $all_seconds_for_this_booking_arr ){
1146
1147 // In case if we have only start time or end time for specific SAME Booking, then we need to fill times: .. - 10:00 or 14:00 - ..
1148 if ( 1 == count( $all_seconds_for_this_booking_arr ) ) {
1149
1150 $seconds__this__booking = $all_seconds_for_this_booking_arr[0];
1151 //$is_check_in_out__or_full = $seconds__this__booking % 10; // 1, 2 (not 0)
1152
1153 $is_check_in_out__or_full = substr( ( (string) $seconds__this__booking ), -1 ); // '1', '2' (not '0')
1154
1155 if ( '1' == $is_check_in_out__or_full ) {
1156 $all_seconds_for_this_booking_arr = array( $seconds__this__booking, WPBC_FULL_DAY_TIME_OUT ); // 24 hours - 10 seconds + 2 seconds (2 sec. - because check out)
1157 }
1158 if ( '2' == $is_check_in_out__or_full ) {
1159 $all_seconds_for_this_booking_arr = array( WPBC_FULL_DAY_TIME_IN, $seconds__this__booking ); // + 1 second (1 sex. - because check in)
1160 }
1161 }
1162
1163 if ( count( $all_seconds_for_this_booking_arr ) > 2 ) {
1164 // Non standard situation ??? !!!
1165 }
1166
1167 $all_seconds__key__time_range = implode( ' - ', $all_seconds_for_this_booking_arr );
1168
1169 return $all_seconds__key__time_range;
1170 }
1171
1172
1173
1174 // ---------------------------------------------------------------------------------------------------------------------
1175 // Get READABLE_DATES_ARR & create WPBC_BOOKING_DATE for each bookings in [ > resource_id < ][ > booking_id < ][ ... ]
1176 // ---------------------------------------------------------------------------------------------------------------------
1177
1178 // GOOD
1179 /**
1180 * Loop all Resources / Bookings to set 'WPBC_BOOKING_DATE' Objects: [ > resource_id < ][ > booking_id < ] => ['__summary__booking']['sql__booking_dates__arr']['_readable_dates'] = [ 2023-09-01: [ 0: "00:00:01 - 24:00:00" ] , ... ]
1181 *
1182 * @param $resources__booking_id__obj = [ > resource_id < ][ > booking_id < ] => obj( ... )
1183 *
1184 * @return $resources__booking_id__obj = [
1185 * 3 = [
1186 * 62 = {stdClass}
1187 * 63 = {
1188 * booking_date = "2023-09-01 00:00:00"
1189 * approved = "0"
1190 * date_res_type = null
1191 * booking_id = "63"
1192 * form = "text^selected_short_dates_hint3^September 1, 2023...
1193 * parent = "0"
1194 * prioritet = "30"
1195 * type = "3"
1196 * __summary__booking = [
1197 * sql__booking_dates__arr = [
1198 *
1199 * ....
1200 */
1201 function wpbc__in_all_bookings__create_WPBC_BOOKING_DATE( $resources__booking_id__obj ){
1202
1203
1204 // [ > resource_id < ][ > booking_id < ] => obj( ['__summary__booking']['sql__booking_dates__arr'] [ ... , [ ' >seconds< '] => ' > SQL DATE < ' , ... ] )
1205 foreach ( $resources__booking_id__obj as $resource_id => $bookings_arr ) {
1206
1207 foreach ( $bookings_arr as $booking_id => $booking_obj ) {
1208
1209 $readable_datestimeslots_arr = wpbc__get__readable_dates_arr__from_timestamp_arr( $booking_obj->__summary__booking[ 'sql__booking_dates__arr' ] );
1210
1211 // New Dates Object - for this booking ID
1212 $boking_dates_obj = new WPBC_BOOKING_DATE( $readable_datestimeslots_arr );
1213
1214 $resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj' ] = $boking_dates_obj;
1215
1216 if ( $boking_dates_obj->is_debug ) {
1217 $resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj__24_hour_arr' ] = $boking_dates_obj->loop_all_dates( 'get_times__as_24_hour_arr' );
1218 $resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj__seconds_arr' ] = $boking_dates_obj->loop_all_dates( 'get_times__as_seconds_arr' );
1219 $resources__booking_id__obj[$resource_id][$booking_id]->__summary__booking[ '__dates_obj__timestamps_arr' ] = $boking_dates_obj->loop_all_dates( 'get_times__as_timestamps_arr' );
1220 }
1221
1222 }
1223 }
1224
1225 return $resources__booking_id__obj;
1226 }
1227
1228
1229 // =====================================================================================================================
1230 // Transform SQL dates INTO Readable time-slots by Dates
1231 //
1232 // All these below 5 functions required for transformation booked SQL dates: [ 1690884011 : "2023-08-01 10:00:01", ... ]
1233 // Into readable time slots by dates: [ '2023-08-01': [ "10:00:01 - 12:00:02" ], '2023-08-05': [ "10:00:01 - 12:00:02" ] ]
1234 // =====================================================================================================================
1235
1236 // GOOD
1237 /**
1238 * Transform SQL dates INTO Readable time-slots by Dates. Transform linear [ 1690884011 = "2023-08-01 10:00:01" , ... ] -> [ '2023-08-01': [ 0: "10:00:01 - 12:00:02" ], '2023-08-05': [ 0:"10:00:01 - 12:00:02" ] ...]
1239 *
1240 * @param array $sql_dates_arr [
1241 * 1690884011 = "2023-08-01 10:00:01"
1242 * 1690891192 = "2023-08-01 12:00:02"
1243 * ...
1244 * ]
1245 *
1246 * @return array
1247 * [
1248 * 2023-08-01 = [ 0 = "10:00:01 - 12:00:02" ]
1249 * 2023-08-05 = [ 0 = "10:00:01 - 12:00:02" ]
1250 * ]
1251 * OR
1252 * [
1253 * 2023-09-01 = [ 0 = "00:00:01 - 24:00:00" ]
1254 * 2023-09-03 = [ 0 = "00:00:00 - 24:00:00" ]
1255 * 2023-09-14 = [ 0 = "00:00:00 - 24:00:02" ]
1256 * ]
1257 *
1258 */
1259 function wpbc__get__readable_dates_arr__from_timestamp_arr( $sql_dates_arr ){
1260
1261 // Full Dates
1262 $is_all_dates_full = wpbc_is_all__fulldays__in_dates_arr( $sql_dates_arr );
1263 if ( $is_all_dates_full ) {
1264 $sql_dates_arr = wpbc__add_to__fulldays__check_in_out( $sql_dates_arr );
1265 }
1266
1267 /**
1268 * Convert timestamps to -> [ '2023-08-01' : [ 36011 = "10:00:01", 43192 = "12:00:02" ] , '2023-08-05' : [...] ... ]
1269 */
1270 $times_arr___by_dates = wpbc__transform__timestamp_arr__in__times_by_dates__arr( $sql_dates_arr );
1271
1272 /**
1273 * Convert to our concept times: -> [ '2023-08-01' : [ 0 = "10:00:01 - 12:00:02" ], '2023-08-05' : [ 0 = "10:00:01 - 12:00:02" ] ]
1274 */
1275 $times_arr___by_dates = wpbc__transform__times_by_dates__in__readable_dates_arr( $times_arr___by_dates );
1276
1277 return $times_arr___by_dates;
1278 }
1279
1280
1281 // GOOD
1282 /**
1283 * Convert times by dates: [ '2023-08-01': [ 36011: "10:00:01", ... ] ... ] -> [ '2023-08-01': [ 0: "10:00:01 - 12:00:02" ], '2023-08-05': [ 0:"10:00:01 - 12:00:02" ] ...]
1284 *
1285 * @param $times_arr___by_dates = [
1286 * 2023-08-01 = [
1287 * 36001 = "10:00:01"
1288 * 43202 = "12:00:02"
1289 * ]
1290 * 2023-08-05 = [
1291 * 36001 = "10:00:01"
1292 * 43202 = "12:00:02"
1293 * ]
1294 * ]
1295 *
1296 * @return array
1297 * [
1298 * 2023-08-01 = [ 0 = "10:00:01 - 12:00:02" ]
1299 * 2023-08-05 = [ 0 = "10:00:01 - 12:00:02" ]
1300 * ]
1301 * OR
1302 * [
1303 * 2023-09-01 = [ 0 = "00:00:01 - 24:00:00" ]
1304 * 2023-09-03 = [ 0 = "00:00:00 - 24:00:00" ]
1305 * 2023-09-14 = [ 0 = "00:00:00 - 24:00:02" ]
1306 * ]
1307 *
1308 *
1309 *
1310 *
1311 * from this:
1312 *
1313 * $times_arr___by_dates = [
1314 * 2023-09-01 = [
1315 * 1 = "00:00:01"
1316 * ]
1317 * 2023-09-03 = [
1318 * 0 = "00:00:00"
1319 * ]
1320 * 2023-09-14 = [
1321 * 86402 = "24:00:02"
1322 * ]
1323 * ]
1324 * OR this:
1325 * [
1326 * 2023-08-01 = [
1327 * 36001 = "10:00:01"
1328 * 43202 = "12:00:02"
1329 * ]
1330 * 2023-08-05 = [
1331 * 36001 = "10:00:01"
1332 * 43202 = "12:00:02"
1333 * ]
1334 * ]
1335 * OR
1336 * [
1337 * 2023-09-26 = [
1338 * 50401 = "14:00:01"
1339 * ]
1340 * 2023-09-27 = [
1341 * 0 = "00:00:00"
1342 * ]
1343 * 2023-09-28 = [
1344 * 43202 = "12:00:02"
1345 * ]
1346 * ]
1347 * INTO
1348 *
1349 * - Time-Slots A - B '10:00:01 - 12:00:02'
1350 *
1351 * - Check in A - ... '14:00:01 - 24:00:00'
1352 * - Check out ... - B '00:00:00 - 12:00:02'
1353 *
1354 * - Full day ... - ... '00:00:00 - 24:00:00'
1355 *
1356 * - Full IN ..1 - ... '00:00:01 - 24:00:00'
1357 * - Full OUT ... - ..2 '00:00:00 - 24:00:02'
1358 *
1359 */
1360 function wpbc__transform__times_by_dates__in__readable_dates_arr( $times_arr___by_dates ) {
1361
1362
1363 foreach ( $times_arr___by_dates as $only_date_key => $times_arr ) {
1364
1365 /**
1366 * Because it's dates_times from 1 booking, then in each date we have only 1 or 2 times.
1367 */
1368
1369 if ( 1 == count( $times_arr___by_dates[ $only_date_key ] ) ) {
1370
1371 // One Loop only, to get the $time_only_24hours value
1372 foreach ( $times_arr___by_dates[ $only_date_key ] as $time_only_seconds => $time_only_24hours ) {
1373
1374 if ( '00:00:00' == $time_only_24hours ) { // Full Day
1375
1376 $times_arr___by_dates[ $only_date_key ] = array( '00:00:00', '24:00:00' );
1377
1378 } else if( '00:00:01' == $time_only_24hours ) { // Check In ___ full day
1379
1380 $times_arr___by_dates[ $only_date_key ] = array( '00:00:01', '24:00:00' );
1381
1382 } else if( '24:00:02' == $time_only_24hours ) { // Check Out ___ full day
1383
1384 $times_arr___by_dates[ $only_date_key ] = array( '00:00:00', '24:00:02' );
1385 } else {
1386
1387 // Check in / out
1388 $is_check_in_out__or_full = substr( $time_only_24hours, -1 ); // '1', '2' (not '0')
1389
1390 if ( '1' == $is_check_in_out__or_full ) { // Check In
1391
1392 $times_arr___by_dates[ $only_date_key ] = array( $time_only_24hours, '24:00:00' );
1393
1394 } else if ( '2' == $is_check_in_out__or_full ) { // Check Out
1395
1396 $times_arr___by_dates[ $only_date_key ] = array( '00:00:00', $time_only_24hours );
1397
1398 } else { // Unexpected ?
1399 echo "WPBC. Unexpected data value: {$time_only_24hours} Timestamp ended with value different than: 1|2 for the day {$only_date_key} in one booking ";
1400 }
1401
1402 }
1403 }
1404 }
1405
1406
1407 if ( 2 == count( $times_arr___by_dates[ $only_date_key ] ) ) {
1408
1409 // Time slots or already defined check in / out times
1410 $times_his_values = implode( ' - ', $times_arr___by_dates[ $only_date_key ] );
1411
1412 $times_arr___by_dates[ $only_date_key ] = array();
1413 $times_arr___by_dates[ $only_date_key ][] = $times_his_values;
1414
1415 } else {
1416
1417 // Something wrong ???? Check it.
1418 echo "WPBC. Unexpected data value. We have more than 2 time slots for single day {$only_date_key} in one booking ";
1419 debuge( $times_arr___by_dates, __FILE__, __LINE__ );
1420 }
1421 }
1422
1423 return $times_arr___by_dates;
1424 }
1425
1426
1427 // GOOD
1428 /**
1429 * Transform linear [ 1690884011 = "2023-08-01 10:00:01" , ... ] -> [ '2023-08-01' : [ 36011 = "10:00:01", 43192 = "12:00:02", ... ] , '2023-08-05' : [...] ... ]
1430 *
1431 * @param array $datetimestamps_datesql_arr [
1432 * 1690884011 = "2023-08-01 10:00:01"
1433 * 1690891192 = "2023-08-01 12:00:02"
1434 * 1691229611 = "2023-08-05 10:00:01"
1435 * 1691236792 = "2023-08-05 12:00:02"
1436 * ]
1437 *
1438 * @return array [
1439 * 2023-08-01 = [
1440 * 36011 = "10:00:01"
1441 * 43192 = "12:00:02"
1442 * 2023-08-05 = [
1443 * 36011 = "10:00:01"
1444 * 43192 = "12:00:02"
1445 * ]
1446 */
1447 function wpbc__transform__timestamp_arr__in__times_by_dates__arr( $datetimestamps_datesql_arr ) {
1448
1449 ksort( $datetimestamps_datesql_arr );
1450
1451 $by_dates__timestamp_datesql__arr = array();
1452
1453 foreach ( $datetimestamps_datesql_arr as $this_datetime_stamp => $this_date_sql ) {
1454
1455 // '2023-08-01' '10:00:01'
1456 list( $only_day_sql, $only_time_sql ) = explode( ' ', $this_date_sql );
1457
1458 $only_day_sql = trim( $only_day_sql ); // '2023-08-01'
1459 $only_time_sql = trim( $only_time_sql ); // '10:00:01'
1460
1461 if ( ! isset( $by_dates__timestamp_datesql__arr[ $only_day_sql ] ) ) {
1462 $by_dates__timestamp_datesql__arr[ $only_day_sql ] = array(); // [ '2023-08-01': [] ]
1463 }
1464
1465 $only_time_in_sec = wpbc_convert__time_his__to_seconds( $only_time_sql, false ); // 36001, false <- $is_apply__check_in_out__10s
1466
1467 // '2023-08-01' 36001 '10:00:01'
1468 $by_dates__timestamp_datesql__arr[ $only_day_sql ][ $only_time_in_sec ] = $only_time_sql;
1469 }
1470
1471 return $by_dates__timestamp_datesql__arr;
1472 }
1473
1474
1475 // GOOD
1476 /**
1477 * Add to the first and last dates the check in/out times
1478 *
1479 * @param array $sql_dates_arr
1480 *
1481 * @return array $sql_dates_arr
1482 */
1483 function wpbc__add_to__fulldays__check_in_out( $sql_dates_arr ){
1484
1485 // Add check in/out to first and last dates !
1486 $is_apply__check_in_out__10s = false;
1487
1488 // EVEN if we have only 1 day, it has to work! from
1489 $all_timestamps_arr = array_keys( $sql_dates_arr );
1490
1491
1492 // CHECK_IN date, - lowest timestamp: -------------------------------------------------------------------
1493 $check_in_timestamp = min( $all_timestamps_arr );
1494 // Remove this date
1495 if ( isset( $sql_dates_arr[ $check_in_timestamp ] ) ) { unset( $sql_dates_arr[ $check_in_timestamp ] ); }
1496
1497 // Add new date: see definition of WPBC_FULL_DAY_TIME_IN <- 00:00:01
1498 $real__check_in__date_sql = date( 'Y-m-d', $check_in_timestamp ) . ' 00:00:01';
1499 $real__check_in_timestamp_new = wpbc_convert__sql_date__to_seconds( date( 'Y-m-d', $check_in_timestamp ) . ' 00:00:01', $is_apply__check_in_out__10s );
1500 $sql_dates_arr[ $real__check_in_timestamp_new ] = $real__check_in__date_sql;
1501
1502
1503 // CHECK_OUT date, - highest timestamp: ------------------------------------------------------------------
1504 $check_out_timestamp = max( $all_timestamps_arr );
1505 // Remove this date
1506 if ( isset( $sql_dates_arr[ $check_out_timestamp ] ) ) {
1507 unset( $sql_dates_arr[ $check_out_timestamp ] );
1508 }
1509 // Add new date: see definition of WPBC_FULL_DAY_TIME_OUT <- 23:59:52
1510 $real__check_out__date_sql = date( 'Y-m-d', $check_out_timestamp ) . ' 24:00:02';
1511 $real__check_out_timestamp_new = wpbc_convert__sql_date__to_seconds( date( 'Y-m-d', $check_out_timestamp ) . ' 23:59:52', $is_apply__check_in_out__10s );
1512 $sql_dates_arr[ $real__check_out_timestamp_new ] = $real__check_out__date_sql;
1513
1514 // Sort such dates again, because we changed the order ---------------------------------------------------
1515 ksort( $sql_dates_arr );
1516
1517 return $sql_dates_arr;
1518 }
1519
1520
1521 // GOOD
1522 /**
1523 * Check if all dates in array it is full dates e.g. 2023-07-25 00:00:00
1524 * and not the check in/out, such as 2023-07-25 12:00:02
1525 *
1526 * @param array $booking_sqldates_arr [
1527 * 1690884011 = "2023-08-01 10:00:01"
1528 * 1690891192 = "2023-08-01 12:00:02"
1529 * ...
1530 * ]
1531 *
1532 * @return bool
1533 */
1534 function wpbc_is_all__fulldays__in_dates_arr( $booking_sqldates_arr ) {
1535
1536 $is_all_dates_full = true;
1537
1538 foreach ( $booking_sqldates_arr as $date_sql ) {
1539
1540 $is_check_in_out__or_full = (string) $date_sql;
1541 $is_check_in_out__or_full = substr( $is_check_in_out__or_full, - 1 ); // '0', '1', '2' from "2023-08-01 12:00:02"
1542 if ( '0' !== $is_check_in_out__or_full ) {
1543 $is_all_dates_full = false;
1544 break;
1545 }
1546 }
1547
1548 return $is_all_dates_full;
1549 }
1550
1551 // =====================================================================================================================
1552
1553
1554 /**
1555 * Convert [ "2023-10-20", "2023-10-25", "2023-11-23" ] -> [ '20.10.2023', '25.10.2023', '23.11.2023' ]
1556 *
1557 * @param $dates_arr__yyyy_mm_dd [ "2023-10-20", "2023-10-25", "2023-11-23" ]
1558 *
1559 * @return [] [ '20.10.2023', '25.10.2023', '23.11.2023' ]
1560 */
1561 function wpbc_convert_dates_arr__yyyy_mm_dd__to__dd_mm_yyyy( $dates_arr__yyyy_mm_dd ) {
1562
1563 $dates_arr__dd_mm_yyyy = array_map( function ( $value ) {
1564 $value_arr = explode( '-', $value );
1565 return ( count( $value_arr ) > 2 )
1566 ? $value_arr[2] . '.' . $value_arr[1] . '.' . $value_arr[0]
1567 : '';
1568 }
1569 , $dates_arr__yyyy_mm_dd ); // [ "2023-10-20", "2023-10-25", "2023-11-23" ]
1570
1571 $dates_arr__dd_mm_yyyy = array_filter( $dates_arr__dd_mm_yyyy ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1572 return $dates_arr__dd_mm_yyyy;
1573 }
1574
1575
1576 /**
1577 * Convert '20.10.2023, 25.10.2023, 23.10.2023' -> '2023-10-20,2023-10-23,2023-10-25'
1578 *
1579 * or even: '20.10.2023 - 23.10.2023' -> '2023-10-20,2023-10-21,2023-10-22,2023-10-23'
1580 *
1581 * @param $str_dates__dd_mm_yyyy '20.10.2023, 25.10.2023, 23.10.2023'
1582 *
1583 * @return string '2023-10-20,2023-10-23,2023-10-25'
1584 */
1585 function wpbc_convert_dates_str__dd_mm_yyyy__to__yyyy_mm_dd( $str_dates__dd_mm_yyyy ) {
1586
1587 $str_dates__dd_mm_yyyy = str_replace( '|', ',', $str_dates__dd_mm_yyyy ); // Check this for some old versions of plugin
1588
1589 if ( strpos( $str_dates__dd_mm_yyyy, ' - ' ) !== false ) { // Recheck for any type of Range Days Formats
1590 $arr_check_in_out_dates = explode( ' - ', $str_dates__dd_mm_yyyy );
1591 $str_dates__dd_mm_yyyy = wpbc_get_comma_seprated_dates_from_to_day( $arr_check_in_out_dates[0], $arr_check_in_out_dates[1] );
1592 }
1593
1594 $dates_arr__dd_mm_yyyy = explode( ',', $str_dates__dd_mm_yyyy ); // Create dates Array
1595
1596 $dates_arr__yyyy_mm_dd = array_map( function ( $value ) {
1597 $value = trim( $value );
1598 $value_arr = explode( '.', $value );
1599 return ( count( $value_arr ) > 2 )
1600 ? $value_arr[2] . '-' . $value_arr[1] . '-' . $value_arr[0]
1601 : '';
1602 }
1603 , $dates_arr__dd_mm_yyyy ); // [ '20.10.2023', '25.10.2023', '23.11.2023' ]
1604 $dates_arr__yyyy_mm_dd = array_filter( $dates_arr__yyyy_mm_dd ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1605 // Remove duplicates
1606 $dates_arr__yyyy_mm_dd = array_unique( $dates_arr__yyyy_mm_dd );
1607
1608 // Sort Dates
1609 sort( $dates_arr__yyyy_mm_dd );
1610
1611 $dates_str__yyyy_mm_dd = implode( ',', $dates_arr__yyyy_mm_dd );
1612
1613 return $dates_str__yyyy_mm_dd; // '2023-10-20,2023-10-23,2023-10-25'
1614 }
1615
1616