PluginProbe
Booking Calendar / 10.10.1
Booking Calendar v10.10.1
11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 All 203 releases
booking / core / wpbc_functions.php

wpbc_functions.php in Booking Calendar 10.10.1, at core/wpbc_functions.php

1,610 lines 54.3 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 Support 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 // <editor-fold defaultstate="collapsed" desc=" == Get html preview of shortcode for Edit pages == " >
18
19 /**
20 * Get html preview of shortcode for Edit pages in Elementor and at Block editors
21 *
22 * @param $shortcode_type
23 * @param $attr
24 *
25 * @return string
26 */
27 function wpbc_get_preview_for_shortcode( $shortcode_type, $attr ) {
28
29 // FixIn: 9.9.0.39.
30
31 return '<div style="border:2px dashed #ccc;text-align: center; padding:10px;display:flex;flex-flow:column wrap;justify-content: center;align-content: center;">
32 <div>WP Booking Calendar Shortcode</div>
33 <code>['.$shortcode_type.' ...]</code>
34 <div style="font-size:0.8em;">This is not a real preview. Publish the page to see it in action.</div>
35 </div>';
36 }
37 // </editor-fold>
38
39
40 // <editor-fold defaultstate="collapsed" desc=" == Calendar functions == " >
41
42 /**
43 * Get maximum visible days in calendar
44 *
45 * @return int
46 */
47 function wpbc_get_max_visible_days_in_calendar(){
48
49 // Number of months to scroll
50 $max_visible_days_in_calendar = get_bk_option( 'booking_max_monthes_in_calendar');
51
52 if ( false !== strpos( $max_visible_days_in_calendar, 'm' ) ) {
53 //$max_visible_days_in_calendar = intval( str_replace( 'm', '', $max_visible_days_in_calendar ) ) * 31 ; // FixIn: 9.6.1.1.
54 // FixIn: 10.0.0.26.
55 $diff_days = strtotime( '+' . intval( str_replace( 'm', '', $max_visible_days_in_calendar ) ) . ' months', strtotime( 'now' ) ) - strtotime( 'now' );
56 $max_visible_days_in_calendar = round( $diff_days / ( 60 * 60 * 24 ) ) + 1;
57 } else {
58 $max_visible_days_in_calendar = intval( str_replace( 'y', '', $max_visible_days_in_calendar ) ) * 365 + 15; // FixIn: 9.6.1.1.
59 }
60
61 return $max_visible_days_in_calendar;
62 }
63
64
65 /**
66 * Parse {calendar ....} option parameter in Calendar | Booking form shortcode
67 *
68 * @param $bk_options
69 *
70 * @return array|false
71 */
72 function wpbc_parse_calendar_options( $bk_options ) {
73
74 if ( empty( $bk_options ) ) {
75 return false;
76 }
77 /* $matches structure:
78 * Array
79 (
80 [0] => Array
81 (
82 [0] => {calendar months="6" months_num_in_row="2" width="341px" cell_height="48px"},
83 [1] => calendar
84 [2] => months="6" months_num_in_row="2" width="341px" cell_height="48px"
85 )
86
87 [1] => Array
88 (
89 [0] => {select-day condition="weekday" for="5" value="3"},
90 [1] => select-day
91 [2] => condition="weekday" for="5" value="3"
92 )
93 .....
94 )
95 */
96
97 $pattern_to_search='%\s*{([^\s]+)\s*([^}]+)\s*}\s*[,]?\s*%';
98
99 preg_match_all( $pattern_to_search, $bk_options, $matches, PREG_SET_ORDER );
100
101 foreach ( $matches as $value ) {
102 if ( $value[1] == 'calendar' ) {
103 $paramas = $value[2];
104 $paramas = trim( $paramas );
105 $paramas = explode( ' ', $paramas );
106 $options = array();
107 foreach ( $paramas as $vv ) {
108 if ( ! empty( $vv ) ) {
109 $vv = trim( $vv );
110 $vv = explode( '=', $vv );
111 if ( ( isset( $vv[0] ) ) && ( isset( $vv[1] ) ) ) {
112 $options[ $vv[0] ] = trim( $vv[1] );
113 }
114 }
115 }
116 if ( count( $options ) == 0 ) {
117 return false;
118 } else {
119 return $options;
120 }
121 }
122 }
123
124 return false; // We are not have the "calendar" options in the shortcode
125 }
126
127
128
129 /**
130 * Parse {calendar ....} option parameter in Calendar | Booking form shortcode
131 *
132 * @param $bk_options
133 *
134 * @return array|false
135 */
136 function wpbc_parse_calendar_options__aggregate_param( $bk_options ) { // FixIn: 9.8.15.10.
137
138 if ( empty( $bk_options ) ) {
139 return false;
140 }
141 /* $matches structure:
142 $matches = [
143 0 = [
144 0 = "{aggregate type=bookings_only}"
145 1 = "aggregate"
146 2 = "type=bookings_only"
147 ]
148 ]
149 */
150
151 $pattern_to_search='%\s*{([^\s]+)\s*([^}]+)\s*}\s*[,]?\s*%';
152
153 preg_match_all( $pattern_to_search, $bk_options, $matches, PREG_SET_ORDER );
154
155 foreach ( $matches as $value ) {
156 if ( $value[1] == 'aggregate' ) {
157 $paramas = $value[2];
158 $paramas = trim( $paramas );
159 $paramas = explode( ' ', $paramas );
160 $options = array();
161 foreach ( $paramas as $vv ) {
162 if ( ! empty( $vv ) ) {
163 $vv = trim( $vv );
164 $vv = explode( '=', $vv );
165 if ( ( isset( $vv[0] ) ) && ( isset( $vv[1] ) ) ) {
166 $options[ $vv[0] ] = trim( $vv[1] );
167 }
168 }
169 }
170 if ( count( $options ) == 0 ) {
171 return false;
172 } else {
173 return $options;
174 }
175 }
176 }
177
178 return false; // We are not have the "calendar" options in the shortcode
179 }
180
181
182 function wpbc_is_calendar_skin_legacy( $skin_name ){
183 $legacy_skins = array(
184 'black.css',
185 'multidays.css',
186 'premium-black.css',
187 'premium-light-noborder.css',
188 'premium-light.css',
189 'premium-marine.css',
190 'premium-steel-noborder.css',
191 'premium-steel.css',
192 'standard.css',
193 'traditional-light.css',
194 'traditional.css'
195 // FixIn: 10.7.1.5.
196 , 'traditional-times.css'
197 , 'black-2.css'
198 , 'green-01.css'
199 , 'light-01.css'
200 );
201
202 return in_array( $skin_name, $legacy_skins );
203 }
204
205
206 /**
207 * Get Legacy calendar skin
208 *
209 * @param $skin_name = 'Black-2'
210 * @param $skin_arr = ["24_9__dark_1.css", "/css/skins/blac...", "Black-2"]
211 *
212 * @return mixed
213 */
214 function wpbc_get_legacy_calendar_skin_name($skin_name, $skin_arr){
215
216 if (wpbc_is_calendar_skin_legacy($skin_arr[0]) ){
217 return __( 'Legacy', 'booking' ) . ': ' . $skin_name;
218 } else {
219 return $skin_name;
220 }
221 }
222
223 /**
224 * Get Calendar skin options for selectboxes
225 * @return void
226 */
227 function wpbc_get_calendar_skin_options( $url_prefix = '' ){
228 // Calendar Skin /////////////////////////////////////////////////////
229 $calendar_skins_options = array();
230 $legacy_calendar_skins_options = array();
231 // Skins in the Custom User folder (need to create it manually): http://example.com/wp-content/uploads/wpbc_skins/ ( This folder do not owerwrited during update of plugin )
232 $upload_dir = wp_upload_dir();
233 // FixIn: 8.9.4.8.
234 $files_in_folder = wpbc_dir_list( array( WPBC_PLUGIN_DIR . '/css/skins/' ) ); // Folders where to look about calendar skins
235 foreach ( $files_in_folder as $skin_file ) { // Example: $skin_file['/css/skins/standard.css'] => 'Standard';
236
237 //FixIn: 8.9.4.8 // FixIn: 9.1.2.10.
238 $skin_file[1] = str_replace( array( WPBC_PLUGIN_DIR, WPBC_PLUGIN_URL , $upload_dir['basedir'] ), '', $skin_file[1] ); // Get relative path for calendar skin
239
240 if ( ! wpbc_is_calendar_skin_legacy( $skin_file[0] ) ) {
241 $calendar_skins_options[ $skin_file[1] ] = $skin_file[2];
242 } else {
243 $legacy_calendar_skins_options[ $skin_file[1] ] = wpbc_get_legacy_calendar_skin_name( $skin_file[2], $skin_file );
244 }
245 }
246
247 $calendar_skins_options_real = array();
248 $calendar_skins_options_real[] = array( 'optgroup' => true, 'close' => false, 'title' => '&nbsp;' . __('Calendar Skins' ,'booking') );
249 foreach ( $calendar_skins_options as $s_key => $s_val ) {
250 $calendar_skins_options_real [ $url_prefix . $s_key ] = $s_val;
251 }
252 $calendar_skins_options_real[] = array( 'optgroup' => true, 'close' => true );
253 $calendar_skins_options_real[] = array( 'optgroup' => true, 'close' => false, 'title' => '&nbsp;' . __('Legacy Calendar Skins' ,'booking') );
254 foreach ( $legacy_calendar_skins_options as $s_key => $s_val ) {
255 $calendar_skins_options_real [ $url_prefix . $s_key ] = array( 'title' => $s_val, 'attr' => array( 'style' => 'color:#ccc;' ) );
256 }
257 $calendar_skins_options_real[] = array( 'optgroup' => true, 'close' => true );
258 $calendar_skins_options_real[] = array( 'optgroup' => true, 'close' => false, 'title' => '&nbsp;' . __('Custom Calendar Skins' ,'booking') );
259 $files_in_folder = wpbc_dir_list( array( $upload_dir['basedir'].'/wpbc_skins/' ) ); // Folders where to look about calendar skins
260 foreach ( $files_in_folder as $skin_file ) { // Example: $skin_file['/css/skins/standard.css'] => 'Standard';
261
262 //FixIn: 8.9.4.8 // FixIn: 9.1.2.10.
263 $skin_file[1] = str_replace( array( WPBC_PLUGIN_DIR, WPBC_PLUGIN_URL , $upload_dir['basedir'] ), '', $skin_file[1] ); // Get relative path for calendar skin
264
265 $calendar_skins_options_real[ $url_prefix . $skin_file[1] ] = $skin_file[2];
266
267 }
268
269 $calendar_skins_options_real[] = array( 'optgroup' => true, 'close' => true );
270
271 return $calendar_skins_options_real;
272 }
273 // </editor-fold>
274
275
276 // <editor-fold defaultstate="collapsed" desc=" == Files functions == " >
277
278 // Get array of images - icons inside of this directory
279 function wpbc_dir_list ($directories) {
280
281 // create an array to hold directory list
282 $results = array();
283
284 if (is_string($directories)) $directories = array($directories);
285 foreach ($directories as $dir) {
286 if ( is_dir( $dir ) ) {
287 $directory = $dir;
288 } else {
289 $directory = WPBC_PLUGIN_DIR . $dir;
290 }
291
292 if ( file_exists( $directory ) ) { //FixIn: 5.4.5
293 // create a handler for the directory
294 $handler = @opendir($directory);
295 if ($handler !== false) {
296 // keep going until all files in directory have been read
297 while ($file = readdir($handler)) {
298
299 // if $file isn't this directory or its parent,
300 // add it to the results array
301 if ($file != '.' && $file != '..' && ( strpos($file, '.css' ) !== false ) )
302 $results[] = array($file, /* WPBC_PLUGIN_URL .*/ $dir . $file, ucfirst(strtolower( str_replace('.css', '', $file))) );
303 }
304
305 // tidy up: close the handler
306 closedir($handler);
307 }
308 }
309 }
310 // done!
311 return $results;
312 }
313
314
315 /**
316 * Check if such file exist or not.
317 *
318 * @param string $path - relative path to file (relative to plugin folder).
319 * @return boolean true | false
320 */
321 function wpbc_is_file_exist( $path ) {
322
323 if ( file_exists( trailingslashit( WPBC_PLUGIN_DIR ) . ltrim( $path, '/\\' ) ) ) // check if this file exist
324 return true;
325 else
326 return false;
327 }
328
329
330 /**
331 * Count the number of bytes of a given string.
332 * Input string is expected to be ASCII or UTF-8 encoded.
333 * Warning: the function doesn't return the number of chars
334 * in the string, but the number of bytes.
335 * See http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
336 * for information on UTF-8.
337 *
338 * @param string $str The string to compute number of bytes
339 *
340 * @return The length in bytes of the given string.
341 */
342 function wpbc_get_bytes_from_str( $str ) {
343 // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
344 // Number of characters in string
345 $strlen_var = strlen( $str );
346
347 $d = 0; // string bytes counter
348
349 // Iterate over every character in the string, escaping with a slash or encoding to UTF-8 where necessary
350 for ( $c = 0; $c < $strlen_var; ++ $c ) {
351 $ord_var_c = ord( $str[$c] ); // FixIn: 2.0.17.1.
352 switch ( true ) {
353 case(($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): // characters U-00000000 - U-0000007F (same as ASCII)
354 $d ++;
355 break;
356 case(($ord_var_c & 0xE0) == 0xC0): // characters U-00000080 - U-000007FF, mask 110XXXXX
357 $d += 2;
358 break;
359 case(($ord_var_c & 0xF0) == 0xE0): // characters U-00000800 - U-0000FFFF, mask 1110XXXX
360 $d += 3;
361 break;
362 case(($ord_var_c & 0xF8) == 0xF0): // characters U-00010000 - U-001FFFFF, mask 11110XXX
363 $d += 4;
364 break;
365 case(($ord_var_c & 0xFC) == 0xF8): // characters U-00200000 - U-03FFFFFF, mask 111110XX
366 $d += 5;
367 break;
368 case(($ord_var_c & 0xFE) == 0xFC): // characters U-04000000 - U-7FFFFFFF, mask 1111110X
369 $d += 6;
370 break;
371 default:
372 $d ++;
373 }
374 }
375 return $d;
376 }
377
378
379 // </editor-fold>
380
381
382 // <editor-fold defaultstate="collapsed" desc=" == Can I Load JavaScript Files == " >
383
384 function wpbc_can_i_load_on__edit_new_post_page() {
385
386 if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
387 return false;
388 }
389
390
391 $pages_where_load = array( 'post-new.php', 'page-new.php', 'post.php', 'page.php', 'widgets.php', 'customize.php' );
392 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
393 if ( ( in_array( basename( $_SERVER['PHP_SELF'] ), $pages_where_load ) )
394 || ( wpbc_is_setup_wizard_page() )
395 ) {
396 return true;
397 }
398
399 return false;
400 }
401
402
403 function wpbc_can_i_load_on__searchable_resources_page() {
404
405 if (
406 ( isset( $_REQUEST['page'] ) ) && ( $_REQUEST['page'] === 'wpbc-resources' ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
407 && ( isset( $_REQUEST['tab'] ) ) && ( $_REQUEST['tab'] === 'searchable_resources' ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
408 ) {
409 return true;
410 }
411
412 return false;
413 }
414
415
416 function wpbc_can_i_load_on__resources_page() {
417
418 if (
419 ( isset( $_REQUEST['page'] ) ) && ( $_REQUEST['page'] === 'wpbc-resources' ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
420 ) {
421 return true;
422 }
423
424 return false;
425 }
426
427
428 /**
429 * Can I load scripts on this page for 'shortcode_config'
430 *
431 * @return bool
432 */
433 function wpbc_can_i_load_on_this_page__shortcode_config() {
434
435 if (
436 wpbc_can_i_load_on__edit_new_post_page()
437 || (
438 wpbc_can_i_load_on__resources_page()
439 && ( ! wpbc_can_i_load_on__searchable_resources_page() )
440 )
441 || wpbc_is_setup_wizard_page()
442 // || wpbc_is_bookings_page() // FixIn: 10.6.6.2.
443 ){
444 return true;
445 } else {
446 return false;
447 }
448 }
449
450 /**
451 * Can I load scripts on this page? Loaded only at ../admin.php?page=wpbc-resources&tab=searchable_resources
452 *
453 * @return bool
454 */
455 function wpbc_can_i_load_on_this_page__modal_search_options() {
456
457 if ( wpbc_can_i_load_on__searchable_resources_page() ){
458 return true;
459 } else {
460 return false;
461 }
462 }
463
464 // </editor-fold>
465
466
467 // <editor-fold defaultstate="collapsed" desc=" == Footer == " >
468
469 function wpbc_show_booking_footer(){
470
471 $wpdev_copyright_adminpanel = get_bk_option( 'booking_wpdev_copyright_adminpanel' ); // check
472
473 $message = '';
474
475
476
477 if ( ( 'Off' !== $wpdev_copyright_adminpanel ) && ( ! wpbc_is_this_demo() ) ) {
478
479
480 /* translators: 1: ... */
481 $message .= sprintf( __( 'If you like %1$s please leave us a %2$s rating. A huge thank you in advance!', 'booking' )
482 , '<strong>Booking Calendar</strong> ' . esc_attr( WP_BK_VERSION_NUM )
483 , '<a href="https://wordpress.org/support/plugin/booking/reviews/#new-post" target="_blank" title="' . esc_attr__( 'Thanks :)', 'booking' ) . '">'
484 . '&#9733;&#9733;&#9733;&#9733;&#9733;'
485 . '</a>'
486 );
487 }
488
489
490 if ( ! empty( $message ) ) {
491
492 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
493 echo '<div id="wpbc-footer" style="position:absolute;bottom:40px;text-align:left;width:95%;font-size:0.9em;text-shadow:0 1px 0 #fff;margin:0;color:#888;">' . $message . '</div>';
494
495 ?>
496 <script type="text/javascript">
497 jQuery(document).ready(function () {
498 jQuery('#wpfooter').append(jQuery('#wpbc-footer'));
499 });
500 </script>
501 <?php
502 }
503 }
504
505 // </editor-fold>
506
507
508 // <editor-fold defaultstate="collapsed" desc=" == P a g i n a t i o n o f T a b l e L i s t i n g == " >
509
510 /**
511 * Show P a g i n a t i o n
512 *
513 * @param int $summ_number_of_items - total number of items
514 * @param int $active_page_num - number of activated page
515 * @param int $num_items_per_page - number of items per page
516 * @param array $only_these_parameters - array of keys to exclude from links
517 * @param string $url_sufix - usefule for anchor to HTML section with specific ID, Example: '#my_section'
518 */
519 function wpbc_show_pagination( $summ_number_of_items, $active_page_num, $num_items_per_page , $only_these_parameters = false, $url_sufix = '' ) {
520
521 if ( empty( $num_items_per_page ) ) {
522 $num_items_per_page = '10';
523 }
524
525 $pages_number = ceil( $summ_number_of_items / $num_items_per_page );
526 if ( $pages_number < 2 )
527 return;
528
529 //Fix: 5.1.4 - Just in case we are having tooo much resources, then we need to show all resources - and its empty string
530 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
531 if ( ( isset( $_REQUEST['wh_booking_type'] ) ) && ( strlen( wp_unslash( $_REQUEST['wh_booking_type'] ) ) > 1000 ) ) {
532 $_REQUEST['wh_booking_type'] = '';
533 }
534
535 // First parameter will overwriten by $_GET['page'] parameter
536 $bk_admin_url = wpbc_get_params_in_url( wpbc_get_bookings_url( false, false ), array('page_num'), $only_these_parameters );
537
538
539 ?>
540 <span class="wpdevelop wpbc-pagination">
541 <div class="container-fluid">
542 <div class="row">
543 <div class="col-sm-12 text-center control-group0">
544 <nav class="btn-toolbar">
545 <div class="btn-group wpbc-no-margin" style="float:none;">
546
547 <?php
548 if ( $pages_number > 1 ) { ?>
549 <a class="button button-secondary <?php
550 echo ( $active_page_num == 1 ) ? ' disabled' : ''; ?>"
551 href="<?php
552 echo esc_url( $bk_admin_url ); ?>&page_num=<?php
553 if ( $active_page_num == 1 ) {
554 echo esc_attr( $active_page_num );
555 } else {
556 echo esc_attr( $active_page_num - 1 );
557 }
558 echo esc_attr( $url_sufix );
559 ?>">
560 <?php
561 esc_html_e( 'Prev', 'booking' ); ?>
562 </a>
563 <?php
564 }
565
566 /** Number visible pages (links) that linked to active page, other pages skipped by "..." */
567 $num_closed_steps = 3;
568
569 for ( $pg_num = 1; $pg_num <= $pages_number; $pg_num++ ) {
570
571 if ( ! (
572 ( $pages_number > ( $num_closed_steps * 4) )
573 && ( $pg_num > $num_closed_steps )
574 && ( ( $pages_number - $pg_num + 1 ) > $num_closed_steps )
575 && ( abs( $active_page_num - $pg_num ) > $num_closed_steps )
576 ) ) {
577 ?> <a class="button button-secondary <?php if ($pg_num == $active_page_num ) echo ' active'; ?>"
578 href="<?php echo esc_url( $bk_admin_url ); ?>&page_num=<?php echo esc_attr( $pg_num );
579 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
580 echo $url_sufix; ?>">
581 <?php echo wp_kses_post( $pg_num ); ?>
582 </a><?php
583
584 if ( ( $pages_number > ( $num_closed_steps * 4) )
585 && ( ($pg_num+1) > $num_closed_steps )
586 && ( ( $pages_number - ( $pg_num + 1 ) ) > $num_closed_steps )
587 && ( abs($active_page_num - ( $pg_num + 1 ) ) > $num_closed_steps )
588 ) {
589 echo ' <a class="button button-secondary disabled" href="javascript:void(0);">...</a> ';
590 }
591 }
592 }
593
594 if ( $pages_number > 1 ) { ?>
595 <a class="button button-secondary <?php
596 echo ( $active_page_num == $pages_number ) ? ' disabled' : ''; ?>"
597 href="<?php
598 echo esc_url( $bk_admin_url ); ?>&page_num=<?php
599 if ( $active_page_num == $pages_number ) {
600 echo esc_attr( $active_page_num );
601 } else {
602 echo esc_attr( $active_page_num + 1 );
603 }
604 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
605 echo $url_sufix; ?>">
606 <?php
607 esc_html_e( 'Next', 'booking' ); ?>
608 </a>
609 <?php
610 }
611 ?>
612
613 </div>
614 </nav>
615 </div>
616 </div>
617 </div>
618 </span>
619 <?php
620 }
621
622 // </editor-fold>
623
624
625 // <editor-fold defaultstate="collapsed" desc=" == Number of New Bookings == " >
626
627 /**
628 * Reset Cache for getting Number of new bookings. After this operation, system will get number of new bookings from the DB.
629 *
630 * @return void
631 */
632 function wpbc_booking_cache__new_bookings__reset(){
633 update_bk_option( 'booking_cache__new_bookings__saved_date', '' );
634 }
635 add_action( 'wpbc_track_new_booking', 'wpbc_booking_cache__new_bookings__reset' );
636 add_action( 'wpbc_set_booking_pending', 'wpbc_booking_cache__new_bookings__reset' );
637 add_action( 'wpbc_set_booking_approved', 'wpbc_booking_cache__new_bookings__reset' );
638 add_action( 'wpbc_move_booking_to_trash', 'wpbc_booking_cache__new_bookings__reset' );
639 add_action( 'wpbc_restore_booking_from_trash', 'wpbc_booking_cache__new_bookings__reset' );
640 add_action( 'wpbc_delete_booking_completely', 'wpbc_booking_cache__new_bookings__reset' );
641 add_action( 'wpbc_set_booking_as_read', 'wpbc_booking_cache__new_bookings__reset' );
642 add_action( 'wpbc_set_booking_as_unread', 'wpbc_booking_cache__new_bookings__reset' );
643
644
645 /**
646 * Get number of new bookings
647 * @return false|int|mixed|null
648 */
649 function wpbc_db_get_number_new_bookings() {
650
651 $new_bookings__number = get_bk_option( 'booking_cache__new_bookings__number' );
652 $new_bookings__saved_date = get_bk_option( 'booking_cache__new_bookings__saved_date' );
653
654 $nowdate_str_ymdhis = gmdate( 'Y-m-d H:i:s', strtotime( 'now' ) );
655
656 if ( ! empty( $new_bookings__saved_date ) ) {
657
658 $is_expired = ( strtotime( $new_bookings__saved_date ) <= strtotime( '-10 minutes', strtotime( $nowdate_str_ymdhis ) ) );
659
660 if ( ! $is_expired ) {
661 return $new_bookings__number;
662 }
663 }
664
665 global $wpdb;
666
667 $trash_bookings = ' AND bk.trash != 1 '; // FixIn: 6.1.1.10 - check also below usage of {$trash_bookings} .
668 $sql_req = "SELECT bk.booking_id FROM {$wpdb->prefix}booking as bk WHERE bk.is_new = 1 {$trash_bookings} ";
669
670 $sql_req = apply_bk_filter( 'get_sql_for_checking_new_bookings', $sql_req );
671 $sql_req = apply_bk_filter( 'get_sql_for_checking_new_bookings_multiuser', $sql_req );
672 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
673 $bookings = $wpdb->get_results( $sql_req );
674 $bookings_count = count( $bookings );
675
676 update_bk_option( 'booking_cache__new_bookings__number', $bookings_count );
677 update_bk_option( 'booking_cache__new_bookings__saved_date', $nowdate_str_ymdhis );
678
679 return $bookings_count;
680 }
681
682
683 /**
684 * Update 'is_new' status of bookings in Database
685 *
686 * @param $id_of_new_bookings inr or comma seperated ID of bookings. Example: '1' | '3,5,7,9'
687 * @param $is_new '0' | '1'
688 * @param $user_id 'user_id'
689 *
690 */
691 function wpbc_db_update_number_new_bookings( $id_of_new_bookings, $is_new = '0', $user_id = 1 ) {
692
693 global $wpdb;
694
695 if ( count( $id_of_new_bookings ) > 0 ) {
696
697 $id_of_new_bookings = implode( ',', $id_of_new_bookings );
698 $id_of_new_bookings = wpbc_clean_like_string_for_db( $id_of_new_bookings );
699
700
701 if ( 'all' === $id_of_new_bookings ) {
702 $update_sql = "UPDATE {$wpdb->prefix}booking AS bk SET bk.is_new = {$is_new} WHERE bk.is_new != {$is_new} "; // FixIn: 8.2.1.18.
703
704 $update_sql = apply_bk_filter( 'update_sql_for_checking_new_bookings', $update_sql, 0, $user_id );
705 } else {
706 $update_sql = "UPDATE {$wpdb->prefix}booking AS bk SET bk.is_new = {$is_new} WHERE bk.booking_id IN ( {$id_of_new_bookings} ) ";
707 }
708
709 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
710 if ( false === $wpdb->query( $update_sql ) ) {
711 debuge_error( 'Error during updating status of bookings at DB', __FILE__, __LINE__ );
712 die();
713 }
714 }
715 }
716
717 // </editor-fold>
718
719
720 // <editor-fold defaultstate="collapsed" desc=" == User ID | Role - functions == " >
721
722 /**
723 * Check if Current User have specific Role
724 *
725 * @return bool Whether the current user has the given capability.
726 */
727 function wpbc_is_current_user_have_this_role( $user_role ) {
728
729 if ( $user_role == 'administrator' ) $user_role = 'activate_plugins';
730 if ( $user_role == 'editor' ) $user_role = 'publish_pages';
731 if ( $user_role == 'author' ) $user_role = 'publish_posts';
732 if ( $user_role == 'contributor' ) $user_role = 'edit_posts';
733 if ( $user_role == 'subscriber') $user_role = 'read';
734
735 return current_user_can( $user_role );
736 }
737
738
739 /**
740 * Get Current ID of user or get user ID of Forced log in user in Booking Calendar MultiUser version.
741 *
742 * @return int
743 */
744 function wpbc_get_current_user_id() { // FixIn: 9.2.4.1.
745
746 if ( function_exists( 'wpbc_mu__wp_get_current_user' ) ) {
747 $user = wpbc_mu__wp_get_current_user();
748 $user_bk_id = $user->ID;
749 } else {
750 $user_bk_id = get_current_user_id();
751 }
752
753 return $user_bk_id;
754 }
755
756
757 /**
758 * Get Current User Object or get User object of Forced log in user in Booking Calendar MultiUser version.
759 *
760 * @return stdClass|WP_User|null
761 */
762 function wpbc_get_current_user() { // FixIn: 9.2.4.1.
763
764 if ( function_exists( 'wpbc_mu__wp_get_current_user' ) ) {
765 $user = wpbc_mu__wp_get_current_user();
766 } else {
767 $user = wp_get_current_user();
768 }
769
770 return $user;
771 }
772
773 // </editor-fold>
774
775
776 // <editor-fold defaultstate="collapsed" desc=" == Messages for Admin panel == " >
777
778
779 /**
780 * Show "Saved Changes" message at the top of settings page.
781 *
782 */
783 function wpbc_show_changes_saved_message() {
784 wpbc_show_message ( __('Changes saved.','booking'), 5 );
785 }
786
787
788 /**
789 * Show Message at Top of Admin Pages
790 *
791 * @param type $message - mesage to show
792 * @param type $time_to_show - number of seconds to show, if 0 or skiped, then unlimited time.
793 * @param type $message_type - Default: updated { updated | error | notice }
794 */
795 function wpbc_show_message ( $message, $time_to_show , $message_type = 'updated') {
796
797 // Generate unique HTML ID for the message
798 $inner_message_id = intval( time() * wp_rand(10, 100) );
799
800 // Get formated HTML message
801 $notice = wpbc_get_formated_message( $message, $message_type, $inner_message_id );
802
803 // Get the time of message showing
804 $time_to_show = intval( $time_to_show ) * 1000;
805
806 // Show this Message
807 ?> <script type="text/javascript">
808 if ( jQuery('.wpbc_admin_message').length ) {
809 jQuery('.wpbc_admin_message').append( '<?php
810 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
811 echo $notice; ?>' );
812 <?php if ( $time_to_show > 0 ) { ?>
813 jQuery('#wpbc_inner_message_<?php echo esc_attr( $inner_message_id ); ?>').animate({opacity: 1},<?php echo esc_attr( $time_to_show ); ?>).fadeOut( 2000 );
814 <?php } ?>
815 }
816 </script> <?php
817 }
818
819
820 /**
821 * Escape and prepare message to show it
822 *
823 * @param type $message - message
824 * @param type $message_type - Default: updated { updated | error | notice }
825 * @param string $inner_message_id - ID of message DIV, can be skipped
826 * @return string
827 */
828 function wpbc_get_formated_message ( $message, $message_type = 'updated', $inner_message_id = '') {
829
830
831 // Recheck for any "lang" shortcodes for replacing to correct language
832 $message = wpbc_lang( $message );
833
834 // Escape any JavaScript from message
835 $notice = html_entity_decode( esc_js( $message ) ,ENT_QUOTES) ;
836
837 $notice .= '<a class="close tooltip_left" rel="tooltip" title="'. esc_js(__("Hide",'booking')). '" data-dismiss="alert" href="javascript:void(0)" onclick="javascript:jQuery(this).parent().hide();">&times;</a>';
838
839 if (! empty( $inner_message_id ))
840 $inner_message_id = 'id="wpbc_inner_message_'. $inner_message_id .'"';
841
842 $notice = '<div '.$inner_message_id.' class="wpbc_inner_message '. $message_type . '">' . $notice . '</div>';
843
844 return $notice;
845 }
846
847
848 /**
849 * Show system info in settings page
850 *
851 * @param string $message ...
852 * @param string $message_type 'info' | 'warning' | 'error'
853 * @param string $title __('Important!' ,'booking') | __('Note' ,'booking')
854 *
855 * Exmaple: wpbc_show_message_in_settings( __( 'Nothing Found', 'booking' ), 'warning', __('Important!' ,'booking') );
856 */
857 function wpbc_show_message_in_settings( $message, $message_type = 'info', $title = '' , $is_echo = true ) {
858
859 $message_content = '';
860
861 $message_content .= '<div class="clear"></div>';
862
863 $message_content .= '<div class="wpbc-settings-notice notice-' . $message_type . '" style="text-align:left;">';
864
865 if ( ! empty( $title ) )
866 $message_content .= '<strong>' . esc_js( $title ) . '</strong> ';
867
868 $message_content .= html_entity_decode( esc_js( $message ) ,ENT_QUOTES) ;
869
870 $message_content .= '</div>';
871
872 $message_content .= '<div class="clear"></div>';
873
874 if ( $is_echo ) {
875 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
876 echo $message_content;
877 } else {
878 return $message_content;
879 }
880
881 }
882
883 // </editor-fold>
884
885
886 // <editor-fold defaultstate="collapsed" desc=" == Meta Boxes - Open/Close == " >
887
888 /**
889 * Meta box section open tag
890 *
891 * @param string $metabox_id HTML ID of section
892 * @param string $title Title in section
893 * @param array $params [
894 'is_section_visible_after_load' => true, // Default true - is this section Visible, after page loading or hidden - useful for Booking > Settings General page LEFT column sections
895 'is_show_minimize' => true // Default true - is show minimize button at top right section
896 ]
897 *
898 * @return void
899 */
900 function wpbc_open_meta_box_section( $metabox_id, $title, $params = array() ) {
901
902 $defaults = array(
903 'is_section_visible_after_load' => true,
904 'is_show_minimize' => true,
905 'dismiss_button' => '',
906 'css_class' => 'postbox'
907 );
908 $params = wp_parse_args( $params, $defaults );
909
910 $my_close_open_win_id = $metabox_id . '_metabox';
911
912 ?>
913 <div class='meta-box'>
914 <div id="<?php echo esc_attr( $my_close_open_win_id ); ?>"
915 class="<?php echo esc_attr( $params['css_class'] ); ?> <?php
916 if ( $params['is_show_minimize'] ) {
917 if ( '1' == get_user_option( 'booking_win_' . $my_close_open_win_id ) ) {
918 echo 'closed';
919 }
920 }
921 ?>"
922 style="<?php if ( ! $params['is_section_visible_after_load'] ) {
923 echo 'display:none';
924 }
925 ?>"
926 ><div class="postbox-header" style="display: flex;flex-flow: row nowrap;border-bottom: 1px solid #ccd0d4;">
927 <h3 class='hndle' style="flex: 1 1 auto;border: none;">
928 <span><?php
929 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
930 echo $title;
931 ?></span>
932 <?php
933 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
934 echo $params['dismiss_button'];
935 ?>
936 </h3>
937 <?php if ( $params['is_show_minimize'] ) { ?>
938 <div title="<?php esc_attr_e('Click to toggle','booking'); ?>" class="handlediv"
939 onclick="javascript:wpbc_verify_window_opening(<?php echo esc_attr( wpbc_get_current_user_id() ); ?>, '<?php echo esc_attr( $my_close_open_win_id ); ?>');"
940 ><br/></div>
941 <?php } ?>
942 </div>
943 <div class="inside">
944 <?php
945 }
946
947
948 function wpbc_close_meta_box_section() {
949 ?>
950 </div>
951 </div>
952 </div>
953 <?php
954 }
955
956 // </editor-fold>
957
958
959 // <editor-fold defaultstate="collapsed" desc=" == Inline JavaScript to Footer page == " >
960
961 /**
962 * Queue JavaScript for later output at footer
963 *
964 * @param string $code
965 */
966 function wpbc_enqueue_js( $code ) {
967 global $wpbc_queued_js;
968
969 if ( empty( $wpbc_queued_js ) ) {
970 $wpbc_queued_js = '';
971 }
972
973 $wpbc_queued_js .= "\n" . $code . "\n";
974 }
975
976
977 /**
978 * Output any queued javascript code in the footer.
979 */
980 function wpbc_print_js() {
981
982 global $wpbc_queued_js;
983
984 if ( ! empty( $wpbc_queued_js ) ) {
985
986 $wpbc_queued_js = wp_check_invalid_utf8( $wpbc_queued_js );
987
988 $wpbc_queued_js = wp_specialchars_decode( $wpbc_queued_js, ENT_COMPAT ); // Converts double quotes '&quot;' => '"'.
989
990 $wpbc_queued_js = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", $wpbc_queued_js );
991 $wpbc_queued_js = str_replace( "\r", '', $wpbc_queued_js );
992
993 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
994 echo "<!-- WPBC JavaScript -->\n<script type=\"text/javascript\">\njQuery(function($) {" . $wpbc_queued_js . "});\n</script>\n<!-- End WPBC JavaScript -->\n";
995
996 $wpbc_queued_js = '';
997 unset( $wpbc_queued_js );
998 }
999 }
1000
1001 // </editor-fold>
1002
1003
1004 // <editor-fold defaultstate="collapsed" desc=" == Support functions for MU version == " >
1005
1006 /**
1007 * Set active User Environment in MultiUser version, depend from owner of booking resource
1008 *
1009 * @param int $previous_active_user (default=-1) - blank parameter
1010 * @param int $bktype - booking resource ID for checking
1011 * @return int - ID of Previous Active User
1012 *
1013 * Usage:
1014 $previous_active_user = apply_bk_filter('wpbc_mu_set_environment_for_owner_of_resource', -1, $bktype );
1015
1016 */
1017 function wpbc_mu_set_environment_for_owner_of_resource( $previous_active_user = -1, $bktype = 1 ) {
1018
1019 if ( class_exists( 'wpdev_bk_multiuser' ) ) {
1020 // Get the owner of this booking resource
1021 $user_bk_id = apply_bk_filter( 'get_user_of_this_bk_resource', false, $bktype );
1022
1023 $user = wpbc_get_current_user();
1024
1025 // Get possible other active user settings
1026 $previous_active_user = apply_bk_filter( 'get_client_side_active_params_of_user' );
1027
1028 // Set active user of that specific booking resource
1029 make_bk_action( 'check_multiuser_params_for_client_side_by_user_id', $user_bk_id );
1030 }
1031
1032 return $previous_active_user;
1033 }
1034 add_bk_filter('wpbc_mu_set_environment_for_owner_of_resource', 'wpbc_mu_set_environment_for_owner_of_resource');
1035
1036
1037 /**
1038 * Set environment for this user in MU version
1039 *
1040 * @param int $previous_active_user - ID of user
1041 * Usage:
1042 make_bk_action('wpbc_mu_set_environment_for_user', $previous_active_user );
1043
1044 */
1045 function wpbc_mu_set_environment_for_user( $previous_active_user ) {
1046
1047 if ( $previous_active_user !== -1 ) {
1048
1049 // Reactivate the previous active user
1050 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $previous_active_user );
1051 }
1052 }
1053 add_bk_action('wpbc_mu_set_environment_for_user', 'wpbc_mu_set_environment_for_user');
1054
1055
1056 /**
1057 * Check if we have simulated user login in Booking Calendar MultiUser version
1058 * return user ID of regular simulated user or 0 if not simulated
1059 * @return int
1060 */
1061 function wpbc_mu__is_simulated_login_as_user(){
1062 if ( class_exists( 'wpdev_bk_multiuser' ) ) {
1063
1064 $real_current_user_id = get_current_user_id(); // Is current user suer booking admin and if this user was simulated log in
1065 $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $real_current_user_id );
1066 if ( $is_user_super_admin ) {
1067
1068 $simulate_user_id = intval( get_option( 'booking_simulate_login_as_user' ) ); // Is user was simulated log in
1069
1070 if ( ( ! empty( $simulate_user_id ) ) && ( $simulate_user_id > 0 ) ) {
1071 return $simulate_user_id;
1072 }
1073 }
1074 }
1075 return 0;
1076 }
1077 // </editor-fold>
1078
1079
1080 // <editor-fold defaultstate="collapsed" desc=" == Currency functions (>=BS) == " >
1081
1082 /**
1083 * Format booking cost with a currency symbol.
1084 * In MultiUser version also checking about specific currency that belong to specific WordPress user.
1085 * This checking based on belonging specific booking resource to specific user.
1086 *
1087 * @param float $cost
1088 * @param int $booking_resource_id
1089 * @return string - $cost_to_show_with_currency
1090 */
1091 function wpbc_get_cost_with_currency_for_user( $cost, $booking_resource_id = 0 ){
1092
1093 if ( ( $cost === '' ) || ( ! class_exists( 'wpdev_bk_biz_s' ) ) ) {
1094 return '';
1095 }
1096
1097 if ( ! empty( $booking_resource_id ) ) {
1098 $previous_active_user = apply_bk_filter( 'wpbc_mu_set_environment_for_owner_of_resource', - 1, $booking_resource_id );
1099 } // MU
1100
1101 $cost_to_show_with_currency = wpbc_cost_show( $cost, array( 'currency' => wpbc_get_currency() ) );
1102
1103 if ( ! empty( $booking_resource_id ) ) {
1104 make_bk_action( 'wpbc_mu_set_environment_for_user', $previous_active_user );
1105 } // MU
1106
1107 return $cost_to_show_with_currency;
1108 }
1109
1110
1111 /**
1112 * Get currency Symbol.
1113 * In MultiUser version also checking about specific currency that belong to specific WordPress user.
1114 * This checking based on belonging specific booking resource to specific user.
1115 *
1116 * @param int $booking_resource_id - ID of specific booking resource
1117 * @return string - currency symbol
1118 */
1119 function wpbc_get_currency_symbol_for_user( $booking_resource_id = 0 ){
1120
1121 if ( ! class_exists( 'wpdev_bk_biz_s' ) ) {
1122 return '';
1123 }
1124
1125 if ( ! empty( $booking_resource_id ) ) {
1126 $previous_active_user = apply_bk_filter( 'wpbc_mu_set_environment_for_owner_of_resource', - 1, $booking_resource_id );
1127 } // MU
1128
1129 $currency_symbol = wpbc_get_currency_symbol();
1130
1131 if ( ! empty( $booking_resource_id ) ) {
1132 make_bk_action( 'wpbc_mu_set_environment_for_user', $previous_active_user );
1133 } // MU
1134
1135 return $currency_symbol;
1136 }
1137
1138 /**
1139 * Get Cost per period: DAY / NIGHT / FIXED / HOUR
1140 * In MultiUser version This checking based on belonging specific booking resource to specific user.
1141 *
1142 * @param int $booking_resource_id - ID of specific booking resource
1143 * @return string - cost per period
1144 */
1145 function wpbc_get_cost_per_period_for_user( $booking_resource_id = 0 ){ // FixIn: 10.0.0.14.
1146
1147 if ( ! class_exists( 'wpdev_bk_biz_s' ) ) {
1148 return '';
1149 }
1150
1151 if ( ! empty( $booking_resource_id ) ) {
1152 $previous_active_user = apply_bk_filter( 'wpbc_mu_set_environment_for_owner_of_resource', - 1, $booking_resource_id );
1153 } // MU
1154
1155 $cost_period = get_bk_option( 'booking_paypal_price_period' );
1156
1157 if ( ! empty( $booking_resource_id ) ) {
1158 make_bk_action( 'wpbc_mu_set_environment_for_user', $previous_active_user );
1159 } // MU
1160
1161 return $cost_period;
1162 }
1163 // </editor-fold>
1164
1165
1166 // <editor-fold defaultstate="collapsed" desc=" == Approve | Pending functions == " >
1167
1168 /**
1169 * Check is this booking approved -- get booking dates in DB and check status
1170 *
1171 * @param $booking_id
1172 *
1173 * @return bool
1174 */
1175 function wpbc_is_booking_approved( $booking_id ) {
1176 // FixIn: 8.1.2.8.
1177
1178 $is_booking_approved = false;
1179
1180 global $wpdb;
1181
1182 $sql = $wpdb->prepare( "SELECT DISTINCT approved FROM {$wpdb->prefix}bookingdates WHERE booking_id = %d ORDER BY booking_date", $booking_id );
1183 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
1184 $dates_result = $wpdb->get_results( $sql );
1185
1186 foreach ( $dates_result as $my_date ) {
1187
1188 if ( 1 === intval( $my_date->approved ) ) {
1189 $is_booking_approved = true; // FixIn: 8.3.1.2.
1190 }
1191 }
1192
1193 return $is_booking_approved;
1194 }
1195
1196
1197 /**
1198 * Approve booking in DB (update booking dates in DB like approved = '1')
1199 *
1200 * @param $booking_id int | CSD e.g. 100 | '1,5,10'
1201 *
1202 * @return bool
1203 */
1204 function wpbc_db__booking_approve( $booking_id ) {
1205
1206 $booking_id = wpbc_clean_digit_or_csd( $booking_id ); // Check parameter if it number or comma separated list of numbers.
1207
1208 global $wpdb;
1209
1210 $update_sql = "UPDATE {$wpdb->prefix}bookingdates SET approved = '1' WHERE booking_id IN ({$booking_id});";
1211
1212 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
1213 if ( false === $wpdb->query( $update_sql ) ) {
1214 return false;
1215 }
1216
1217 // In case if the booking was in Trash, then restore it.
1218 // FixIn: 10.8.1.1.
1219
1220 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1221 if ( false === $wpdb->query( "UPDATE {$wpdb->prefix}booking AS bk SET bk.trash = 0 WHERE booking_id IN ({$booking_id})" ) ) {
1222 return false;
1223 }
1224
1225 return true;
1226 }
1227
1228
1229 /**
1230 * Approve specific booking and send email about this.
1231 *
1232 * @param int $booking_id - ID of booking
1233 * @param string $email_reason
1234 */
1235 function wpbc_auto_approve_booking( $booking_id, $email_reason = '' ) {
1236
1237 $booking_id = wpbc_clean_digit_or_csd( $booking_id ); // Check paramter if it number or comma separated list of numbers.
1238
1239 if ( is_numeric( $booking_id ) ) { // FixIn: 8.1.2.8.
1240 if ( ! wpbc_is_booking_approved( $booking_id ) ) {
1241 do_action( 'wpbc_booking_approved', $booking_id, 1 ); // FixIn: 8.7.6.1.
1242
1243 wpbc_send_email_approved( $booking_id, 1, $email_reason );
1244 }
1245 } else {
1246 $booking_id_arr = explode( ',', $booking_id );
1247 foreach ( $booking_id_arr as $bk_id ) {
1248 if ( ! wpbc_is_booking_approved( $bk_id ) ) {
1249 do_action( 'wpbc_booking_approved', $bk_id, 1 ); // FixIn: 8.7.6.1.
1250 wpbc_send_email_approved( $bk_id, 1, $email_reason );
1251 }
1252 }
1253 }
1254
1255 $db_result = wpbc_db__booking_approve( $booking_id );
1256
1257 if ( false === $db_result ) {
1258
1259 wpbc_redirect( site_url() );
1260 }
1261 }
1262
1263
1264 /**
1265 * Set as Pending specific booking and send email about this.
1266 *
1267 * @param int $booking_id - ID of booking
1268 * @param string $denyreason
1269 */
1270 function wpbc_auto_pending_booking( $booking_id, $denyreason = '' ) {
1271 // FixIn: 8.4.7.25.
1272
1273 global $wpdb;
1274
1275 $booking_id = wpbc_clean_digit_or_csd( $booking_id ); // Check paramter if it number or comma separated list of numbers.
1276
1277 if ( is_numeric( $booking_id ) ) { // FixIn: 8.1.2.8.
1278 if ( wpbc_is_booking_approved( $booking_id ) ) {
1279 wpbc_send_email_deny( $booking_id, 1, $denyreason );
1280 }
1281 } else {
1282 $booking_id_arr = explode( ',', $booking_id );
1283 foreach ( $booking_id_arr as $bk_id ) {
1284 if ( wpbc_is_booking_approved( $bk_id ) ) {
1285 wpbc_send_email_deny( $bk_id, 1, $denyreason );
1286 }
1287 }
1288 }
1289
1290 $update_sql = "UPDATE {$wpdb->prefix}bookingdates SET approved = '0' WHERE booking_id IN ({$booking_id});";
1291 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
1292 if ( false === $wpdb->query( $update_sql ) ) {
1293
1294 wpbc_redirect( site_url() );
1295 }
1296 }
1297
1298
1299 /**
1300 * Cancel (move to Trash) specific booking.
1301 *
1302 * @param int $booking_id - ID of booking
1303 * @param string $email_reason - reason of cancellation
1304 */
1305 function wpbc_auto_cancel_booking( $booking_id, $email_reason = '' ) {
1306 // FixIn: 8.4.7.25.
1307
1308 global $wpdb;
1309
1310 $booking_id = wpbc_clean_digit_or_csd( $booking_id ); // Check paramter if it number or comma separated list of numbers.
1311
1312 if ( empty( $email_reason ) ) { // FixIn: 8.4.7.25.
1313 // Get the reason of cancellation.
1314 $email_reason = __( 'Payment rejected', 'booking' );
1315 $auto_cancel_pending_unpaid_bk_is_send_email = get_bk_option( 'booking_auto_cancel_pending_unpaid_bk_is_send_email' );
1316 if ( 'On' === $auto_cancel_pending_unpaid_bk_is_send_email ) {
1317 $email_reason = get_bk_option( 'booking_auto_cancel_pending_unpaid_bk_email_reason' );
1318 }
1319 }
1320 // Send decline emails.
1321 wpbc_send_email_trash( $booking_id, 1, $email_reason );
1322 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1323 if ( false === $wpdb->query( "UPDATE {$wpdb->prefix}booking AS bk SET bk.trash = 1 WHERE booking_id IN ({$booking_id})" ) ) {
1324
1325 wpbc_redirect( site_url() );
1326 }
1327 }
1328
1329
1330 // FixIn: 9.9.0.43.
1331
1332 /**
1333 * Auto approve booking and send email, after successful payment process
1334 *
1335 * It resolves issue in Booking Calendar MultiUser version for sending "regular email" to visitors, if was made booking for booking resource, that belong to regular user,
1336 * and was activated this option "Receive all payments only to Super Booking Admin account" at the WP Booking Calendar > Settings General page in "Multiuser Options" section
1337 *
1338 * @param $booking_id
1339 *
1340 * @return void
1341 */
1342 function wpbc_auto_approve_booking__after_payment( $booking_id ) {
1343 //-------------------------------------------------------------------------------------------------- // FixIn: 9.9.0.43.
1344 $is_force_again = false;
1345 if ( class_exists( 'wpdev_bk_multiuser' ) ) {
1346
1347 list( $booking_hash, $booking_resource_id ) = wpbc_hash__get_booking_hash__resource_id( $booking_id );
1348
1349 $user_id = apply_bk_filter( 'get_user_of_this_bk_resource', false, $booking_resource_id );
1350
1351 $is_booking_resource_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_id );
1352
1353 if (
1354 ( 'On' == get_bk_option( 'booking_super_admin_receive_regular_user_payments' ) )
1355 && ( ! $is_booking_resource_user_super_admin )
1356 ) {
1357 // Finish "Super-User" forcing
1358 make_bk_action( 'finish_force_using_this_user' );
1359 //Reactivate data for "regular user
1360 make_bk_action( 'check_multiuser_params_for_client_side_by_user_id', $user_id );
1361
1362 $is_force_again = true;
1363 }
1364 }
1365 // -------------------------------------------------------------------------------------------------
1366
1367 wpbc_auto_approve_booking( $booking_id );
1368
1369 if ( $is_force_again ) { // FixIn: 9.9.0.43.
1370 make_bk_action( 'make_force_using_this_user', - 999 ); // '-999' - This ID "by default" is the ID of super booking admin user
1371 }
1372 }
1373
1374
1375 /**
1376 * Auto cancel booking and send email, after successful payment process
1377 *
1378 * It resolves issue in Booking Calendar MultiUser version for sending "regular email" to visitors, if was made booking for booking resource, that belong to regular user,
1379 * and was activated this option "Receive all payments only to Super Booking Admin account" at the WP Booking Calendar > Settings General page in "Multiuser Options" section
1380 *
1381 * @param $booking_id
1382 *
1383 * @return void
1384 */
1385 function wpbc_auto_cancel_booking__after_payment( $booking_id ) {
1386 //-------------------------------------------------------------------------------------------------- // FixIn: 9.9.0.43.
1387 $is_force_again = false;
1388 if ( class_exists( 'wpdev_bk_multiuser' ) ) {
1389
1390 list( $booking_hash, $booking_resource_id ) = wpbc_hash__get_booking_hash__resource_id( $booking_id );
1391
1392 $user_id = apply_bk_filter( 'get_user_of_this_bk_resource', false, $booking_resource_id );
1393
1394 $is_booking_resource_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_id );
1395
1396 if (
1397 ( 'On' == get_bk_option( 'booking_super_admin_receive_regular_user_payments' ) )
1398 && ( ! $is_booking_resource_user_super_admin )
1399 ) {
1400 // Finish "Super-User" forcing
1401 make_bk_action( 'finish_force_using_this_user' );
1402 //Reactivate data for "regular user
1403 make_bk_action( 'check_multiuser_params_for_client_side_by_user_id', $user_id );
1404
1405 $is_force_again = true;
1406 }
1407 }
1408 // -------------------------------------------------------------------------------------------------
1409
1410 wpbc_auto_cancel_booking( $booking_id );
1411
1412 if ( $is_force_again ) { // FixIn: 9.9.0.43.
1413 make_bk_action( 'make_force_using_this_user', - 999 ); // '-999' - This ID "by default" is the ID of super booking admin user
1414 }
1415 }
1416 // </editor-fold>
1417
1418
1419 // <editor-fold defaultstate="collapsed" desc=" == Logs for Notes / remarks == " >
1420
1421 /**
1422 * Add Log info to Notes of bookings
1423 *
1424 * @param array | int $booking_id_arr
1425 * @param string $message
1426 */
1427 function wpbc_db__add_log_info( $booking_id_arr, $message ) {
1428
1429 if ( get_bk_option( 'booking_log_booking_actions' ) !== 'On' ) {
1430 return;
1431 }
1432
1433 $booking_id_arr = (array) $booking_id_arr;
1434
1435 $is_append = true;
1436 foreach ( $booking_id_arr as $booking_id ) {
1437 $date_time = date_i18n( '[Y-m-d H:i] ' );
1438 make_bk_action('wpdev_make_update_of_remark' , $booking_id , $date_time . $message , $is_append ); // FixIn: 9.1.2.14.
1439 }
1440 }
1441
1442 // </editor-fold>
1443
1444
1445 // <editor-fold defaultstate="collapsed" desc=" == CSV export support function == " >
1446
1447 /**
1448 * Get Path from request URL. E.g. 'my-category/file.csv' from url, like https://server.com/my-category/file.csv
1449 *
1450 * It can detect internal sub folder or WordPress, like http://server.com/my-website/
1451 *
1452 * @return false|string
1453 */
1454 function wpbc_get_request_url_path(){
1455
1456 $server_request_uri = ( ( isset( $_SERVER['REQUEST_URI'] ) ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */
1457 $my_parsed_url = wp_parse_url( $server_request_uri );
1458
1459 if ( false === $my_parsed_url ) { // seriously malformed URLs, wp_parse_url() may return FALSE.
1460 return false;
1461 }
1462
1463 $my_parsed_url_path = trim( $my_parsed_url['path'] );
1464 $my_parsed_url_path = trim( $my_parsed_url_path, '/' );
1465
1466
1467 // Check internal sub folder of WP, like http://server.com/my-website/[ ... LINK ...] // FixIn: 2.0.5.4.
1468 if ( function_exists( 'wp_parse_url' ) ) {
1469 $wp_home_server_url = wp_parse_url( home_url() );
1470 } else {
1471 $wp_home_server_url = @wp_parse_url( home_url() );
1472 }
1473
1474 if ( ( false !== $wp_home_server_url ) && ( ! empty( $wp_home_server_url['path'] ) ) ) { // seriously malformed URLs, wp_parse_url() may return FALSE.
1475
1476 $server_url_sufix = trim( $wp_home_server_url[ 'path' ] ); // [path] => /my-website
1477 $server_url_sufix = trim( $server_url_sufix, '/' ); // my-website
1478
1479 if ( ! empty( $server_url_sufix ) ) {
1480
1481 $check_sufix = substr( $my_parsed_url_path, 0, strlen( $server_url_sufix ) );
1482
1483 if ( $check_sufix === $server_url_sufix ) {
1484
1485 $my_parsed_url_path = substr( $my_parsed_url_path, strlen( $server_url_sufix ) );
1486
1487 $my_parsed_url_path = trim( $my_parsed_url_path, '/' );
1488 }
1489 }
1490 } //End FixIn: 2.0.5.4
1491
1492 return $my_parsed_url_path;
1493 }
1494
1495 // </editor-fold>
1496
1497
1498 // <editor-fold defaultstate="collapsed" desc=" == SKIP BLANK EMAIL == " >
1499
1500
1501 /**
1502 * Check if this email is NOT blank email to SKIP email sending -- from autofill fast booking creation at Booking > Add booking page.
1503 *
1504 * Currently, plugin use 'blank@wpbookingmanager.com' for all blank bookings, previously it was used 'admin@blank.com'
1505 *
1506 * @param $email_address
1507 * @param $email_content
1508 *
1509 * @return bool
1510 */
1511 function wpbc_is_not_blank_email( $email_address, $email_content ) {
1512
1513 // Previously: if ( ( strpos( $to, '@blank.com' ) === false ) && ( strpos( $replace['content'], 'admin@blank.com' ) === false ) ) { ->send(...) }
1514
1515 if (
1516 ( false === strpos( $email_address, '@blank.com' ) )
1517 && ( false === strpos( $email_content, 'admin@blank.com' ) )
1518 && ( false === strpos( $email_address, '@wpbookingmanager.com' ) )
1519 && ( false === strpos( $email_content, 'blank@wpbookingmanager.com' ) )
1520 ) {
1521 return true;
1522 }
1523
1524 return false;
1525 }
1526
1527 // </editor-fold>
1528
1529
1530 // <editor-fold defaultstate="collapsed" desc=" == PHP PERFORMANCE == " >
1531
1532
1533 /**
1534 * Start calculation of time for execution of specific part of CODE
1535 *
1536 * @param string $name name of section
1537 * @param array $php_performance
1538 *
1539 * @return array
1540 *
1541 * Example:
1542 *
1543 * $php_performance = php_performance_START( 'emails_sending' , $php_performance );
1544 *
1545 * ... some code here ...
1546 *
1547 * $php_performance = php_performance_END( 'emails_sending' , $php_performance );
1548 *
1549 * echo 'Time of execution: ' . $php_performancep['emails_sending']
1550 *
1551 */
1552 function php_performance_START( $name, $php_performance ) {
1553
1554 if ( empty( $php_performance ) ) {
1555 $php_performance = array();
1556 }
1557
1558 $php_performance[ $name ] = microtime( true );
1559
1560 return $php_performance;
1561 }
1562
1563 /**
1564 * End calculation of time for execution of specific part of CODE
1565 *
1566 * @param string $name name of section
1567 * @param array $php_performance
1568 *
1569 * @return array
1570 *
1571 * Example:
1572 *
1573 * $php_performance = php_performance_START( 'emails_sending' , $php_performance );
1574 *
1575 * ... some code here ...
1576 *
1577 * $php_performance = php_performance_END( 'emails_sending' , $php_performance );
1578 *
1579 * echo 'Time of execution: ' . $php_performancep['emails_sending']
1580 *
1581 */
1582 function php_performance_END( $name, $php_performance ) {
1583
1584 if ( empty( $php_performance ) ) {
1585 $php_performance = array();
1586 }
1587 if ( empty( $php_performance[ $name ] ) ) {
1588 $php_performance[ $name ] = microtime( true );
1589 }
1590
1591 $php_performance[ $name ] = microtime( true ) - $php_performance[ $name ];
1592
1593 return $php_performance;
1594 }
1595
1596 /**
1597 * Set maximum number of seconds for execution.
1598 *
1599 * @param $limit_in_seconds_int
1600 *
1601 * @return void
1602 */
1603 function wpbc_set_limit_php( $limit_in_seconds_int = 300 ) {
1604
1605 WPBC_Action_Scheduler_Compatibility::raise_memory_limit();
1606 WPBC_Action_Scheduler_Compatibility::raise_time_limit( $limit_in_seconds_int );
1607 }
1608
1609
1610 // </editor-fold>