PluginProbe
Booking Calendar / 11.8
Booking Calendar v11.8
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 10.11.3 10.11.4 All 201 releases
booking / core / wpbc-dates.php

wpbc-dates.php in Booking Calendar 11.8, at core/wpbc-dates.php

1,086 lines 38.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version 1.0
4 * @package Booking Calendar
5 * @subpackage Dates Functions
6 * @category Functions
7 *
8 * @author wpdevelop
9 * @link https://wpbookingcalendar.com/
10 * @email info@wpbookingcalendar.com
11 *
12 * @modified 29.09.2015
13 */
14
15 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
16
17
18 /**
19 * Get the dates in different formats
20 *
21 * @param type $str_dates__dd_mm_yyyy
22 * @param type $booking_type
23 * @param type $booking_form_data
24 * @return
25 array(
26 'string' => "30.02.2014, 31.02.2014, 01.03.2014"
27 , 'array' => array("2014-02-30", "2014-02-31", ....
28 , 'start_time' => array('00','00','00');
29 , 'end_time' => array('00','00','00');
30 );
31 */
32 function wpbc_get_dates_in_diff_formats( $str_dates__dd_mm_yyyy, $booking_type, $booking_form_data ){
33
34 $str_dates__dd_mm_yyyy = str_replace( '|', ',', $str_dates__dd_mm_yyyy); // Check this for some old versions of plugin
35
36 if ( strpos($str_dates__dd_mm_yyyy,' - ') !== false ) { // Recheck for any type of Range Days Formats
37 $arr_check_in_out_dates = explode(' - ', $str_dates__dd_mm_yyyy );
38 $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] );
39 }
40
41
42 $days_array = explode( ',', $str_dates__dd_mm_yyyy ); // Create dates Array
43 $only_days = array();
44
45 foreach ($days_array as $new_day) {
46
47 if ( ! empty($new_day) ) {
48
49 $new_day = trim( $new_day );
50
51 $new_day = str_replace( '-', '.', $new_day);
52
53 $new_day = explode( '.', $new_day);
54
55 $only_days[] = sprintf( "%04d-%02d-%02d", intval( $new_day[2] ), intval( $new_day[1] ), intval( $new_day[0] ) );
56 }
57 }
58 sort($only_days); // Sort Dates
59
60
61 // Get Times from booking form if these fields exist
62 $start_end_time = wpbc_get_times_in_form( $booking_form_data, $booking_type );
63
64 if ( $start_end_time !== false ) {
65 $start_time = $start_end_time[0]; // array('00','00','01');
66 $end_time = $start_end_time[1]; // array('00','00','01');
67
68 if ( ( '00' == $start_time[0] ) && ( '00' == $start_time[1] ) ) { // FixIn: 8.7.8.8.
69 $start_time = array( '00', '00', '00' );
70 $end_time = array( '00', '00', '00' );
71 } else {
72 if ( count( $only_days ) == 1 ) { // add end date if selected 1 day only and times is exist
73 $only_days[] = $only_days[0];
74 }
75 }
76 } else {
77 $start_time = array( '00', '00', '00' );
78 $end_time = array( '00', '00', '00' );
79 }
80
81
82 return array(
83 'string' => $str_dates__dd_mm_yyyy // dd_mm_yyyy
84 , 'array' => $only_days
85 , 'start_time' => $start_time
86 , 'end_time' => $end_time
87 );
88 }
89
90
91 /**
92 * Check for minimum and maximum available times, and restrict value to these limits.
93 *
94 * @param string $time 24:00
95 * @param string $min_time 00:01
96 * @param string $max_time 23:59
97 *
98 * @return string 23:59
99 */
100 function wpbc_check_min_max_available_times( $time = '00:00', $min_time = '00:00', $max_time = '23:59' ) {
101
102 // Time in minutes
103 $time_m = explode( ':', trim( $time ) );
104 $time_m = intval( $time_m[0] ) * 60 + intval( $time_m[1] );
105
106 // Min time in minutes
107 $min_time_m = explode( ':', trim( $min_time ) );
108 $min_time_m = intval( $min_time_m[0] ) * 60 + intval( $min_time_m[1] );
109
110 // Max time in minutes
111 $max_time_m = explode( ':', trim( $max_time ) );
112 $max_time_m = intval( $max_time_m[0] ) * 60 + intval( $max_time_m[1] );
113
114
115 if ( $time_m < $min_time_m ) {
116 $time_m = $min_time_m;
117 }
118
119 if ( $time_m > $max_time_m ) {
120 $time_m = $max_time_m;
121 }
122
123 // Convert time in minutes back to string HH:MM
124 $time_m_h = floor( $time_m / 60 );
125 $time_m_m = $time_m - $time_m_h * 60;
126
127 // Check leading 0
128 if ( $time_m_h < 10 ) {
129 $time_m_h = '0' . $time_m_h;
130 }
131 if ( $time_m_m < 10 ) {
132 $time_m_m = '0' . $time_m_m;
133 }
134
135 return $time_m_h . ':' . $time_m_m;
136 }
137
138
139 /**
140 * Parse a duration field value into numeric hours and minutes.
141 *
142 * Duration values come from serialized front-end form data. Placeholder or
143 * otherwise malformed values must not reach arithmetic because PHP 8 throws
144 * a TypeError when a non-numeric string is multiplied by an integer.
145 *
146 * @param string $duration_time_value Duration in `HH:MM` format.
147 *
148 * @return array|false Numeric hours and minutes, or false for an invalid duration.
149 */
150 function wpbc_parse_duration_time_value( $duration_time_value ) {
151
152 $duration_time_value = trim( (string) $duration_time_value );
153
154 if ( ! preg_match( '/^([0-9]+):([0-9]{1,2})$/', $duration_time_value, $duration_time_matches ) ) {
155 return false;
156 }
157
158 $duration_hours = intval( $duration_time_matches[1] );
159 $duration_minutes = intval( $duration_time_matches[2] );
160
161 if ( 59 < $duration_minutes ) {
162 return false;
163 }
164
165 return array( $duration_hours, $duration_minutes );
166 }
167
168
169 /**
170 * Get Times from booking Form, if these times fields exist
171 *
172 * @param type $booking_form_data
173 * @param type $booking_type
174 * @return mixed
175 array ( array('00','00','01'), array('00','00','01') )
176 ||
177 false
178 */
179 function wpbc_get_times_in_form( $booking_form_data, $booking_type ){
180
181 $is_time_exist = false;
182
183 $start_time = $end_time = '00:00:00';
184
185 if ( strpos( $booking_form_data, 'rangetime' . $booking_type ) !== false ) {
186
187 // ~checkbox^mymultiple4^~checkbox^rangetime4^ ~checkbox^rangetime4^12:00 - 13:00~ checkbox^rangetime4^~checkbox^rangetime4^~text^name4^Jonny~
188
189 // Types of the conditions
190 $f_type = '[^\^]*';
191 $f_name = 'rangetime[\d]*[\[\]]{0,2}';
192 $f_value = '[\s]*([0-9:]*)[\s]*\-[\s]*([0-9:]*)[\s]*[^~]*';
193
194 $pattern_to_search='%[~]?'.$f_type.'\^'.$f_name.'\^'.$f_value.'[~]?%';
195
196 preg_match_all($pattern_to_search, $booking_form_data, $matches, PREG_SET_ORDER);
197
198 /**
199 * Example of $matches: [ [ [0] => '~checkbox^rangetime4^13:00 - 14:00~'
200 [1] => '13:00'
201 [2] => '14:00'
202 ] ]
203 */
204
205 if (count($matches)>0){
206
207 $start_time = wpbc_get_time_in_24_hours_format( trim( $matches[0][1] ) );
208 $start_time[2] = '01';
209
210 $end_time = wpbc_get_time_in_24_hours_format( trim( $matches[0][2] ) );
211 $end_time[2] = '02';
212
213 $is_time_exist = true;
214
215 } else {
216 $start_time = array('00','00','01');
217 $end_time = array('00','00','02');
218 }
219
220 } else {
221
222 if ( strpos( $booking_form_data, 'starttime' . $booking_type ) !== false ) { // Get START TIME From form request
223 $pos1 = strpos( $booking_form_data, 'starttime' . $booking_type ); // Find start time pos
224 $pos1 = strpos( $booking_form_data, '^', $pos1 ) + 1; // Find TIME pos
225 $pos2 = strpos( $booking_form_data, '~', $pos1 ); // Find TIME length
226 if ( $pos2 === false ) {
227 $pos2 = strlen( $booking_form_data );
228 }
229 $pos2 = $pos2 - $pos1;
230 $start_time = substr( $booking_form_data, $pos1, $pos2 );
231 if ( $start_time == '' ) {
232 $start_time = '00:00';
233 }
234
235 $start_time = wpbc_check_min_max_available_times( $start_time, '00:01', '23:59' ); // FixIn: 8.7.11.1.
236
237 $start_time = explode( ':', $start_time );
238
239 $start_time[2] = '01';
240 } else {
241 $start_time = explode( ':', $start_time );
242 }
243
244 if ( strpos( $booking_form_data, 'endtime' . $booking_type ) !== false ) { // Get END TIME From form request
245 $pos1 = strpos( $booking_form_data, 'endtime' . $booking_type ); // Find start time pos
246 $pos1 = strpos( $booking_form_data, '^', $pos1 ) + 1; // Find TIME pos
247 $pos2 = strpos( $booking_form_data, '~', $pos1 ); // Find TIME length
248 if ( $pos2 === false ) {
249 $pos2 = strlen( $booking_form_data );
250 }
251 $pos2 = $pos2 - $pos1;
252 $end_time = substr( $booking_form_data, $pos1, $pos2 );
253 if ( $end_time == '' ) {
254 $end_time = '00:00';
255 }
256
257 $end_time = wpbc_check_min_max_available_times( $end_time, '00:01', '23:59' ); // FixIn: 8.7.11.1.
258
259 $is_time_exist = true;
260
261 $end_time = explode( ':', $end_time );
262 $end_time[2] = '02';
263 } else {
264 $end_time = explode( ':', $end_time );
265 }
266
267 if ( strpos( $booking_form_data, 'durationtime' . $booking_type ) !== false ) { // Get END TIME From form request
268 $pos1 = strpos( $booking_form_data, 'durationtime' . $booking_type ); // Find start time pos
269 $pos1 = strpos( $booking_form_data, '^', $pos1 ) + 1; // Find TIME pos
270 $pos2 = strpos( $booking_form_data, '~', $pos1 ); // Find TIME length
271 if ( $pos2 === false ) {
272 $pos2 = strlen( $booking_form_data );
273 }
274 $pos2 = $pos2 - $pos1;
275 $duration_time_value = substr( $booking_form_data, $pos1, $pos2 );
276 $duration_time_parts = wpbc_parse_duration_time_value( $duration_time_value );
277
278 if ( false !== $duration_time_parts ) {
279 $is_time_exist = true;
280
281 // Get the selected start time and add the validated duration to calculate the end time.
282 $new_end_time = mktime( intval( $start_time[0] ), intval( $start_time[1] ) );
283 $new_end_time += $duration_time_parts[0] * 60 * 60;
284 $new_end_time += $duration_time_parts[1] * 60;
285 $end_time = gmdate( 'H:i', $new_end_time );
286
287 if ( '00:00' === $end_time ) {
288 $end_time = '23:59';
289 }
290 $end_time = explode( ':', $end_time );
291 $end_time[2] = '02';
292 }
293 }
294
295 }
296
297 if ( $is_time_exist ) {
298 return array( $start_time, $end_time );
299 } else {
300 return false;
301 }
302 }
303
304
305 //FixIn: TimeFreeGenerator
306 /**
307 * Convert timeslot "10:00 - 12:00" to specfic timeformat, like "10:00 AM - 12:00 PM"
308 * @param string $timeslot - "10:00 - 12:00"
309 * @param string $time_format = "g:i A"
310 */
311 function wpbc_time_slot_in_format( $timeslot, $time_format = false ){
312
313 // FixIn: 8.9.3.1.
314 if ( ( empty( $timeslot ) ) ) {
315 return '';
316 }
317 $value_times = explode( '-', $timeslot );
318 $value_times[0] = trim( $value_times[0] );
319 $value_times[1] = trim( $value_times[1] );
320
321 $s_tm = wpbc_time_localized( $value_times[0] , $time_format);
322 $e_tm = wpbc_time_localized( $value_times[1] , $time_format);
323
324 $t_delimeter = ' - ';
325
326 return $s_tm . $t_delimeter . $e_tm ;
327 }
328
329
330 //FixIn: 8.4.2.11 Deprecated, use this: wpbc_time_localized
331 /**
332 * Convert timeslot "10:00" to specfic timeformat, like "10:00 AM"
333 * @param string $timeslot - "10:00"
334 * @param string $time_format = "g:i A"
335 */
336 function wpbc_time_in_format( $timeslot, $time_format = false ){
337
338 $s_tm = wpbc_time_localized( $timeslot, $time_format );
339 return $s_tm;
340 }
341
342
343 /**
344 * Get dates from DB of specific booking -> '2023-10-09 12:00:01, 2023-10-09 20:00:02'
345 *
346 * @global type $wpdb
347 * @param type $booking_id_str - booking ID
348 * @return string - comma separated dates in SQL format -> '2023-10-09 12:00:01, 2023-10-09 20:00:02'
349 */
350 function wpbc_db__get_sql_dates__in_booking__as_str( $booking_id_str ) {
351
352 global $wpdb;
353
354 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
355 $dates_result = $wpdb->get_results( "SELECT DISTINCT booking_date FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_id_str}) ORDER BY booking_date" );
356
357 $dates_str = array();
358
359 foreach ( $dates_result as $my_date ) {
360
361 $dates_str[] = $my_date->booking_date;
362 }
363 $dates_str = implode( ', ', $dates_str );
364
365
366 return $dates_str;
367 }
368
369
370 /**
371 * Get Only Dates array from Dates Dimes string with comma seperated values
372 *
373 * @param $dates_ymd_his_csv -> '2023-10-09 12:00:01, 2023-10-09 20:00:02'
374 *
375 * @return array|string[] -> '2023-10-09, 2023-10-09'
376 *
377 *
378 * Usually it called like in this Example:
379 * $dates_ymd_his_csv = wpbc_db__get_sql_dates__in_booking__as_str( $booking_id_str ); // '100' | '10,7' - booking ID
380 * $dates_only_arr = wpbc_get_only_dates__from_dates_ymd_his_csv__as_arr( $dates_ymd_his_csv ); // -> '2023-10-09, 2023-10-09'
381 */
382 function wpbc_get_only_dates__from_dates_ymd_his_csv__as_arr( $dates_ymd_his_csv ){
383
384
385 // FixIn: 10.1.5.6.
386 $dates_only_arr = wpbc_get_dates_arr__from_dates_comma_separated( array(
387 'dates_separator' => ', ', // ', '
388 'dates' => $dates_ymd_his_csv, // '2023-04-04 12:03:00, 2023-04-07 2024-06-30:00'
389 ) );
390 // Get Only Dates
391 $dates_only_arr = array_map( function ( $date_sql_ymd_his ) {
392 $date_sql_ymd_his = trim( $date_sql_ymd_his );
393 $date_sql_ymd_his = substr( $date_sql_ymd_his, 0, 10 );
394 return $date_sql_ymd_his;
395 }
396 , $dates_only_arr
397 );
398 $dates_only_arr = array_unique( $dates_only_arr );
399 return $dates_only_arr;
400 }
401
402 /**
403 * Get Time in 24 hours (military) format, from possible AM/PM format
404 *
405 * @param string $time_str - '01:20 PM'
406 * @return string - '13:20'
407 */
408 function wpbc_get_time_in_24_hours_format( $time_str ) {
409
410 $time_str = trim( $time_str );
411 $time_str_plus = 0;
412
413 if ( strpos( strtolower( $time_str) ,'am' ) !== false ) {
414 $time_str = str_replace('am', '', $time_str );
415 $time_str = str_replace('AM', '', $time_str );
416 }
417
418 if ( strpos( strtolower( $time_str) ,'pm' ) !== false ) {
419 $time_str = str_replace('pm', '', $time_str );
420 $time_str = str_replace('PM', '', $time_str );
421 $time_str_plus = 12;
422 }
423
424 $time_str = explode( ':', trim( $time_str ) );
425 // FixIn: 9.9.0.4.
426 $time_str[0] = intval( $time_str[0] ) + $time_str_plus;
427 $time_str[1] = intval( $time_str[1] );
428
429 if ($time_str[0] < 10 ) $time_str[0] = '0' . $time_str[0];
430 if ($time_str[1] < 10 ) $time_str[1] = '0' . $time_str[1];
431
432 return $time_str;
433 }
434
435
436 /**
437 * Get number of days between 2 dates (dates in mySQL format)
438 *
439 * @param string $day1 - Day in MySQL format
440 * @param string $day2 - Day in MySQL format
441 *
442 * @return int - number of days
443 */
444 function wpbc_get_difference_in_days( $day1, $day2 ) {
445 return floor( ( strtotime( $day1 ) - strtotime( $day2 ) ) / 86400 ); // FixIn: 8.2.1.11.
446 }
447
448
449 /**
450 * Get sorted sql dates array, like: [ '2023-10-18 00:00:00', '2023-10-19 00:00:00', '2023-10-20 00:00:00' ]
451 *
452 * @param string $booking_days '19.10.2023,18.10.2023,20.10.2023' - comma separated dates:
453 * @return array - [ '2023-10-18 00:00:00', '2023-10-19 00:00:00', '2023-10-20 00:00:00' ] - sorted dates array
454 */
455 function wpbc_get_sorted_days_array( $booking_days ) {
456
457 if ( strpos($booking_days,' - ') !== false ) {
458 $booking_days = explode(' - ', $booking_days );
459 $booking_days = wpbc_get_comma_seprated_dates_from_to_day($booking_days[0],$booking_days[1]);
460 }
461
462 $days_array = explode(',', $booking_days);
463 $only_days = array();
464
465 foreach ($days_array as $new_day) {
466 if ( ! empty( $new_day ) ) {
467 $new_day = trim( $new_day );
468 if ( strpos( $new_day, '.' ) !== false ) $new_day = explode('.',$new_day);
469 else $new_day = explode('-',$new_day);
470 $only_days[] = $new_day[2] .'-' . $new_day[1] .'-' . $new_day[0] . ' 00:00:00';
471 }
472 }
473
474 if ( ! empty( $only_days ) ) {
475 sort($only_days);
476 }
477
478 return $only_days;
479 }
480
481
482 /**
483 * Get Dates in Comma seperated format, based on start and end dates.
484 *
485 * @param string $date_str_from - start date: 06.04.2015
486 * @param string $date_str_to - end date: 08.04.2015
487 * @return string - comma seperated dates: 06.04.2015, 07.04.2015, 08.04.2015
488 */
489 function wpbc_get_comma_seprated_dates_from_to_day( $date_str_from, $date_str_to ) {
490
491 $date_str_from = explode('.', $date_str_from);
492 $date_str_to = explode('.', $date_str_to);
493 $iDateFrom = mktime( 1, 0, 0, ( intval( $date_str_from[1] ) ), ( intval( $date_str_from[0] ) ), ( intval( $date_str_from[2] ) ) );
494 $iDateTo = mktime( 1, 0, 0, ( intval( $date_str_to[1] ) ), ( intval( $date_str_to[0] ) ), ( intval( $date_str_to[2] ) ) );
495
496 $aryRange=array();
497
498 if ( $iDateTo >= $iDateFrom ) {
499 array_push( $aryRange, gmdate( 'd.m.Y', $iDateFrom ) ); // first entry
500
501 while ($iDateFrom<$iDateTo) {
502 $iDateFrom+=86400; // add 24 hours
503 array_push( $aryRange, gmdate( 'd.m.Y', $iDateFrom ) );
504 }
505 }
506
507 $aryRange = implode(', ', $aryRange);
508
509 return $aryRange;
510 }
511
512
513 /**
514 * Get dates array based on start and end dates.
515 *
516 * @param string $sStartDate - start date: 2015-04-06
517 * @param string $sEndDate - end date: 2015-04-08
518 * @return array - array( 2015-04-06, 2015-04-07, 2015-04-08 )
519 */
520 function wpbc_get_dates_array_from_start_end_days( $sStartDate, $sEndDate ){
521 // Firstly, format the provided dates.
522 // This function works best with YYYY-MM-DD
523 // but other date formats will work thanks
524 // to strtotime().
525 $sStartDate = gmdate("Y-m-d", strtotime($sStartDate));
526 $sEndDate = gmdate("Y-m-d", strtotime($sEndDate));
527
528 // Start the variable off with the start date
529 $aDays[] = $sStartDate;
530
531 // Set a 'temp' variable, sCurrentDate, with
532 // the start date - before beginning the loop
533 $sCurrentDate = $sStartDate;
534
535 // While the current date is less than the end date
536 while($sCurrentDate < $sEndDate){
537 // Add a day to the current date
538 $sCurrentDate = gmdate("Y-m-d", strtotime("+1 day", strtotime($sCurrentDate)));
539
540 // Add this new day to the aDays array
541 $aDays[] = $sCurrentDate;
542 }
543 // Once the loop has finished, return the
544 // array of days.
545 return $aDays;
546 }
547
548
549 /**
550 * Get dates array, from range days selection
551 *
552 * @param $params = array(
553 * 'dates_separator' => ' ~ ', // Dates separator
554 * 'dates' => '2023-04-04 ~ 2023-04-07' // Dates in 'Y-m-d' format: '2023-01-31'
555 * )
556 *
557 * @return array = array(
558 * [0] => 2023-04-04
559 * [1] => 2023-04-05
560 * [2] => 2023-04-06
561 * [3] => 2023-04-07
562 * )
563 *
564 * Example #1: wpbc_get_dates_arr__from_dates_range( array( 'dates_separator' => ' ~ ', 'dates' => '2023-04-04 ~ 2023-04-07' ) );
565 * Example #2: wpbc_get_dates_arr__from_dates_range( array( 'dates_separator' => ' - ', 'dates' => '2023-04-04 - 2023-04-07' ) );
566 */
567 function wpbc_get_dates_arr__from_dates_range( $params ){
568
569 $defaults = array(
570 'dates_separator' => ' ~ ', // ' ~ '
571 'dates' => '', // '2023-04-04 ~ 2023-04-07'
572 );
573 $params = wp_parse_args( $params, $defaults );
574
575 $dates_arr = array();
576
577 if ( ! empty( $params['dates'] ) ) {
578
579 list( $check_in_date_ymd, $check_out_date_ymd ) = explode( $params['dates_separator'], $params['dates'] );
580
581 if ( ( ! empty( $check_in_date_ymd ) ) && ( ! empty( $check_out_date_ymd ) ) ) {
582
583 $dates_arr = wpbc_get_dates_array_from_start_end_days( $check_in_date_ymd, $check_out_date_ymd );
584 }
585 }
586 return $dates_arr;
587 }
588
589 /**
590 * Get dates array, from comma separated dates
591 *
592 * @param $params = array(
593 * 'dates_separator' => ', ', // Dates separator
594 * 'dates' => '2023-04-04, 2023-04-07, 2023-04-05' // Dates in 'Y-m-d' format: '2023-01-31'
595 * )
596 *
597 * @return array = array(
598 * [0] => 2023-04-04
599 * [1] => 2023-04-05
600 * [2] => 2023-04-06
601 * [3] => 2023-04-07
602 * )
603 *
604 * Example #1: wpbc_get_dates_arr__from_dates_comma_separated( array( 'dates_separator' => ', ', 'dates' => '2023-04-04, 2023-04-07, 2023-04-05' ) );
605 */
606 function wpbc_get_dates_arr__from_dates_comma_separated( $params ){
607
608 $defaults = array(
609 'dates_separator' => ', ', // ' ~ '
610 'dates' => '', // ''2023-04-04, 2023-04-07, 2023-04-05'
611 );
612 $params = wp_parse_args( $params, $defaults );
613
614 $dates_arr = array();
615
616 if ( ! empty( $params['dates'] ) ) {
617
618 $dates_arr = explode( $params['dates_separator'], $params['dates'] );
619
620 sort( $dates_arr );
621 }
622 return $dates_arr;
623 }
624
625
626 /**
627 * Get tommorow day from input value
628 *
629 * @param string $nowday : 2015-02-29
630 * @return int : Unix timestamp for a date like this 2015-02-30
631 */
632 function wpbc_get_tommorow_day( $nowday ){
633
634 $nowday_d = gmdate( 'm.d.Y', mysql2date( 'U', $nowday ) );
635 $previos_array = explode( '.', $nowday_d );
636 $tommorow_day = mktime( 0, 0, 0, intval($previos_array[0]), ( intval($previos_array[1]) + 1 ), intval($previos_array[2]) ) ;
637 return $tommorow_day;
638 }
639
640
641 /**
642 * Check if this date is today day
643 *
644 * @param string $some_day : '2015-05-29'
645 * @return boolean : true | false
646 */
647 function wpbc_is_today_date( $some_day ) {
648
649 $some_day_d = gmdate( 'm.d.Y', mysql2date( 'U', $some_day ) );
650 $today_day = gmdate( 'm.d.Y' );
651
652 if ( $today_day == $some_day_d ) {
653 return true;
654 } else {
655 return false;
656 }
657 }
658
659
660 /**
661 * Check if this date is Tomorrow day
662 *
663 * @param string $some_day : '2024-08-18'
664 * @return boolean : true | false
665 */
666 function wpbc_is_tomorrow_date( $some_day ) {
667
668 $some_day_d = gmdate( 'Y-m-d 00:00:00', mysql2date( 'U', $some_day ) );
669 $today_day = gmdate( 'Y-m-d 00:00:00' );
670 $tomorrow_day = gmdate( 'Y-m-d 00:00:00', strtotime( '+1 day', strtotime( $today_day ) ) );
671
672 if ( $tomorrow_day == $some_day_d ) {
673 return true;
674 } else {
675 return false;
676 }
677 }
678
679
680 // FixIn: 8.8.1.2.
681 /**
682 * Check if this date in past
683 *
684 * @param string $some_day : '2015-05-29'
685 * @return boolean : true | false
686 */
687 function wpbc_is_date_in_past( $some_day ) {
688
689 $some_day_d = gmdate( 'm.d.Y', mysql2date( 'U', $some_day ) );
690 $some_array = explode( '.', $some_day_d );
691 $some_day = mktime( 0, 0, 0, intval($some_array[0]), ( intval($some_array[1]) + 1 ), intval($some_array[2]) );
692
693 $today_day = time();
694
695 if ( $today_day > $some_day ) {
696 return true;
697 } else {
698 return false;
699 }
700 }
701
702
703 /**
704 * Check whether a booking can still be changed by a visitor.
705 *
706 * Visitor edit and cancellation actions must fail closed when the booking does
707 * not exist, is in the trash, has no dates, or its final booked date has
708 * already passed. The comparison deliberately uses wpbc_is_date_in_past() so
709 * the rule remains compatible with the established date-based front-end edit
710 * restriction and does not unexpectedly expire time-slot bookings mid-day.
711 *
712 * @param int $booking_id Booking ID resolved from a verified visitor hash.
713 *
714 * @return bool True when at least one booked date is current or future.
715 */
716 function wpbc_is_visitor_booking_action_allowed( $booking_id ) {
717 global $wpdb;
718
719 $booking_id = absint( $booking_id );
720 if ( empty( $booking_id ) ) {
721 return false;
722 }
723
724 $last_booking_date = $wpdb->get_var(
725 $wpdb->prepare(
726 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
727 "SELECT MAX(dt.booking_date)
728 FROM {$wpdb->prefix}bookingdates AS dt
729 INNER JOIN {$wpdb->prefix}booking AS bk ON bk.booking_id = dt.booking_id
730 WHERE bk.booking_id = %d AND bk.trash = 0",
731 $booking_id
732 )
733 ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
734
735 if ( empty( $last_booking_date ) || ! is_string( $last_booking_date ) ) {
736 return false;
737 }
738
739 return ! wpbc_is_date_in_past( $last_booking_date );
740 }
741
742
743 /**
744 * Check if the booking was made without calendar ( no booking date submited.)
745 *
746 * @param $is_no_date
747 * @param $date
748 *
749 * @return mixed|true
750 */
751 function wpbc_maybe_no_booking_date( $is_no_date, $date_ymd ) {
752
753 if ( ( ! empty( $date_ymd ) ) && ( is_array( $date_ymd ) ) ) {
754 $date_ymd = $date_ymd[0];
755 }
756 // FixIn: 2981-01-13 13 Jan 2981.
757 if ( '2981-01-13' === gmdate( 'Y-m-d', mysql2date( 'U', $date_ymd ) ) ) {
758 $is_no_date = true;
759 }
760
761 return $is_no_date;
762 }
763 add_filter( 'wpbc_maybe_no_booking_date', 'wpbc_maybe_no_booking_date', 10, 2 );
764
765
766 //TODO: refactor it, by replacig date_i18n to wp_loc_date... (check depndencies of this function in other usage functions...)
767 /**
768 * Change date / time format
769 *
770 * @param string $dt - MySQL Date - '2015-11-21 00:00:00'
771 * @param type $date_format - Optional. Date format
772 * @param type $time_format - Optional. Time format
773 * @return array( 'DATE in custom Format', 'TIME in custom Format' )
774 */
775 function wpbc_get_date_in_correct_format( $dt, $date_format = false, $time_format = false ) {
776
777 $is_no_date = apply_filters( 'wpbc_maybe_no_booking_date', false, $dt );
778 if ( $is_no_date ) {
779 return array( '---', '' );
780 }
781
782 if ( $date_format === false ) $date_format = get_bk_option( 'booking_date_format');
783 if ( empty( $date_format ) ) $date_format = "m / d / Y, D";
784
785 if ( $time_format === false ) $time_format = get_bk_option( 'booking_time_format');
786 if ( empty( $time_format ) ) $time_format = get_option( 'time_format' ); //'h:i a'; //FixIn: TimeFree 2 - in Booking Calendar Free version show by default times hints in AM/PM format
787
788 $my_time = gmdate( 'H:i:s' , mysql2date( 'U', $dt ) );
789 if ( $my_time == '00:00:00' ) $time_format = '';
790
791 $bk_date = date_i18n( $date_format, mysql2date( 'U', $dt ) );
792 $bk_time = date_i18n( ' ' . $time_format , mysql2date( 'U', $dt ) );
793
794 if ( $bk_time == ' ' ) $bk_time = '';
795
796 return array($bk_date, $bk_time);
797 }
798
799
800 /**
801 * Get SHORT Dates showing data
802 *
803 * @param array $bk_dates_short - Array of dates
804 * @param bool $is_approved - is dates approved or not
805 * @param type $bk_dates_short_id
806 * @param type $booking_types
807 * @return string
808 */
809 function wpbc_get_short_dates_formated_to_show( $bk_dates_short, $is_approved = false, $bk_dates_short_id = array() , $booking_types = array() ){
810
811 $short_dates_content = '';
812 $dcnt = 0;
813 foreach ( $bk_dates_short as $dt ) {
814 if ( $dt == '-' ) {
815 $short_dates_content .= '<span class="date_tire"> - </span>';
816 } elseif ( $dt == ',' ) {
817 $short_dates_content .= '<span class="date_tire">, </span>';
818 } else {
819 $short_dates_content .= '<a href="javascript:void(0)" class="field-booking-date label flex-label ';
820 if ( $is_approved )
821 $short_dates_content .= ' approved';
822 $short_dates_content .= '">';
823
824 $bk_date = wpbc_get_date_in_correct_format( $dt );
825 $short_dates_content .= $bk_date[0];
826 $short_dates_content .= '<sup class="field-booking-time">' . $bk_date[1] . '</sup>';
827
828 if ( class_exists( 'wpdev_bk_biz_l' ) ) { // BL
829 if ( ( !empty( $bk_dates_short_id[$dcnt] ) ) && ( isset( $booking_types[$bk_dates_short_id[$dcnt]] ) ) ){
830 $bk_booking_type_name_date = $booking_types[$bk_dates_short_id[$dcnt]]->title; // Default
831
832 if ( strlen( $bk_booking_type_name_date ) > 19 )
833 $bk_booking_type_name_date = substr( $bk_booking_type_name_date, 0, 13 )
834 . '...'
835 . substr( $bk_booking_type_name_date, -3 );
836
837 $short_dates_content .= '<sup class="field-booking-time date_from_dif_type"> ' . $bk_booking_type_name_date . '</sup>';
838 }
839 }
840 $short_dates_content .= '</a>';
841 }
842 $dcnt++;
843 }
844 return $short_dates_content;
845 }
846
847 // FixIn: 9.6.3.5.
848
849 /**
850 * Get booking dates from DB for specific calendar
851 *
852 * @param array $params array(
853 'approved' => '' // '' - all | '0' - pending | '1' - approved
854 , 'resource_id' => 1 // int or dcv
855 , 'skip_booking_id' => '' // int or dcv
856
857 )
858 *
859 * @return array array( [1-7-2023] => array(
860 [sec_0] => stdClass Object
861 (
862 [booking_date] => 2023-01-07 00:00:00
863 [approved] => 0
864 [booking_id] => 96
865 )
866
867 )
868 [1-8-2023] => Array(
869 [sec_0] => stdClass Object
870 (
871 [booking_date] => 2023-01-08 00:00:00
872 [approved] => 0
873 [booking_id] => 42
874 )
875 )
876 ...
877
878 */
879 function wpbc__sql__get_booked_dates( $params ){
880
881 $defaults = array(
882 'approved' => '' // '' - all | '0' - pending | '1' - approved
883 , 'resource_id' => 1 // int or dcv
884 , 'skip_booking_id' => '' // int or dcv
885 );
886 $params = wp_parse_args( $params, $defaults );
887
888 // S a n i t i z e
889 $params['approved'] = ( '' != $params['approved'] ) ? intval( $params['approved'] ) : '';
890 $params['skip_booking_id'] = ( '' != $params['skip_booking_id'] ) ? wpbc_sanitize_digit_or_csd( $params['skip_booking_id'] ) : '';
891 $params['resource_id'] = ( '' != $params['resource_id'] ) ? wpbc_sanitize_digit_or_csd( $params['resource_id'] ) : 1;
892
893
894 // S Q L
895 global $wpdb;
896 $sql = "SELECT DISTINCT dt.booking_date, dt.approved, bk.booking_id
897
898 FROM {$wpdb->prefix}bookingdates as dt
899
900 INNER JOIN {$wpdb->prefix}booking as bk
901
902 ON bk.booking_id = dt.booking_id
903
904 WHERE ( 1 = 1 )";
905
906 // W H E R E
907 $sql_where = '';
908 $sql_where .= ( '' != $params['approved'] ) ? " AND ( dt.approved = {$params['approved']} ) " : ''; // Approved (1) or Pending (0) or All // int
909 $sql_where .= " AND dt.booking_date >= " . wpbc_sql_date_math_expr_explicit('', 'curdate') . " "; // Only actual bookings
910 $sql_where .= " AND bk.trash != 1 "; // Not in Trash // int
911 $sql_where .= " AND bk.booking_type IN ( {$params['resource_id']} ) "; // For specific calendar (booking resource) // int
912 $sql_where .= ( '' != $params['skip_booking_id'] ) ? " AND dt.booking_id NOT IN ( {$params['skip_booking_id']} ) " : '' ; // Skip some bookings ? Usually, during booking edit.
913
914 // O R D E R
915 $sql_order = " ORDER BY dt.booking_date"; // Order by booking dates & times
916
917
918 /**
919 * Array( [0] => stdClass Object ( [booking_date] => 2022-12-27 00:00:00, [approved] => 0, [booking_id] => 187 )
920 [1] => stdClass Object ( [booking_date] => 2022-12-28 00:00:00, [approved] => 1, [booking_id] => 26 )
921 ...
922 */
923
924 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
925 $result_arr = $wpdb->get_results( $sql . $sql_where . $sql_order );
926
927 // P A R S E
928 $prior_check_out_date = false;
929 $dates_arr = array();
930 foreach ( $result_arr as $sql_date ) {
931
932 $blocked_days_range = array( $sql_date->booking_date );
933 $resource_id = explode( ',', $params['resource_id'] );
934 $resource_id = $resource_id[0];
935 if (
936 ( ! class_exists( 'wpdev_bk_biz_l' ) )
937 || ( ( class_exists( 'wpdev_bk_biz_l' ) ) && ( ! wpbc_is_this_parent_resource( $resource_id ) ) )
938 ){ // FixIn: 9.1.2.7.
939 list( $blocked_days_range, $prior_check_out_date ) = apply_filters( 'wpbc_get_extended_block_dates_filter', array( $blocked_days_range, $prior_check_out_date ) );
940 }
941
942 foreach ( $blocked_days_range as $date_ymd_his ) {
943
944 $sql_date->booking_date = $date_ymd_his;
945
946
947 $date_as_int = strtotime( $sql_date->booking_date );
948
949 $date_key = gmdate( 'Y-m-d', $date_as_int );
950 $date_seconds = $date_as_int - strtotime( $date_key );
951
952 // Transform '2022-09-01' to 9-1-2022
953 $date_key__for_calendar = gmdate( 'n-j-Y', $date_as_int ); // j - Day of the month without leading zeros 1 to 31 ; n - Number of month, without leading zeros 1 to 12
954
955 if ( empty( $dates_arr[ $date_key__for_calendar ] ) ) {
956 $dates_arr[ $date_key__for_calendar ] = array();
957 }
958
959 /**
960 * Important info about [ 'sec_' . $date_seconds ]
961 *
962 * We need to have 'sec_0' instead of simple 0
963 *
964 * for having JavaScript Objects (object property 'sec_o') instead of Array (index 0), after sending Ajax response and JSON decode!
965 */
966 $dates_arr[ $date_key__for_calendar ][ 'sec_' . $date_seconds] = $sql_date;
967 }
968
969
970 }
971
972 return $dates_arr;
973 }
974
975
976 /**
977 * Get season availability based on booking resource and seasons from Booking > Resources > Availability page
978 *
979 * @param array $params array(
980 'resource_id' => 1 // int or dcv
981 , 'from' => 'NOW' // any value that is possible to use in strtotime()
982 , 'count' => 365 // int
983 )
984 *
985 * @return array Array (
986 [2023-01-09] => 1
987 [2023-01-10] => 1
988 [2023-01-11] => 1
989 [2023-01-12] => 1
990 [2023-01-13] => 1
991 [2023-01-14] =>
992 [2023-01-15] =>
993 [2023-01-16] => 1
994 [2023-01-17] => 1
995 [2023-01-18] => 1
996 [2023-01-19] => 1
997 ...
998 */
999 function wpbc__sql__get_season_availability( $params ){
1000
1001 // FixIn: 9.5.4.4.
1002 $max_days_count = 365;
1003 $max_monthes_in_calendar = get_bk_option( 'booking_max_monthes_in_calendar' );
1004
1005 if ( strpos( $max_monthes_in_calendar, 'm' ) !== false ) {
1006 $max_days_count = intval( str_replace( 'm', '', $max_monthes_in_calendar ) ) * 31 + 5; // FixIn: 9.6.1.1.
1007 } else {
1008 $max_days_count = intval( str_replace( 'y', '', $max_monthes_in_calendar ) ) * 365 + 15; // FixIn: 9.6.1.1.
1009 }
1010
1011 $defaults = array(
1012 'resource_id' => 1 // int or dcv
1013 , 'from' => 'NOW' // any value that is possible to use in strtotime()
1014 , 'count' => $max_days_count // int
1015 );
1016 $params = wp_parse_args( $params, $defaults );
1017
1018
1019 // S a n i t i z e
1020 $params['resource_id'] = ( '' != $params['resource_id'] ) ? wpbc_sanitize_digit_or_csd( $params['resource_id'] ) : 1;
1021
1022 $is_all_days_available = true;
1023
1024 $season_filters_id_arr = array();
1025
1026 if ( ( class_exists( 'wpdev_bk_biz_m' ) ) && ( function_exists( 'wpbc_get_resource_meta' ) ) ) { // BM and higher // FixIn: 9.9.0.13.
1027
1028 // S Q L
1029 $availability_res = wpbc_get_resource_meta( $params['resource_id'], 'availability' );
1030
1031 if ( ! empty( $availability_res ) ) {
1032
1033 /**
1034 * Array ( [general] => On, [filter] => Array ( [1] => On, ...
1035 * [2] => Off
1036 * ...
1037 * [8] => Off
1038 * [9] => On
1039 * )
1040 * )
1041 */
1042 $availability = maybe_unserialize( $availability_res[0]->value );
1043
1044 $is_all_days_available = ( 'On' === $availability['general'] ) ? true : false;
1045 $season_filter = $availability['filter'];
1046
1047 // Get ID of only activated Seasons
1048 if ( is_array( $season_filter ) ) {
1049 foreach ( $season_filter as $key => $value ) {
1050 if ( $value == 'On' ) {
1051 $season_filters_id_arr[] = intval( $key ); // Sanitize booking_filter_id for future SQL
1052 }
1053 }
1054 }
1055
1056 }
1057
1058 }
1059
1060 $days_availability = array();
1061
1062 for( $i = 0; $i < $params['count']; $i++) {
1063
1064 $date_y_m_d = gmdate( 'Y-m-d', strtotime( '+' . $i . 'days', strtotime( $params['from'] ) ) );
1065
1066 $days_availability[ $date_y_m_d ] = $is_all_days_available;
1067
1068 $date_arr = explode( '-', $date_y_m_d );
1069
1070 foreach ( $season_filters_id_arr as $filter_id ) {
1071
1072 $day = intval( $date_arr[2] );
1073 $month = intval( $date_arr[1] );
1074 $year = intval( $date_arr[0] );
1075
1076 if ( wpbc_is_day_inside_of_filter( $day, $month, $year, $filter_id ) ){
1077 $days_availability[ $date_y_m_d ] = ! $days_availability[ $date_y_m_d ];
1078 break;
1079 }
1080 }
1081
1082 }
1083
1084 return $days_availability;
1085 }
1086