PluginProbe
Booking Calendar / 10.15.6
Booking Calendar v10.15.6
11.8.4 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 All 204 releases
booking / includes / page-bookings / bookings__sql.php

bookings__sql.php in Booking Calendar 10.15.6, at includes/page-bookings/bookings__sql.php

2,709 lines 118.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php /**
2 * @version 1.0
3 * @description Bookings Listing SQL
4 * @category Booking Listing
5 * @author wpdevelop
6 *
7 * @web-site http://oplugins.com/
8 * @email info@oplugins.com
9 *
10 * @modified 2022-04-07
11 * @file ../includes/page-bookings/bookings__sql.php
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
15
16 // <editor-fold defaultstate="collapsed" desc=" D E F A U L T R E Q U E S T " >
17
18 /**
19 * Get params names for escaping and/or default value of such params
20 *
21 * @param string $structure_type 'validate_and_default' (default) | 'validate' | 'default'
22 *
23 * @return array
24 * if $structure_type == '' array ( 'keyword' => array( 'validate' => 's', 'default' => '' )
25 * , 'wh_booking_date' => array( 'validate' => 'digit_or_date', 'default' => '3' ), ...
26 * if $structure_type == 'validate' array ( 'keyword' => 's'
27 * , 'wh_booking_date' => 'digit_or_date'), ...
28 * if $structure_type == 'default' array ( 'keyword' => '' )
29 * , 'wh_booking_date' => '3' ), ...
30 */
31 function wpbc_ajx_get__request_params__names_default( $structure_type = 'validate_and_default' ){
32
33 // Clean specific $_REQUEST params, if param is NOT set then return "default"
34 $params_for_cleaning = array(
35 // 'wh_booking_id' => array( 'validate' => 'digit_or_date', 'default' => '' ),
36
37 // 'digit_or_csd' can check about 'digit_or_csd' in arrays, as well
38 'wh_booking_type' => array( 'validate' => 'digit_or_csd', 'default' => array( '0' ) ) // if ['0'] - All booking resources, ['-1'] - lost bookings in deleted resources
39
40 , 'wh_approved' => array( 'validate' => 'digit_or_csd', 'default' => '' ) // '0' | '1' | ''
41
42 , 'wh_booking_date' => array( 'validate' => 'array', 'default' => array( "3" ) ) // array( "0" ) - Current dates, | array( "3" ) - All dates // number | date 2016-07-20
43 , 'ui_wh_booking_date_radio' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' ....
44 , 'ui_wh_booking_date_next' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' ....
45 , 'ui_wh_booking_date_prior' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' ....
46 , 'ui_wh_booking_date_checkin' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20
47 , 'ui_wh_booking_date_checkout' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20
48
49 , 'wh_what_bookings' => array( 'validate' => array( 'any', 'new', 'imported', 'in_plugin' ), 'default' => 'any' ) // '1' | ''
50
51 , 'wh_modification_date' => array( 'validate' => 'array', 'default' => array( "3" ) ) // number | date 2016-07-20
52 , 'ui_wh_modification_date_radio' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' ....
53 , 'ui_wh_modification_date_prior' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' ....
54 , 'ui_wh_modification_date_checkin' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20
55 , 'ui_wh_modification_date_checkout' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20
56
57 , 'keyword' => array( 'validate' => 's', 'default' => '' ) //string
58
59 , 'wh_pay_status' => array( 'validate' => 'array', 'default' => array( 'all' ) )
60 , 'ui_wh_pay_status_radio' => array( 'validate' => 's', 'default' => '' ) // string
61 , 'ui_wh_pay_status_custom' => array( 'validate' => 's', 'default' => '' ) // string
62
63 , 'wh_cost' => array( 'validate' => 'float_or_empty', 'default' => '' ) // '1' | ''
64 , 'wh_cost2' => array( 'validate' => 'float_or_empty', 'default' => '' ) // '1' | ''
65
66 , 'wh_sort' => array( 'validate' => array(
67 'booking_id__asc',
68 'booking_id__desc',
69 'dates__asc',
70 'dates__desc',
71 'resource__asc',
72 'resource__desc',
73 'cost__asc',
74 'cost__desc'
75 ), 'default' => 'booking_id__desc' )
76 , 'wh_trash' => array( 'validate' => array( '0', 'trash', 'any' ), 'default' => 'any' )
77
78 , 'page_num' => array( 'validate' => 'd', 'default' => 1 ) // '1' | ''
79 , 'page_items_count' => array( 'validate' => 'd', 'default' => 10 ) // '1' | ''
80
81 , 'ui_usr__send_emails' => array( 'validate' => array( 'send', 'not_send' ), 'default' => 'send' )
82 , 'ui_usr__is_expand_remarks' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' )
83 , 'ui_usr__default_selected_toolbar' => array( 'validate' => array( 'filters', 'actions', 'options' ), 'default' => 'filters' )
84
85 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
86 , 'ui_reset' => array( 'validate' => 's', 'default' => '' ) // string
87 , 'ui_usr__dates_short_wide' => array( 'validate' => array( 'short', 'wide' ), 'default' => 'short' )
88 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89 , 'view_days_num' => array( 'validate' => 'd', 'default' => 30 ) // '1' | '' // FixIn: 8.9.2.1.
90 , 'scroll_start_date' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20
91 , 'scroll_day' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
92 , 'scroll_month' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
93 , 'limit_hours' => array( 'validate' => 'digit_or_csd', 'default' => '' ) //
94 , 'only_booked_resources' => array( 'validate' => 'd', 'default' => 0 ) // '1' | ''
95
96 );
97
98 if ( 'validate_and_default' == $structure_type ) {
99 return $params_for_cleaning;
100 }
101
102 $return_simple_arr = array();
103
104 foreach ( $params_for_cleaning as $key => $value ) {
105 $return_simple_arr[ $key ] = $value[ $structure_type ];
106 }
107 return $return_simple_arr;
108 }
109
110 // </editor-fold>
111
112
113 // <editor-fold defaultstate="collapsed" desc=" S A V E U S E R R E Q U E S T " >
114
115 /**
116 * Save user filter request - saving user filters in toolbar
117 *
118 * @param array $params
119 * @param integer $user_id
120 *
121 * @return bool|int
122 */
123 function wpbc_ajx__user_request_params__save( $params, $user_id ) {
124
125 // Reset some parameters, like selected page
126 if ( isset( $params['page_num'] ) ) {
127 $params['page_num'] = 1;
128 $params['keyword'] = '';
129 }
130
131 return update_user_option( (int) $user_id, 'booking_listing_request_params' , $params );
132 }
133
134 /**
135 * Delete saved user request - used for resetting user filters in toolbar
136 * @param integer $user_id
137 *
138 * @return bool
139 */
140 function wpbc_ajx__user_request_params__delete( $user_id ) {
141
142 if ( empty( $user_id ) ) {
143 $user_id = wpbc_get_current_user_id();
144 }
145
146 return delete_user_option( (int) $user_id, 'booking_listing_request_params' );
147 }
148
149 /**
150 * Get saved user filter request - params for user filters in toolbar
151 *
152 * @param integer $user_id
153 *
154 * @return false|mixed
155 */
156 function wpbc_ajx__user_request_params__get( $user_id ) {
157
158 if ( empty( $user_id ) ) {
159 $user_id = wpbc_get_current_user_id();
160 }
161
162 // wpbc_ajx__user_request_params__delete($user_id); //For debugging. delete it.
163
164 return get_user_option( 'booking_listing_request_params', (int) $user_id );
165 }
166
167 /**
168 * Get sanitized array of use request parameters that was saved before
169 *
170 * @param $user_id int
171 *
172 * @return array|false
173 */
174 function wpbc_ajx__user_request_params__get_sanitized( $user_id ) {
175
176 $request_params_values_arr = wpbc_ajx__user_request_params__get( $user_id ); // - $request_params_values_arr - unserialized here automatically
177
178 if ( false !== $request_params_values_arr ) {
179
180 $request_params_structure = wpbc_ajx_get__request_params__names_default(); /**
181 * array( 'page_num' => array( 'validate' => 'd', 'default' => 1 )
182 * , 'page_items_count' => array( 'validate' => 'd', 'default' => 10 )
183 * , 'sort' => array( 'validate' => array( 'booking_id' ), 'default' => 'booking_id' )
184 * , 'sort_type' => array( 'validate' => array( 'ASC', 'DESC'),'default' => 'DESC' )
185 * , 'keyword' => array( 'validate' => 's', 'default' => '' )
186 * , 'create_date' => array( 'validate' => 'date', 'default' => '' )
187 * )
188 */
189
190 $escaped_request_params = wpbc_sanitize_params_in_arr( $request_params_values_arr, $request_params_structure ); // Escaping params here
191
192
193 return $escaped_request_params;
194 } else {
195 return false;
196 }
197 }
198
199 /**
200 * Get user saved option from Request in Booking Listing
201 *
202 * @param $user_id int 1
203 * @param $option_name string 'ui_usr__send_emails'
204 *
205 * @return false|mixed
206 */
207 function wpbc_ajx__user_request_params__get_option( $user_id, $option_name ){
208
209 // Get User saved option from request
210 $escaped_request_params = wpbc_ajx__user_request_params__get_sanitized( $user_id );
211 if ( ( ! empty( $escaped_request_params ) ) && ( ! empty( $escaped_request_params[ $option_name ] ) ) ) {
212 return $escaped_request_params[ $option_name ];
213 }
214
215 // Get default option
216 $default_param_values = wpbc_ajx_get__request_params__names_default( 'default' );
217 if ( ! empty( $default_param_values[ $option_name ] ) ) {
218 return $default_param_values[ $option_name ];
219 }
220
221 // There is no such option
222 return false;
223 }
224
225
226 /**
227 * Is send emails ? Check DB SAVED user defined option from Options toolbar.
228 * @param $user_id int ID of user
229 *
230 * @return int 1 | 0
231 */
232 function wpbc_ajx__user_request_option__is_send_emails( $user_id ){
233
234 $is_send_emeils = wpbc_ajx__user_request_params__get_option( $user_id, 'ui_usr__send_emails' );
235
236 $is_send_emeils = ( 'send' == $is_send_emeils ) ? 1 : 0;
237
238 return $is_send_emeils;
239 }
240
241 /**
242 * Is expand remarks by default ? Check DB SAVED user defined option from Options toolbar.
243 *
244 * It's useful only, when we are checking during Ajax action requests, where need to check data in Database,
245 * For templates, need to use JavaScript:
246 * <# if ( 'Off' === wpbc_ajx_booking_listing.search_get_param('ui_usr__is_expand_remarks') ) { #>display: none;<# } #>
247 *
248 *
249 * @param $user_id int ID of user
250 *
251 * @return int 1 | 0
252 */
253 function wpbc_ajx__user_request_option__is_expand_remarks( $user_id ){
254
255 $is_send_emeils = wpbc_ajx__user_request_params__get_option( $user_id, 'ui_usr__is_expand_remarks' );
256
257 $is_send_emeils = ( 'On' == $is_send_emeils ) ? 1 : 0;
258
259 return $is_send_emeils;
260 }
261
262
263 // </editor-fold>
264
265
266 // <editor-fold defaultstate="collapsed" desc=" S Q L " >
267
268
269 /**
270 * Get array of bookings and total number of items in all pages.
271 *
272 * @param array $request_params = Array(
273 [wh_booking_id] =>
274 [wh_booking_type] =>
275 [booking_type] =>
276 [wh_approved] =>
277 [wh_booking_date] =>
278 [wh_booking_date2] =>
279 [wh_booking_datenext] => 0
280 [wh_booking_dateprior] => 0
281 [wh_booking_datefixeddates] =>
282 [wh_booking_date2fixeddates] =>
283 [wh_is_new] => 0
284 [wh_modification_date] =>
285 [wh_modification_date2] =>
286 [wh_modification_dateprior] => 0
287 [wh_modification_datefixeddates] =>
288 [wh_modification_date2fixeddates] =>
289 [wh_pay_statuscustom] =>
290 [wh_pay_status] =>
291 [wh_cost] => 0
292 [wh_cost2] => 0
293 [wh_sort] =>
294 [wh_trash] =>
295 [page_num] => 1
296 [page_items_count] => 10
297 [view_days_num] => 30
298 [scroll_start_date] =>
299 [scroll_day] => 0
300 [scroll_month] => 0
301 [limit_hours] =>
302 [only_booked_resources] => 0
303 )
304 *
305 * @return array = Array(
306 [count] => 14
307 [data_arr] => Array (
308 [0] => Array (
309 [ajx_booking_id] => 14
310 [last_check_booking_id] => 0
311 [status] =>
312 [last_run_date] =>
313 [booking] => Array (
314 [email_template] => super_new
315 [conditions] => Array (
316 [0] => Array (
317 [if] => __system__|source
318 [sign] => >=
319 [value] => 1"0'0\0
320 )
321 ), ...
322 )
323 [ru_create_date] => 2020-01-25 10:36:55
324 ...
325 ), ...
326 */
327 function wpbc_ajx_get_booking_data_arr( $request_params ){
328
329 // 1. Get booking resources (sql)
330 $resources_arr = wpbc_ajx_get_all_booking_resources_arr(); /**
331 * Array ( [0] => Array ( [booking_type_id] => 1
332 [title] => Standard
333 [users] => 1
334 [import] =>
335 [export] =>
336 [cost] => 25
337 [default_form] => standard
338 [prioritet] => 0
339 [parent] => 0
340 [visitors] => 2
341 ), ... */
342
343 $resources_arr_sorted = wpbc_ajx_get_sorted_booking_resources_arr( $resources_arr );
344
345 // 2. Get all bookings (sql)
346 $bookings = wpbc_ajx_get__bookings_obj__sql( $request_params ); /**
347 * Array ( [count] => 172, [bookings] => Array (
348 * [0] => stdClass Object (
349 [booking_id] => 175
350 [trash] => 0
351 [sync_gid] =>
352 [is_new] => 1
353 [status] =>
354 [sort_date] => 2022-04-19 12:00:01
355 [modification_date] => 2022-04-03 08:05:13
356 [form] => selectbox-one^rangetime5^12:00 - 14:00~text^name5^test data~ ... ~checkbox^term_and_condition5[]^I Accept terms
357 [hash] => ae964965356f7c735139764eebe12a63
358 [booking_type] => 5
359 [remark] =>
360 [cost] => 50.00
361 [pay_status] => 164896951360.82
362 [pay_request] => 0
363 ), ....
364 */
365 $bookings_obj = $bookings['bookings'];
366 $bookings_count = $bookings['count'];
367
368
369 // 3. Get booking dates (sql)
370 $booking_dates_obj = wpbc_ajx_get__booking_dates_obj__sql( $bookings_obj ); /**
371 * Array ( [0] => stdClass Object (
372 [booking_dates_id] => 333
373 [booking_id] => 165
374 [booking_date] => 2022-03-28 11:00:01
375 [approved] => 0
376 [type_id] =>
377 )
378 [1] => ....
379 */
380
381
382 // 4. Include dates into bookings (Wide and Short dates view)
383 $bookings_with_dates = wpbc_ajx_include_bookingdates_in_the_bookings( $bookings_obj, $booking_dates_obj );
384 /**
385 Array ( [182] => stdClass Object (
386
387 [booking_db] => stdClass Object (
388 [booking_id] => 182
389 [trash] => 0
390 [sync_gid] =>
391 [is_new] => 1
392 [status] =>
393 [sort_date] => 2023-01-23 10:00:01
394 [modification_date] => 2022-04-18 12:23:30
395 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^name2^rr~text^secondname2^hjk~email^email2^hyui@nbco.csdf~text^phone2^h~text^address2^khj~text^city2^e~text^postcode2^hj~selectbox-one^country2^HT~selectbox-one^visitors2^1~selectbox-one^children2^0~textarea^details2^djkh~checkbox^term_and_condition2[]^I Accept term and conditions
396 [hash] => a1ae510d8fee961b7f8ae53101632151
397 [booking_type] => 2
398 [remark] =>
399 [cost] => 75.00
400 [pay_status] => 165028101080.84
401 [pay_request] => 0
402 )
403 [id] => 182
404 [approved] => 0
405 [dates] => Array (
406 [0] => 2023-01-23 10:00:01
407 [1] => 2023-01-25 00:00:00
408 [2] => 2023-01-27 12:00:02
409 )
410 [child_id] => Array (
411 [0] =>
412 [1] =>
413 [2] =>
414 )
415 [short_dates] => Array (
416 [0] => 2023-01-23 10:00:01
417 [1] => ,
418 [2] => 2023-01-25 00:00:00
419 [3] => ,
420 [4] => 2023-01-27 12:00:02
421 )
422 [short_dates_child_id] => Array (
423 [0] =>
424 [1] =>
425 [2] =>
426 [3] =>
427 [4] =>
428 )
429 )
430 [181] => stdClass Object ...
431 */
432
433 // 4.5 remove some bookings, that does not fit to Dates conditions
434 list( $bookings_with_dates, $bookings_count ) = wpbc_ajx_get__remove_bookings__where_dates_outside( $request_params, $bookings_with_dates, $bookings_count );
435
436 // 5. Parse forms
437 $parsed_bookings = wpbc_ajx_parse_bookings( $bookings_with_dates, $resources_arr );
438 /** array( [188] => stdClass Object (
439 [booking_db] => stdClass Object (
440 [booking_id] => 188
441 [trash] => 0
442 [sync_gid] =>
443 [is_new] => 1
444 [status] =>
445 [sort_date] => 2023-03-05 10:00:01
446 [modification_date] => 2022-04-19 11:58:31
447 [form] => text^selected_short_dates_hint4^March 5, 2023~text^days_number_hint4^1~text^cost_hint4^&amp;#36;95~selectbox-one^rangetime4^10:00 - 12:00~text^name4^test~email^email4^test@wpbookingcalendar.com~selectbox-one^my_select4^1~selectbox-multiple^multi_select4[]^0,1,2,3~checkbox^my_checkbx4[]^false~checkbox^my_multi_checkbx4[]^1~checkbox^my_multi_checkbx4[]^~checkbox^my_multi_checkbx4[]^3~checkbox^exclusive_multi_checkbx4^~checkbox^exclusive_multi_checkbx4^2~checkbox^exclusive_multi_checkbx4^~radio^my_radio4^2~selectbox-one^country4^GB~textarea^details4^s~checkbox^term_and_condition4[]^I Accept term and conditions
448 [hash] => dd12c3a61f14aaca693f52d110d2723a
449 [booking_type] => 4
450 [remark] =>
451 [cost] => 95.00
452 [pay_status] => 165036591118.88
453 [pay_request] => 0 )
454 [id] => 188
455 [approved] => 0
456 [dates] => Array ( [0] => 2023-03-05 10:00:01 [1] => 2023-03-05 12:00:02 )
457 [child_id] => Array([0] => [1] => )
458 [short_dates] => Array ( [0] => 2023-03-05 10:00:01 [1] => - [2] => 2023-03-05 12:00:02 )
459 [short_dates_child_id] => Array ( [0] => [1] => [2] => )
460 [form_data] => Array
461 (
462 [selected_short_dates_hint] => March 5, 2023
463 [days_number_hint] => 1
464 [cost_hint] => &amp;#36;95
465 [rangetime] => 10:00 AM - 12:00 PM
466 [name] => test
467 ...
468 [term_and_condition] => I Accept term and conditions
469 [booking_id] => 188
470 [trash] => 0
471 [sync_gid] =>
472 [is_new] => 1
473 [status] =>
474 [sort_date] => 2023-03-05 10:00:01
475 [modification_date] => 2022-04-19 11:58:31
476 [hash] => dd12c3a61f14aaca693f52d110d2723a
477 [booking_type] => 4
478 [cost] => 95.00
479 [pay_status] => 165036591118.88
480 [pay_request] => 0
481 [id] => 188
482 [approved] => 0
483 [resource_title] => Apartment#3
484 [_form_show] => "<div class="payment-content-form"><strong>Times</strong>:<span class="fieldvalue">10:00 AM - 12:00 PM</span>&nbsp;&nbsp; ...."
485 )
486 ...
487 */
488
489 // Reset array keys for correct DESC sorting during sending Ajax request.
490 $parsed_bookings = array_values( $parsed_bookings );
491
492 return array(
493 'booking_resources' => $resources_arr_sorted, //$resources_arr,
494 'data_arr' => $parsed_bookings,
495 'count' => $bookings_count
496 );
497 }
498
499 /**
500 * R E S O U R C E S - Get SORTED booking resources as array
501 *
502 * @param $resources_arr array Array ( [1] => Array (
503 [booking_type_id] => 1
504 [title] => Standard
505 [users] => 1
506 [import] =>
507 [export] =>
508 [cost] => 25
509 [default_form] => standard
510 [prioritet] => 0
511 [parent] => 0
512 [visitors] => 2
513 ), ...
514 *
515 * @return array
516 */
517 function wpbc_ajx_get_sorted_booking_resources_arr( $resources_arr ) {
518
519 if ( ! empty( $resources_arr ) ) {
520 $resources_arr_sorted = wpbc_ajx_arrange_booking_resources_arr( $resources_arr );
521 $resources_arr_sorted = $resources_arr_sorted['linear_resources'];
522 foreach ( $resources_arr_sorted as $key_id => $resource ) {
523 $resources_arr_sorted[ $key_id ]['title'] = wpbc_lang( $resources_arr_sorted[ $key_id ]['title'] );
524 }
525 // Reset keys for having correct sorting (important for parent/child resources) after ajax response
526 $resources_arr_sorted = array_values( $resources_arr_sorted );
527 } else {
528 $resources_arr_sorted = $resources_arr;
529 }
530
531 return $resources_arr_sorted;
532 }
533
534
535 /**
536 * R E S O U R C E S - Get all booking resources as array
537 *
538 * @return array Array ( [1] => Array (
539 [booking_type_id] => 1
540 [title] => Standard
541 [users] => 1
542 [import] =>
543 [export] =>
544 [cost] => 25
545 [default_form] => standard
546 [prioritet] => 0
547 [parent] => 0
548 [visitors] => 2
549 ), ...
550 */
551 function wpbc_ajx_get_all_booking_resources_arr( ){
552
553 if ( ! class_exists( 'wpdev_bk_personal' ) ) {
554 return array();
555 }
556
557 $db_names = wpbc_get_db_names();
558
559 $sql = array();
560
561 $sql['select'] = "SELECT * FROM {$db_names['resources']} as bt";
562
563 $sql['where'] = " WHERE ( 1 = 1 )";
564
565 if ( class_exists( 'wpdev_bk_multiuser' ) ) { // MultiUser - only specific booking resources for specific Regular User in Admin panel.
566
567 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
568 if ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) {
569 $user_bk_id = intval( $_REQUEST['wpbc_ajx_user_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
570 } else {
571 $user_bk_id = wpbc_get_current_user_id();
572 }
573 $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_bk_id );
574
575 if ( ! $is_user_super_admin ) {
576 $sql['where'] .= 'AND users = ' . $user_bk_id . ' ';
577 }
578 }
579
580 // Order depends from version // FixIn: 9.9.0.23.
581 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
582 $sql['order'] = " ORDER BY parent, prioritet, title, booking_type_id";
583 } else {
584 $sql['order'] = " ORDER BY title, booking_type_id";
585 }
586
587 global $wpdb;
588 $sql_prepared = //$wpdb->prepare(
589 $sql['select']
590 . $sql['where']
591 . $sql['order'];
592 // , $sql['sql_args']
593 // );
594 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
595 $resources = $wpdb->get_results( $sql_prepared );
596
597 $resources_arr = array();
598
599 foreach ( $resources as $resource ) {
600 $resources_arr[ $resource->booking_type_id ] = get_object_vars( $resource );
601 }
602
603 return $resources_arr;
604 }
605
606
607 /**
608 * Get arranged / sorted booking resources arrays
609 *
610 * @param $resources_sql_arr array( ...
611 * [4] => Array (
612 [booking_type_id] => 4
613 [title] => Apartment#3
614 [users] => 1
615 [import] =>
616 [export] =>
617 [cost] => 270
618 [default_form] => standard
619 [prioritet] => 1
620 [parent] => 0
621 [visitors] => 1
622 )
623 [5] => Array (
624 [booking_type_id] => 5
625 [title] => Standard-1
626 [users] => 1
627 [import] =>
628 [export] =>
629 [cost] => 25
630 [default_form] => standard
631 [prioritet] => 1
632 [parent] => 1
633 [visitors] => 1
634 )
635 ...
636 */
637 function wpbc_ajx_arrange_booking_resources_arr( $all_resources ){
638
639 if ( count( $all_resources ) > 0 ) {
640
641 $resources = array();
642 $child_resources = array();
643 $parent_single_resources = array();
644
645 foreach ( $all_resources as $single_resources ) {
646
647 $single_resources = $single_resources ;
648 $single_resources['id'] = $single_resources['booking_type_id'];
649
650 // Child booking resource
651 if ( ( ! empty( $single_resources[ 'parent' ] ) )
652 ){ // Child
653
654 if ( ! isset( $child_resources[ $single_resources['parent'] ] ) )
655 $child_resources[ $single_resources['parent'] ] = array();
656
657 $child_resources[ $single_resources['parent'] ][ $single_resources['id'] ] = $single_resources;
658
659 } else { // Parent or Single
660
661 $parent_single_resources[ $single_resources['id'] ] = $single_resources;
662 }
663 // All resources
664 $resources[ $single_resources['id'] ] = $single_resources;
665 }
666
667
668 $final_resource_array = array();
669 foreach ( $parent_single_resources as $key => $res) {
670
671 // Calc Capacity
672 if ( isset( $child_resources[$res['id']] ) ) $res['count'] = count( $child_resources[$res['id']] ) + 1;
673 else $res['count'] = 1;
674
675 // Fill the parent resource
676 $final_resource_array[ $res['id'] ] = $res;
677
678 // Fill all child resources (its already sorted) - for having linear array with child resourecs.
679 if ( isset( $child_resources[ $res['id'] ] ) ) {
680 foreach ( $child_resources[ $res['id'] ] as $child_obj ) {
681 $child_obj['count'] = 1;
682 $final_resource_array[ $child_obj['id'] ] = $child_obj;
683 }
684 }
685 }
686
687 return array(
688 'linear_resources' => $final_resource_array
689 , 'single_or_parent' => $parent_single_resources
690 , 'child' => $child_resources
691 );
692 } else {
693 return false;
694 }
695 }
696
697
698 /**
699 * S Q L - B O O K I N G S - Get array of "Bookings" objects from DB
700 * based on request params
701 *
702 * @param array $request_params
703 *
704 * @return array of bookings sql objects
705 */
706 function wpbc_ajx_get__bookings_obj__sql( $request_params ) {
707
708 $defaults = wpbc_ajx_get__request_params__names_default( 'default' );
709
710 $params = wp_parse_args( $request_params, $defaults );
711
712 global $wpdb;
713 $db_names = wpbc_get_db_names();
714
715 $sql_args = array();
716 $sql = array();
717
718
719 $sql['start_select'] = " SELECT * ";
720 $sql['start_count'] = " SELECT COUNT(*) as count";
721 $sql['from'] = " FROM {$db_names['bookings']} as bk";
722
723 $sql['where'] = " WHERE ( 1 = 1 )";
724
725 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
726 // DATES
727 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
728 $sql['where'] .= " AND ( EXISTS (
729 SELECT *
730 FROM {$db_names['dates']} as dt
731 WHERE bk.booking_id = dt.booking_id ";
732
733 // W H E R E : Approved | Pending ----------------------------------------------------------------------
734 if ( $request_params['wh_approved'] !== '' ) {
735 $sql['where'] .= " AND approved = {$request_params['wh_approved']} ";
736 }
737
738 // W H E R E : D A T E S --------------------------------------------------------------------------------
739 if (1){
740 if ( is_array( $request_params['wh_booking_date'] ) ) {
741 $wh_booking_date = array_replace( array( '', '' ), $request_params['wh_booking_date'] ); // Always have minimum 2 values in arr
742 } else {
743 $wh_booking_date = array( '', '' );
744 }
745
746 if ( count( $wh_booking_date ) > 2 ) {
747 $removed_el = array_shift( $wh_booking_date ); // Remove an element off the beginning of array
748 }
749 }
750 $sql['where'] .= wpbc_ajx__sql_where_for_dates( (string) $wh_booking_date[0], (string) $wh_booking_date[1] );
751
752 $sql['where'] .= " )
753 )";
754 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
755
756
757 // W H E R E : M o d i f i c a t i o n D A T E S --------------------------------------------------
758 if (1){
759 if ( is_array( $request_params['wh_modification_date'] ) ) {
760 $wh_modification_date = array_replace( array( '', '' ), $request_params['wh_modification_date'] ); // Always have minimum 2 values in arr
761 } else {
762 $wh_modification_date = array( '', '' );
763 }
764
765 if ( count( $wh_modification_date ) > 2 ) {
766 $removed_el = array_shift( $wh_modification_date ); // Remove an element off the beginning of array
767 }
768 }
769 $sql['where'] .= wpbc_ajx__sql_where_for_modification_date( (string) $wh_modification_date[0], (string) $wh_modification_date[1] );
770
771
772
773 // W H E R E : Resources ------------------------------------------------------------------------------
774 if ( class_exists( 'wpdev_bk_personal' ) ) {
775
776 if ( ! empty( $request_params['wh_booking_type'] ) ) {
777
778 $sql['where'] .= wpbc_ajx__sql_where_for_resources(
779 $request_params['wh_booking_type'],
780 $request_params['wh_approved'],
781 (string) $wh_booking_date[0],
782 (string) $wh_booking_date[1]
783 );
784 }
785 }
786
787
788 // W H E R E : Payment Status -------------------------------------------------------------------------
789 if ( class_exists( 'wpdev_bk_biz_s' ) ) {
790
791 if ( ! empty( $request_params['wh_pay_status'] ) ) {
792
793 $sql_and_args = wpbc_ajx__sql_where_for_payment_status( $request_params['wh_pay_status'] );
794
795 $sql['where'] .= $sql_and_args[0];
796
797 if ( count( $sql_and_args[1] ) > 0 ) {
798 foreach ( $sql_and_args[1] as $my_arg ) {
799 $sql_args[] = $my_arg;
800 }
801 }
802
803 }
804 }
805
806
807 // W H E R E : C o s t Min - Max -------------------------------------------------------------------
808 if ( class_exists( 'wpdev_bk_biz_s' ) ) {
809
810 if ( ( isset( $request_params['wh_cost'] ) )
811 || ( isset( $request_params['wh_cost2'] ) ) ) {
812
813 $wh_cost_min = ( isset( $request_params['wh_cost'] ) ) ? $request_params['wh_cost'] : '';
814 $wh_cost_max = ( isset( $request_params['wh_cost2'] ) ) ? $request_params['wh_cost2'] : '';
815
816 $sql_and_args = wpbc_ajx__sql_where_cost_min_max( $wh_cost_min, $wh_cost_max );
817
818 $sql['where'] .= $sql_and_args[0];
819
820 if ( count( $sql_and_args[1] ) > 0 ) {
821 foreach ( $sql_and_args[1] as $my_arg ) {
822 $sql_args[] = $my_arg;
823 }
824 }
825
826 }
827 }
828
829
830
831 // W H E R E : Trash -----------------------------------------------------------------------------------
832 if ( isset( $request_params['wh_trash'] ) ) {
833
834 if ( '0' === $request_params['wh_trash'] ) { // Existing
835 $sql['where'] .= " AND bk.trash = 0 ";
836 }
837
838 if ( 'trash' === $request_params['wh_trash'] ) { // In trash
839 $sql['where'] .= " AND bk.trash = 1 ";
840 }
841
842 //if ( 'any' === $request_params['wh_trash'] ) { } // Any
843 }
844
845
846 // W H E R E : All bookings | New bookings | Imported bookings | Plugin bookings
847 if ( isset( $request_params['wh_what_bookings'] ) ) {
848
849 if ( 'any' === $request_params['wh_what_bookings'] ) {
850 //$sql['where'] .= " AND bk.is_new = 0 ";
851 }
852 if ( 'new' === $request_params['wh_what_bookings'] ) {
853 $sql['where'] .= " AND bk.is_new = 1";
854 }
855 if ( 'imported' === $request_params['wh_what_bookings'] ) {
856 $sql['where'] .= " AND bk.sync_gid != '' ";
857 }
858 if ( 'in_plugin' === $request_params['wh_what_bookings'] ) {
859 $sql['where'] .= " AND bk.sync_gid = '' ";
860 }
861 }
862
863
864 // W H E R E : K E Y W O R D
865 if ( ! empty( $params['keyword'] ) ) {
866 $sql['where'] .= " AND ( ";
867
868 /**
869 * Relative configuration of LIKE sanitization
870 * check at the bottom here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536
871 *
872 * So this is a correct way:
873 *
874 * $sql['where'] .= "( bk.form LIKE %s ) ";
875 * $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%';
876 *
877 */
878
879 $sql['where'] .= "( bk.form LIKE %s ) ";
880 $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%';
881
882 if ( is_numeric( $params['keyword'] ) ) {
883 $sql['where'] .= " OR ( bk.booking_id = %d ) ";
884 $sql_args[] = intval( $params['keyword'] );
885 }
886
887 $sql['where'] .= " OR ( bk.sync_gid LIKE %s ) ";
888 $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%';
889
890 if ( class_exists( 'wpdev_bk_personal' ) ) {
891 $sql['where'] .= " OR ( bk.remark LIKE %s ) ";
892 $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%';
893
894 $sql['where'] .= " OR ( bk.hash LIKE %s ) ";
895 $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%';
896 }
897
898 $sql['where'] .= " )";
899
900
901 // W H E R E : booking ID // FixIn: 9.4.3.9.
902 $is_id = strpos( trim( strtolower( $params['keyword'] ) ) , 'id:' ); // Keyword, like 'id:200' OR 'id:100,105'
903 if ( 0 === $is_id ){
904
905 $search_booking_id = substr( trim( $params['keyword'] ), 3 );
906 $search_booking_id_arr = explode( ',', $search_booking_id ); // Get array of booking ID: from 'id:200,201,15' we get [200,201,15]
907
908 $sql_where_arr = array();
909 $sql_args = array(); // It's last WHERE in a list so all previous arguments ($sql_args) we are resetting
910
911 foreach ( $search_booking_id_arr as $bk_id ) {
912
913 $sql_where_arr[] = ' bk.booking_id = %d ';
914 $sql_args[] = intval( $bk_id );
915 }
916
917 $sql['where'] = " WHERE ( " . implode( ' OR ', $sql_where_arr ) . ") ";
918
919 $sql['where'] = apply_bk_filter('update_where_sql_for_getting_bookings_in_multiuser', $sql['where'] ); // Add 'AND bk.booking_type IN ( $user_resources )' to the end of Where
920 }
921 }
922
923 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
924
925
926 switch ( $params['wh_sort'] ) {
927 case 'booking_id__asc':
928 $order_by = 'booking_id ASC ';
929 break;
930 case 'booking_id__desc':
931 $order_by = 'booking_id DESC ';
932 break;
933 case 'dates__asc':
934 $order_by = 'sort_date ASC ';
935 break;
936 case 'dates__desc':
937 $order_by = 'sort_date DESC ';
938 break;
939 case 'resource__asc':
940 $order_by = 'booking_type ASC ';
941 break;
942 case 'resource__desc':
943 $order_by = 'booking_type DESC ';
944 break;
945 case 'cost__asc':
946 $order_by = 'cost ASC ';
947 break;
948 case 'cost__desc':
949 $order_by = 'cost DESC ';
950 break;
951 default:
952 $order_by = 'booking_id ASC ';
953 }
954 $sql['order'] = " ORDER BY bk." . $order_by; // $sql['order'] = " ORDER BY bk." . esc_sql( $params['sort'] ) . ( ( 'DESC' == $params['sort_type'] ) ? " DESC " : " ASC " );
955
956 $sql_args_count = $sql_args; // For SELECT COUNT(*) as count we do not need other parameters
957
958 $sql['limit'] = " LIMIT %d, %d ";
959
960 $sql_args[] = ( $params['page_num'] - 1 ) * $params['page_items_count'];
961 $sql_args[] = $params['page_items_count'];
962
963
964
965 /**
966 * Good Practice: https://blog.ircmaxell.com/2017/10/disclosure-wordpress-wpdb-sql-injection-technical.html
967 * fixed in WordPress 4.8.3
968 *
969 $where = "WHERE foo = %s";
970 $args = [$_GET['data']];
971 $args[] = 1;
972 $args[] = 2;
973 $query = $wpdb->prepare("SELECT * FROM something $where LIMIT %d, %d", $args);
974 *
975 */
976
977 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
978 // SELECT at this specific PAGE /////////////////////////////////////////////////////////////////
979 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
980 /* phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare */
981 $sql_prepared = $wpdb->prepare( $sql['start_select'] . $sql['from'] . $sql['where'] . $sql['order'] . $sql['limit'], $sql_args );
982 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
983 $bookings_sql_obj = $wpdb->get_results( $sql_prepared );
984
985
986 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
987 // COUNT of items with this WHERE ///////////////////////////////////////////////////////////////////
988 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
989 $sql_for_listing_count = $sql['start_count']
990 . $sql['from']
991 . $sql['where'];
992
993 if ( false === strpos( $sql_for_listing_count, '%' ) ) {
994
995 $sql_prepared = $sql_for_listing_count;
996
997 } else {
998 /* phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare */
999 $sql_prepared = $wpdb->prepare( $sql_for_listing_count, $sql_args_count );
1000 }
1001 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1002 $bookings_count = $wpdb->get_results( $sql_prepared );
1003 $bookings_count = ( ( count( $bookings_count ) > 0 ) ? $bookings_count[0]->count : 0 );
1004
1005 return array(
1006 'count' => $bookings_count
1007 , 'bookings' => $bookings_sql_obj
1008 );
1009 }
1010
1011 // W H E R E C O N D I T I O N S
1012
1013 /**
1014 * Get SQL W H E R E conditions for D a t e s of bookings
1015 *
1016 * @param string $wh_booking_date - Parameter from Booking Listing request (usually its number)
1017 * @param string $wh_booking_date2 - Parameter from Booking Listing request (usually its number)
1018 * @param string $pref - Optional. Prefix for table.
1019 * @return string - WHERE conditions for SQL
1020 */
1021 function wpbc_ajx__sql_where_for_dates( $wh_booking_date, $wh_booking_date2, $pref = 'dt.' ) {
1022
1023 $wh_booking_date = (string) $wh_booking_date;
1024 $wh_booking_date2 = (string) $wh_booking_date2;
1025
1026 $sql_where= '';
1027 if ($pref == 'dt.') { $and_pre = ' AND '; $and_suf = ''; }
1028 else { $and_pre = ''; $and_suf = ' AND '; }
1029
1030 // Actual
1031 if ( ( ( $wh_booking_date === '' ) && ( $wh_booking_date2 === '' ) ) || ($wh_booking_date === '0') ) {
1032 $sql_where = $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.5.2.14.
1033
1034 } else if ($wh_booking_date === '1') { // Today // FixIn: 7.1.2.8.
1035 $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '23:59:59' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ;
1036 $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.4.7.21.
1037
1038
1039 } else if ($wh_booking_date === '2') { // Previous
1040 $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.5.2.16.
1041
1042 } else if ($wh_booking_date === '3') { // All
1043 $sql_where = '';
1044
1045 } else if ($wh_booking_date === '4') { // Next
1046 $wh_booking_date2 = intval( $wh_booking_date2 ); // FixIn: 10.14.16.1.
1047 $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL ". $wh_booking_date2 . " DAY", 'curdate' ) . ") ) ".$and_suf ;
1048 // $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1049 $sql_where .= $and_pre."( ".$pref."booking_date > ( " . wpbc_sql_date_math_expr_explicit('', 'curdate') . " ) ) ".$and_suf ; // FixIn: 8.0.1.1.
1050
1051 } else if ($wh_booking_date === '5') { // Prior
1052 $wh_booking_date2 = str_replace('-', '', $wh_booking_date2);
1053 $wh_booking_date2 = intval( $wh_booking_date2 ); // FixIn: 10.14.16.1.
1054 $sql_where = $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL ". $wh_booking_date2 . " DAY", 'curdate' ) . ") ) ".$and_suf ;
1055 $sql_where .= $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1056
1057 } else if ($wh_booking_date === '7') { // Check In date - Today/Tomorrow
1058 $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '47:59:59' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ;
1059 $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1060
1061 } else if ($wh_booking_date === '8') { // Check Out date - Tomorrow
1062 $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '47:59:59' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ;
1063 $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1064
1065 } else if ( ( $wh_booking_date === '9' ) || ( $wh_booking_date === '10' ) || ( $wh_booking_date === '11' ) ) { // Today check in/out
1066 $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1067 $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1068
1069 } else { // Fixed
1070
1071 $wh_booking_date = wpbc_sanitize_date( $wh_booking_date );
1072 $wh_booking_date2 = wpbc_sanitize_date( $wh_booking_date2 );
1073
1074 /*
1075 if ( $wh_booking_date !== '' ){
1076 $sql_where .= $and_pre . "( " . $pref . "booking_date >= ( '" . $wh_booking_date . "' - INTERVAL '00:00:01' HOUR_SECOND ) ) " . $and_suf;
1077 }
1078 if ( $wh_booking_date2 !== '' ) {
1079 $sql_where .= $and_pre . "( " . $pref . "booking_date <= ( '" . $wh_booking_date2 . "' + INTERVAL '23:59:59' HOUR_SECOND ) ) " . $and_suf;
1080 }
1081 */
1082
1083 if ( $wh_booking_date !== '' ) {
1084 if ( strpos( $wh_booking_date, ':' ) === false ) {
1085 $sql_where .= $and_pre . "( " . $pref . "booking_date >= '" . $wh_booking_date . " 00:00:00' ) " . $and_suf;
1086 } else {
1087 $sql_where .= $and_pre . "( " . $pref . "booking_date >= '" . $wh_booking_date . "' ) " . $and_suf;
1088 }
1089 }
1090
1091 if ( $wh_booking_date2 !== '' ) {
1092 if ( strpos( $wh_booking_date2, ':' ) === false ) {
1093 $sql_where .= $and_pre . "( " . $pref . "booking_date <= '" . $wh_booking_date2 . " 23:59:59' ) " . $and_suf;
1094 } else {
1095 $sql_where .= $and_pre . "( " . $pref . "booking_date <= '" . $wh_booking_date2 . "' ) " . $and_suf;
1096 }
1097 }
1098
1099
1100 }
1101
1102 return $sql_where;
1103 }
1104
1105
1106 /**
1107 * Get SQL W H E R E conditions for M o d i f i c a t i o n D a t e of bookings
1108 *
1109 * @param string $wh_modification_date - Parameter from Booking Listing request (usually its number)
1110 * @param string $wh_modification_date2 - Parameter from Booking Listing request (usually its number)
1111 * @param string $pref - Optional. Prefix for table.
1112 * @return string - WHERE conditions for SQL
1113 */
1114 function wpbc_ajx__sql_where_for_modification_date( $wh_modification_date, $wh_modification_date2, $pref = 'bk.' ) {
1115
1116 $sql_where = '';
1117
1118 if ($pref == 'bk.') { $and_pre = ' AND '; $and_suf = ''; }
1119 else { $and_pre = ''; $and_suf = ' AND '; }
1120
1121 if ($wh_modification_date === '1') { // Today
1122 $sql_where = $and_pre."( ".$pref."modification_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '23:59:59' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.4.7.22.
1123 $sql_where .= $and_pre."( ".$pref."modification_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.4.7.22.
1124
1125 } else if ($wh_modification_date === '3') { // All
1126 $sql_where = '';
1127
1128 } else if ($wh_modification_date === '5') { // Prior
1129 $wh_modification_date2 = str_replace('-', '', $wh_modification_date2);
1130 $wh_modification_date2 = intval( $wh_modification_date2 ); // FixIn: 10.14.16.1.
1131 $sql_where = $and_pre."( ".$pref."modification_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL ". $wh_modification_date2 . " DAY", 'curdate' ) . ") ) ".$and_suf ;
1132 $sql_where .= $and_pre."( ".$pref."modification_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1133
1134 } else { // Fixed
1135
1136 $wh_modification_date = wpbc_sanitize_date( $wh_modification_date ); // FixIn: 9.4.4.1.
1137 $wh_modification_date2 = wpbc_sanitize_date( $wh_modification_date2 );
1138
1139 if ( $wh_modification_date !== '' )
1140 $sql_where.= $and_pre."( ".$pref."modification_date >= ( '" . $wh_modification_date . "' - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf;
1141
1142 if ( $wh_modification_date2 !== '' )
1143 $sql_where.= $and_pre."( ".$pref."modification_date <= ( '" . $wh_modification_date2 . "' + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf;
1144 }
1145
1146 return $sql_where;
1147 }
1148
1149
1150 /**
1151 * Get SQL W H E R E conditions for B o o k i n g R e s o u r c e s
1152 *
1153 * @param $wh_booking_type
1154 * @param $wh_approved
1155 * @param $wh_booking_date
1156 * @param $wh_booking_date2
1157 *
1158 * @return string - SQL
1159 */
1160 function wpbc_ajx__sql_where_for_resources( $wh_booking_type, $wh_approved, $wh_booking_date, $wh_booking_date2 ){
1161 global $wpdb;
1162
1163 if ( ! class_exists( 'wpdev_bk_personal' ) ) {
1164 return '';
1165 }
1166
1167 if ( is_array( $wh_booking_type ) ) {
1168 $wh_booking_type = implode( ',', $wh_booking_type );
1169 }
1170
1171 $sql_where = '';
1172
1173 if ( '0' === $wh_booking_type ) { // All booking resources
1174 // Get all booking resources of this user
1175 $resources_sql_arr = wpbc_ajx_get_all_booking_resources_arr();
1176 $wh_booking_type = implode( ',', array_keys( $resources_sql_arr ) );
1177 //$resources_arr = wpbc_ajx_arrange_booking_resources_arr( $resources_sql_arr );
1178 }
1179
1180 if ( '-1' === $wh_booking_type ) { // Lost booking resources
1181
1182 $is_show_lost = true;
1183
1184 if ( class_exists( 'wpdev_bk_multiuser' ) ) { // MultiUser - Only for super booking admin user
1185
1186 $user_bk_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
1187
1188 $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_bk_id );
1189
1190 if ( ! $is_user_super_admin ) {
1191 $is_show_lost = false; // For regular user show all bookings from the booking resources that belong to this user.
1192 $sql_where .= " AND bk.booking_type IN ( SELECT DISTINCT booking_type_id FROM {$wpdb->prefix}bookingtypes WHERE users = " . $user_bk_id . " ) ";
1193 }
1194 }
1195
1196 // "Lost" bookings in deleted booking resources
1197 if ( $is_show_lost ) {
1198 $sql_where .= " AND bk.booking_type NOT IN ( SELECT DISTINCT booking_type_id FROM {$wpdb->prefix}bookingtypes ) ";
1199 }
1200
1201 } else if ( ! empty( $wh_booking_type ) ) {
1202 // P
1203 $sql_where .= " AND ( ";
1204 $sql_where .= " ( bk.booking_type IN ( " . $wh_booking_type . " ) ) ";
1205
1206 // BL - Show bookings from child booking resources, if was selected only parent booking resource
1207 $is_show_bookings_for_child_resources = true;
1208 if ( $is_show_bookings_for_child_resources ) {
1209 $sql_where .= wpbc_ajx__sql_where_for_resources_bl( $wh_booking_type, $wh_approved, $wh_booking_date, $wh_booking_date2 );
1210 }
1211
1212 // P
1213 $sql_where .= " ) ";
1214
1215 // MU - Check if searching bookings are belongs to specific user in Booking Calendar MultiUser version
1216 $sql_where = apply_bk_filter( 'update_where_sql_for_getting_bookings_in_multiuser', $sql_where );
1217 }
1218
1219 return $sql_where;
1220 }
1221
1222
1223 /**
1224 * Get SQL W H E R E conditions for B o o k i n g R e s o u r c e s BL - Capacity
1225 *
1226 * @param $wh_booking_type
1227 * @param $wh_approved
1228 * @param $wh_booking_date
1229 * @param $wh_booking_date2
1230 *
1231 * @return string - SQL
1232 */
1233 function wpbc_ajx__sql_where_for_resources_bl( $wh_booking_type, $wh_approved, $wh_booking_date, $wh_booking_date2 ){
1234
1235 if ( ! class_exists( 'wpdev_bk_biz_l' ) ) {
1236 return '';
1237 }
1238
1239 global $wpdb;
1240 $sql_where = '';
1241
1242 // BL // Childs in dif sub resources
1243 $sql_where.= " OR ( bk.booking_id IN (
1244 SELECT DISTINCT booking_id
1245 FROM {$wpdb->prefix}bookingdates as dtt
1246 WHERE " ;
1247 if ($wh_approved !== '')
1248 $sql_where.= " dtt.approved = $wh_approved AND " ;
1249 $sql_where .= wpbc_ajx__sql_where_for_dates( $wh_booking_date, $wh_booking_date2, 'dtt.' );
1250
1251 $sql_where.= " (
1252 dtt.type_id IN ( ". $wh_booking_type ." )
1253 OR dtt.type_id IN (
1254 SELECT booking_type_id
1255 FROM {$wpdb->prefix}bookingtypes as bt
1256 WHERE bt.parent IN ( ". $wh_booking_type ." )
1257 )
1258 )
1259 )
1260 ) " ;
1261
1262 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
1263 if ( ( isset($_REQUEST['tab']) ) && ( $_REQUEST['tab']== 'vm_calendar' ) ) {
1264
1265 // Skip the bookings from the children resources, if we are in the Calendar view mode at the admin panel
1266
1267 } else {
1268 // BL // Just children booking resources
1269 $sql_where .= " OR ( bk.booking_type IN (
1270 SELECT booking_type_id
1271 FROM {$wpdb->prefix}bookingtypes as bt
1272 WHERE bt.parent IN ( " . $wh_booking_type . " )
1273 )
1274 )";
1275 }
1276
1277 return $sql_where;
1278 }
1279
1280
1281 /**
1282 * Get SQL W H E R E conditions for P a y m e n t S t a t u s
1283 *
1284 * @param $wh_pay_status [ 'any ' ] | ['group_ok'] | ['group_unknown' ] | ['group_pending'] | ['group_failed'] | [ 'user_entered', 'myCustom status' ]
1285 *
1286 * @return array [ string SQL, array ARGS ]
1287 */
1288 function wpbc_ajx__sql_where_for_payment_status( $wh_pay_status_arr ){
1289
1290 // [ 'any ' ] | ['group_ok'] | ['group_unknown' ] | ['group_pending'] | ['group_failed'] | [ 'user_entered', 'myCustom status' ]
1291
1292 $wh_pay_status_custom = '';
1293 $wh_pay_status = '';
1294
1295 if ( ! empty( $wh_pay_status_arr ) ) {
1296
1297 if ( count( $wh_pay_status_arr ) > 1 ) {
1298 $wh_pay_status_custom = $wh_pay_status_arr[1];
1299 }
1300 $wh_pay_status = $wh_pay_status_arr[0];
1301 }
1302
1303 $sql_where = '';
1304 $sql_args = array();
1305
1306 if ( ( '' != $wh_pay_status ) && ( 'all' != $wh_pay_status ) ) {
1307
1308 $sql_where .= " AND ( ";
1309
1310 // Check firstly if we are selected some goup of payment status
1311 if ( $wh_pay_status == 'group_ok' ) { // SUCCESS
1312
1313 $payment_status = wpbc_get_payment_status_ok();
1314
1315 foreach ( $payment_status as $label ) {
1316 $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR";
1317 }
1318 $sql_where = substr( $sql_where, 0, - 2 );
1319
1320 } else if ( ( $wh_pay_status == 'group_unknown' ) || ( is_numeric( $wh_pay_status_custom ) ) ) { // UNKNOWN
1321
1322 $payment_status = wpbc_get_payment_status_unknown();
1323 foreach ( $payment_status as $label ) {
1324 $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR";
1325 }
1326 //$sql_where = substr($sql_where, 0, -2);
1327 $sql_where .= " ( bk.pay_status = '' ) OR ( bk.pay_status regexp '^[0-9]') ";
1328
1329 } else if ( $wh_pay_status == 'group_pending' ) { // Pending
1330
1331 $payment_status = wpbc_get_payment_status_pending();
1332 foreach ( $payment_status as $label ) {
1333 $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR";
1334 }
1335 $sql_where = substr( $sql_where, 0, - 2 );
1336
1337 } else if ( $wh_pay_status == 'group_failed' ) { // Failed
1338
1339 $payment_status = wpbc_get_payment_status_error();
1340 foreach ( $payment_status as $label ) {
1341 $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR";
1342 }
1343 $sql_where = substr( $sql_where, 0, - 2 );
1344
1345 } else { // CUSTOM Payment Status
1346 $sql_where .= " bk.pay_status = %s ";
1347
1348 // $wh_pay_status_custom = htmlspecialchars_decode( $wh_pay_status_custom ); // ? Convert special HTML entities back to characters: "&#60; - &#62;" to "< - >"
1349 $sql_args[] = $wh_pay_status_custom;
1350 }
1351
1352 $sql_where .= " ) ";
1353 }
1354
1355 return array( $sql_where, $sql_args );
1356 }
1357
1358
1359 /**
1360 * Get SQL W H E R E conditions for C o s t Min - Max
1361 *
1362 * @param $wh_cost_min '' or number
1363 * @param $wh_cost_max '' or number
1364 *
1365 * @return array [ string SQL, array ARGS ]
1366 */
1367 function wpbc_ajx__sql_where_cost_min_max( $wh_cost_min, $wh_cost_max ) {
1368
1369 $sql_where = '';
1370 $sql_args = array();
1371
1372 if ( $wh_cost_min !== '' ) {
1373 $sql_where .= " AND ( bk.cost >= %f ) ";
1374 $sql_args[] = $wh_cost_min;
1375 }
1376 if ( $wh_cost_max !== '' ) {
1377 $sql_where .= " AND ( bk.cost <= %f ) ";
1378 $sql_args[] = $wh_cost_max;
1379 }
1380
1381 return array( $sql_where, $sql_args );
1382
1383 }
1384
1385
1386 /**
1387 * D A T E S - Get array of "Booking Dates" objects from DB
1388 * relative to specific bookings - array of Bookings objects from DB
1389 *
1390 * @param array of object $bookings_sql_obj
1391 *
1392 * @return array of booking dates sql objects
1393 */
1394 function wpbc_ajx_get__booking_dates_obj__sql( $bookings_sql_obj ){
1395
1396 global $wpdb;
1397 $db_names = wpbc_get_db_names();
1398
1399 // Get list of booking ID from bookings obj ///////////////////////////////////////////////////////////////
1400 $booking_id_list = array();
1401 foreach ( $bookings_sql_obj as $booking ) {
1402 $booking_id_list[] = intval( $booking->booking_id );
1403 }
1404 $booking_id_list = array_unique( $booking_id_list ); // remove duplicates
1405 $booking_id_list = implode( ",", $booking_id_list );
1406 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1407
1408
1409 if ( ! empty( $booking_id_list ) ) { // Get Dates for all our Bookings
1410
1411 $sql = "SELECT *
1412 FROM {$db_names['dates']} as dt
1413 WHERE dt.booking_id in ( {$booking_id_list} ) ";
1414
1415 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1416 $sql .= " ORDER BY booking_id, type_id, booking_date ";
1417 } else {
1418 $sql .= " ORDER BY booking_id, booking_date ";
1419 }
1420 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1421 $booking_dates_sql_obj = $wpdb->get_results( $sql );
1422 } else {
1423 $booking_dates_sql_obj = array();
1424 }
1425
1426 return $booking_dates_sql_obj;
1427 }
1428
1429
1430 /**
1431 * S Q L - B O O K I N G S - Get array of "Bookings" objects from DB
1432 * based on request params
1433 *
1434 * @param array $request_params
1435 * @param array of object $bookings_sql_obj
1436 *
1437 * @return array of array( booking dates, $bookings_count) array( sql objects, int )
1438 */
1439 function wpbc_ajx_get__remove_bookings__where_dates_outside($request_params, $bookings_obj, $bookings_count){
1440
1441 $is_id = strpos( trim( strtolower( $request_params['keyword'] ) ) , 'id:' );
1442 if ( false !== $is_id ) {
1443 return array( $bookings_obj, $bookings_count );
1444 }
1445 // W H E R E : D A T E S --------------------------------------------------------------------------------
1446 if (1){
1447 if ( is_array( $request_params['wh_booking_date'] ) ) {
1448 $wh_booking_date_arr = array_replace( array( '', '' ), $request_params['wh_booking_date'] ); // Always have minimum 2 values in arr
1449 } else {
1450 $wh_booking_date_arr = array( '', '' );
1451 }
1452
1453 if ( count( $wh_booking_date_arr ) > 2 ) {
1454 $removed_el = array_shift( $wh_booking_date_arr ); // Remove an element off the beginning of array
1455 }
1456 }
1457
1458 $wh_booking_date = (string) $wh_booking_date_arr[0];
1459 $wh_booking_date2 =(string) $wh_booking_date_arr[1];
1460
1461 // Check In date - Tomorrow
1462 if ( $wh_booking_date === '7' ) {
1463
1464 $today_mysql_format = date_i18n( 'Y-m-d', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) + DAY_IN_SECONDS ); // Tommorow day with gmt offset
1465 foreach ( $bookings_obj as $bc_id => $bc_value ) {
1466 $check_in_date = $bc_value->short_dates[0];
1467 $check_in_date = explode( ' ', $check_in_date );
1468 $check_in_date = $check_in_date[0]; // 2014-02-25
1469 if ( $today_mysql_format != $check_in_date ) {
1470 unset( $bookings_obj[ $bc_id ] );
1471 $bookings_count--;
1472 }
1473 }
1474 }
1475
1476 // Check Out date - Tomorrow
1477 if ( $wh_booking_date === '8' ) {
1478
1479 $tomorrow_mysql_format = date_i18n( 'Y-m-d', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) + DAY_IN_SECONDS ); // Tommorow day with gmt offset
1480 foreach ( $bookings_obj as $bc_id => $bc_value ) {
1481 if ( 1 == count( $bc_value->short_dates ) ) {
1482 $check_out_date = $bc_value->short_dates[0];
1483 } else {
1484 $check_out_date = $bc_value->short_dates[2];
1485 }
1486 $check_out_date = explode( ' ', $check_out_date );
1487 $check_out_date = $check_out_date[0]; // 2014-02-25
1488 if ( $tomorrow_mysql_format != $check_out_date ) {
1489 unset( $bookings_obj[ $bc_id ] );
1490 $bookings_count --;
1491 }
1492 }
1493 }
1494
1495 // Today == check in/out | Today = Check in | Today = Check out
1496 if ( ( $wh_booking_date === '9' ) || ( $wh_booking_date === '10' ) || ( $wh_booking_date === '11' ) ) {
1497
1498 $today_mysql_format = date_i18n( 'Y-m-d', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) + 0 * DAY_IN_SECONDS ); // Today day with gmt offset
1499
1500 foreach ( $bookings_obj as $bc_id => $bc_value ) {
1501
1502 $check_in_date = $bc_value->short_dates[0];
1503 $check_in_date = explode( ' ', $check_in_date );
1504 $check_in_date = $check_in_date[0]; // 2014-02-25
1505
1506 if ( count( $bc_value->short_dates ) == 1 ) {
1507 $check_out_date = $bc_value->short_dates[0];
1508 } else {
1509 $check_out_date = $bc_value->short_dates[2];
1510 }
1511 $check_out_date = explode( ' ', $check_out_date );
1512 $check_out_date = $check_out_date[0]; // 2014-02-25
1513
1514 // Check In
1515 if ( $wh_booking_date === '10' ) {
1516 if ( $today_mysql_format != $check_in_date ) {
1517 unset( $bookings_obj[ $bc_id ] );
1518 $bookings_count --;
1519 }
1520 }
1521 // Check out
1522 if ( $wh_booking_date === '11' ) {
1523 if ( $today_mysql_format != $check_out_date ) {
1524 unset( $bookings_obj[ $bc_id ] );
1525 $bookings_count --;
1526 }
1527 }
1528 // Check In | Check out // FixIn: 9.6.3.12.
1529 if ( $wh_booking_date === '9' ) {
1530 if ( ( $today_mysql_format != $check_in_date ) && ( $today_mysql_format != $check_out_date ) ) {
1531 unset( $bookings_obj[ $bc_id ] );
1532 $bookings_count --;
1533 }
1534 }
1535
1536 }
1537 }
1538
1539 return array( $bookings_obj, $bookings_count );
1540 }
1541
1542 /**
1543 * Get array of bookings with dates (wide and short dates view)
1544 * after inserting dates into the bookings
1545 *
1546 * @param $bookings_obj Array (
1547 [0] => stdClass Object (
1548 [booking_id] => 182
1549 [trash] => 0
1550 [sync_gid] =>
1551 [is_new] => 1
1552 [status] =>
1553 [sort_date] => 2023-01-23 10:00:01
1554 [modification_date] => 2022-04-18 12:23:30
1555 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^name2^rr~text^secondname2^hjk~email^email2^hyui@nbco.csdf~text^phone2^h~text^address2^khj~text^city2^e~text^postcode2^hj~selectbox-one^country2^HT~selectbox-one^visitors2^1~selectbox-one^children2^0~textarea^details2^djkh~checkbox^term_and_condition2[]^I Accept term and conditions
1556 [hash] => a1ae510d8fee961b7f8ae53101632151
1557 [booking_type] => 2
1558 [remark] =>
1559 [cost] => 75.00
1560 [pay_status] => 165028101080.84
1561 [pay_request] => 0
1562 )
1563 [1] => stdClass Object, ....
1564 * @param $booking_dates_obj Array (
1565 [0] => stdClass Object (
1566 [booking_dates_id] => 294
1567 [booking_id] => 147
1568 [booking_date] => 2022-06-27 12:00:01
1569 [approved] => 0
1570 [type_id] =>
1571 )
1572 [1] => stdClass Object, ...
1573 *
1574 * @return array Array (
1575 * [182] => stdClass Object (
1576 * ... many other props ....
1577 * [id] => 182
1578 * [approved] => 0
1579 * [dates] => Array (
1580 * [0] => 2023-01-23 10:00:01
1581 * [1] => 2023-01-25 00:00:00
1582 * [2] => 2023-01-27 12:00:02
1583 * )
1584 * [child_id] => Array (
1585 * [0] =>
1586 * [1] =>
1587 * [2] =>
1588 * )
1589 * [short_dates] => Array (
1590 * [0] => 2023-01-23 10:00:01
1591 * [1] => ,
1592 * [2] => 2023-01-25 00:00:00
1593 * [3] => ,
1594 * [4] => 2023-01-27 12:00:02
1595 * )
1596 * [short_dates_child_id] => Array (
1597 * [0] =>
1598 * [1] =>
1599 * [2] =>
1600 * [3] =>
1601 * [4] =>
1602 * )
1603 * )
1604 * [181] => stdClass Object (
1605 * ....
1606 */
1607 function wpbc_ajx_include_bookingdates_in_the_bookings( $bookings_obj, $booking_dates_obj ){
1608
1609 $bookings_arr = array();
1610 foreach ( $bookings_obj as $booking ) {
1611
1612 $bookings_arr[$booking->booking_id] = new StdClass;
1613 $bookings_arr[$booking->booking_id]->booking_db = $booking;
1614 $bookings_arr[$booking->booking_id]->id = $booking->booking_id;
1615 $bookings_arr[$booking->booking_id]->approved = 0;
1616 $bookings_arr[$booking->booking_id]->dates = array();
1617 $bookings_arr[$booking->booking_id]->child_id = array();
1618 /*
1619 $resource_id = (isset( $booking->booking_type )) ? $booking->booking_type : '1';
1620
1621 // booking Form parse can be here
1622
1623
1624 if ( ( isset( $booking->sync_gid ) ) && (!empty( $booking->sync_gid )) ) {
1625 $booking->form .= "~text^sync_gid{$booking->booking_type}^{$booking->sync_gid}";
1626 }
1627
1628 $cont = wpbc__legacy__get_form_content_arr( $booking->form
1629 , $resource_id
1630 , ''
1631 , array(
1632 'booking_id' => $booking->booking_id
1633 , 'resource_title' => (isset( $booking_types[$booking->booking_type] )) ? $booking_types[$booking->booking_type] : ''
1634 )
1635 );
1636 $search = array( "'(<br[ ]?[/]?>)+'si", "'(<[/]?p[ ]?>)+'si" );
1637 $replace = array( "&nbsp;&nbsp;", " &nbsp; ", " &nbsp; " );
1638 $cont['content'] = preg_replace( $search, $replace, $cont['content'] );
1639 //debuge( htmlentities( $cont['content'] ) );die;
1640 $bookings_arr[$booking->booking_id]->form_show = $cont['content'];
1641 unset( $cont['content'] );
1642 $bookings_arr[$booking->booking_id]->form_data = $cont;
1643
1644 /**/
1645 }
1646
1647 // Wide dates in bookings
1648 foreach ( $booking_dates_obj as $date ) {
1649 $bookings_arr[ $date->booking_id ]->approved = $date->approved;
1650
1651 $bookings_arr[ $date->booking_id ]->dates[] = $date->booking_date;
1652 $bookings_arr[ $date->booking_id ]->child_id[] = ( isset( $date->type_id ) ) ? $date->type_id : '';
1653 }
1654
1655 // Short dates
1656 foreach ( $bookings_arr as $booking_id => $booking ) {
1657
1658 if ( count( $booking->dates ) == 0 ) { continue; } // If no dates, then skip
1659
1660 $bookings_arr[ $booking_id ]->short_dates = array( $booking->dates[0] ); // First Day
1661 $bookings_arr[ $booking_id ]->short_dates_child_id = array( $bookings_arr[ $booking_id ]->child_id[0] );
1662 $previous = array(
1663 'date' => $booking->dates[0],
1664 'date_index' => 0,
1665 'separator' => false
1666 );
1667
1668 if ( count( $booking->dates ) == 1 ) { continue; } // if 1 date, then skip
1669
1670
1671 for ( $date_indx = 1; $date_indx < ( count( $booking->dates ) ); $date_indx ++ ) { // Start from 2nd day
1672
1673 $date = $booking->dates[ $date_indx ];
1674
1675 // if ( wpbc_is_next_day( $date, $previous['date'] ) ) {
1676 $next_day_if__check_in__then__check_out = true;
1677 if ( wpbc_is_less_than_next_day( $date, $previous['date'], $next_day_if__check_in__then__check_out ) ) {
1678
1679 if ( '-' != $previous['separator'] ) {
1680 $bookings_arr[ $booking_id ]->short_dates[] = '-';
1681 $bookings_arr[ $booking_id ]->short_dates_child_id[] = '';
1682 }
1683 $previous['separator'] = '-';
1684
1685 } else {
1686
1687 if ( '-' == $previous['separator'] ) {
1688
1689 $bookings_arr[ $booking_id ]->short_dates[] = $previous['date'];
1690 $bookings_arr[ $booking_id ]->short_dates_child_id[] = $bookings_arr[ $booking_id ]->child_id[ $previous['date_index'] ];
1691 }
1692 $bookings_arr[ $booking_id ]->short_dates[] = ',';
1693 $bookings_arr[ $booking_id ]->short_dates_child_id[] = '';
1694
1695 $bookings_arr[ $booking_id ]->short_dates[] = $date;
1696 $bookings_arr[ $booking_id ]->short_dates_child_id[] = $bookings_arr[ $booking_id ]->child_id[ $date_indx ];
1697
1698 $previous['separator'] = ',';
1699 }
1700
1701 $previous['date'] = $date;
1702 $previous['date_index'] = $date_indx;
1703
1704 } // dates loop: $date_indx => $date
1705
1706 if ( '-' == $previous['separator'] ) {
1707 $bookings_arr[ $booking_id ]->short_dates[] = $previous['date'];
1708 $bookings_arr[ $booking_id ]->short_dates_child_id[] = $bookings_arr[ $booking_id ]->child_id[ $previous['date_index'] ];
1709 }
1710
1711 } // bookings loop: $booking_id => $booking
1712
1713 return $bookings_arr;
1714 }
1715
1716
1717 function wpbc_ajx_parse_bookings( $bookings_arr, $resources_arr ) {
1718
1719 $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
1720
1721 foreach ( $bookings_arr as $booking_id => $booking ) {
1722
1723 // Booking resource ------------------------------------------------------------------------------------
1724 $resource_id = ( isset( $booking->booking_db->booking_type ) ) ? $booking->booking_db->booking_type : '1';
1725 $resource_title = '';
1726 $resource_owner_user = $user_id;
1727
1728 if ( class_exists( 'wpdev_bk_personal' ) ) {
1729 $resource_title = ( isset( $resources_arr[ $resource_id ] ) ) ? $resources_arr[ $resource_id ]['title'] : __( 'Resource not exist', 'booking' );
1730 $resource_title = wpbc_lang( $resource_title );
1731 }
1732 if ( class_exists( 'wpdev_bk_multiuser' ) ) {
1733 $resource_owner_user = ( isset( $resources_arr[ $resource_id ] ) ) ? $resources_arr[ $resource_id ]['users'] : $user_id;
1734 }
1735
1736 // Parse form fields only from $booking->booking_db->form ------------------------------------------
1737 $booking_data_arr = wpbc_parse_booking_data_fields( $booking->booking_db->form,
1738 array( 'resource_id' => $resource_id )
1739 );
1740
1741
1742 foreach ( $booking_data_arr as $booking_data_arr_key => $booking_data_arr_value ) {
1743 // Booking Listing escaping
1744 $booking_data_arr[$booking_data_arr_key] = wpbc_string__escape__then_convert__n_amp__html( $booking_data_arr_value );
1745 }
1746
1747 // Add system keys to data fields arr, like ( 'booking_id', 'trash', 'sync_gid'... ---------------------
1748 $booking_data_arr = wpbc_add_system_booking_data_fields(
1749 $booking_data_arr,
1750 array_merge(
1751 get_object_vars( $booking->booking_db ),
1752 array( 'id' => $booking->id,
1753 'approved' => $booking->approved,
1754 'wpbc_custom_booking_form' => '' //FixIn: 9.4.3.12 // FixIn: 9.4.4.9.
1755 )
1756 )
1757 , array(
1758 'booking_id',
1759 'trash',
1760 'sync_gid',
1761 'is_new',
1762 'status',
1763 'sort_date',
1764 'modification_date',
1765 'creation_date',
1766 'hash',
1767 'booking_type',
1768 'remark',
1769 'cost',
1770 'pay_status',
1771 'pay_request',
1772 'id',
1773 'approved',
1774 'booking_options',
1775 'wpbc_custom_booking_form', // FixIn: 9.4.3.12.
1776 )
1777 );
1778
1779 // Set dates and times in correct format ---------------------------------------------------------------
1780 $booking_data_arr = wpbc_parse_booking_data_fields_formats( $booking_data_arr );
1781
1782 // Get SHORT / WIDE Dates showing data -----------------------------------------------------------------
1783 $dates_attr = array( 'date_html_tag' => 'span' );
1784 $short_dates_content = wpbc_get_formated_dates__short( $booking->short_dates, (boolean) $booking->approved, $booking->short_dates_child_id, $resources_arr, $dates_attr );
1785 $wide_dates_content = wpbc_get_formated_dates__wide( $booking->dates, (boolean) $booking->approved, $booking->child_id, $resources_arr, $dates_attr );
1786
1787 //------------------------------------------------------------------------------------------------------
1788 // Payment Status
1789 //------------------------------------------------------------------------------------------------------
1790 if ( 1 ) {
1791 $booking_data_arr['is_paid'] = 0; // 0 | 1
1792 $booking_data_arr['pay_print_status'] = ''; // "Unknown" | "Stripe_v3:OK"
1793 // $booking_data_arr['pay_status'] // "165458416073.66" | "Stripe_v3:OK" | "PayPal:Ok"
1794
1795 if ( class_exists( 'wpdev_bk_biz_s' ) ) {
1796
1797 if ( wpbc_is_payment_status_ok( trim( $booking_data_arr['pay_status'] ) ) ) {
1798 $booking_data_arr['is_paid'] = 1;
1799 }
1800
1801 $payment_status_titles = get_payment_status_titles();
1802
1803 $current_payment_status_title = array_search( $booking_data_arr['pay_status'], $payment_status_titles );
1804
1805 if ( $current_payment_status_title === false ) {
1806 $current_payment_status_title = $booking_data_arr['pay_status'];
1807 }
1808
1809 if ( $booking_data_arr['is_paid'] ) {
1810 $booking_data_arr['pay_print_status'] = $booking_data_arr['pay_status'];
1811 if ( $current_payment_status_title == 'Completed' ) {
1812 $booking_data_arr['pay_print_status'] = $current_payment_status_title;
1813 }
1814 } else if ( ( is_numeric( $booking_data_arr['pay_status'] ) ) || ( $booking_data_arr['pay_status'] == '' ) ) {
1815 $booking_data_arr['pay_print_status'] = __( 'Unknown', 'booking' );
1816 } else {
1817 $booking_data_arr['pay_print_status'] = $current_payment_status_title;
1818 }
1819 ////////////////////////////////////////////////////////////////////////////////////////////////////
1820
1821 if ( $booking_data_arr['pay_print_status'] == 'Completed' ) { // FixIn: 8.4.7.11.
1822 $booking_data_arr['pay_print_status'] = __( 'Completed', 'booking' );
1823 }
1824 $real_payment_css = empty( $booking_data_arr['pay_status'] ) ? $current_payment_status_title : $booking_data_arr['pay_status']; // FixIn: 8.7.7.13.
1825 $css_payment_label = 'wpbc_label_payment_status_' . wpbc_check_payment_status( $real_payment_css ); // 'success' | 'pending' | 'unknown' | 'error' // FixIn: 8.7.7.13.
1826
1827 if ( $booking_data_arr['is_paid'] ) {
1828 $css_payment_label .= ' wpbc_label_payment_status_success';
1829 }
1830 $payment_label_template = '<span class="wpbc_label wpbc_label_payment_status ' . $css_payment_label . '">'
1831 . '<span style="font-size:07px;padding: 0 1em 0 0;line-height: 2em;">'
1832 . __( 'Payment', 'booking' )
1833 . '</span> '
1834 . '<span>'
1835 . $booking_data_arr['pay_print_status']
1836 . '</span> '
1837 . '</span>';
1838 } else {
1839 $payment_label_template = '';
1840 }
1841 }
1842
1843 //------------------------------------------------------------------------------------------------------
1844 // Currency
1845 //------------------------------------------------------------------------------------------------------
1846 if ( class_exists( 'wpdev_bk_biz_s' ) ) {
1847 $currency_symbol = wpbc_get_currency_symbol_for_user( $resource_id );
1848 $booking_data_arr['currency_symbol'] = $currency_symbol;
1849 }
1850
1851 //------------------------------------------------------------------------------------------------------
1852 // Add some fields to [ 'parsed_fields' ]
1853 //------------------------------------------------------------------------------------------------------
1854 $booking_data_arr['resource_title'] = $resource_title;
1855 $booking_data_arr['resource_id'] = $resource_id;
1856 $booking_data_arr['resource_owner_user'] = $resource_owner_user;
1857 //$booking_data_arr['short_dates_content'] = $short_dates_content;
1858 //$booking_data_arr['wide_dates_content'] = $wide_dates_content;
1859
1860 //------------------------------------------------------------------------------------------------------
1861 // Form Show - "Content of booking fields data" form
1862 //------------------------------------------------------------------------------------------------------
1863
1864 $custom_booking_form_name = ( ! empty( $booking_data_arr['wpbc_custom_booking_form'] ) ) ? $booking_data_arr['wpbc_custom_booking_form'] : ''; // FixIn: 9.4.3.12.
1865 $form_show_template = wpbc_get_content_booking_form_show( $resource_id , $custom_booking_form_name ); // <strong>First Name</strong>:<span class="fieldvalue">[name]</span>&nbsp;&nbsp; ...
1866 $parsed_form_show = wpbc_get_parsed_content_booking_form_show( $booking_data_arr, $form_show_template ); // <strong>First Name</strong>:<span class="fieldvalue">John</span>&nbsp;&nbsp; ...
1867
1868 //------------------------------------------------------------------------------------------------------
1869 // Google Calendar link
1870 //------------------------------------------------------------------------------------------------------
1871 $booking_data_arr['google_calendar_link'] = wpbc_booking_do_action__get_google_calendar_link( array(
1872 'form_data' => $booking_data_arr,
1873 'form_show' => $parsed_form_show, //wp_strip_all_tags( $parsed_form_show ),
1874 'dates_short' => $booking->short_dates
1875 ) );
1876 $booking_data_arr['visitorbookingpayurl'] = ( class_exists( 'wpdev_bk_biz_s' ) )
1877 ? apply_bk_filter( 'wpdev_booking_set_booking_edit_link_at_email', '[visitorbookingpayurl]', $booking_id )
1878 : '';
1879 // =====================================================================================================
1880 $bookings_arr[ $booking_id ]->parsed_fields = $booking_data_arr;
1881
1882
1883 // =====================================================================================================
1884 $bookings_arr[ $booking_id ]->templates = array(
1885 'form_show' => $parsed_form_show,
1886 'form_show_simple' => wp_kses( trim( stripslashes( $parsed_form_show ) ),
1887 // array_merge(
1888 array(
1889 'span' => array( 'style'=>true , 'class'=>true , 'id'=>true ),
1890 'b' => array( 'style'=>true , 'class'=>true , 'id'=>true ),
1891 'strong' => array( 'style'=>true , 'class'=>true , 'id'=>true ),
1892 'i' => array( 'style'=>true , 'class'=>true , 'id'=>true ),
1893 'class' => array(),
1894 'style' => array()
1895 )
1896 // , wp_kses_allowed_html( 'post' ) )
1897 ),
1898 'form_show_nohtml' => wp_strip_all_tags( $parsed_form_show ),
1899 'short_dates_content' => $short_dates_content,
1900 'wide_dates_content' => $wide_dates_content,
1901 'payment_label_template' => $payment_label_template
1902 );
1903 }
1904
1905 return $bookings_arr;
1906 }
1907
1908
1909 //TODO: Refactor this function to make this simpler, for prevent of issues in future.
1910 /**
1911 * Get SHORT Dates showing data
1912 *
1913 * @param array $short_dates_arr - Array of dates.
1914 * @param bool $is_approved - true or false
1915 * @param $dates_type_id_arr
1916 * @param $booking_resources_arr
1917 * @param array $attr - [ 'date_html_tag' => 'a' ] .
1918 *
1919 * @return string
1920 */
1921 function wpbc_get_formated_dates__short( $short_dates_arr, $is_approved = false, $dates_type_id_arr = array(), $booking_resources_arr = array(), $attr = array() ) {
1922
1923 $defaults = array(
1924 'date_html_tag' => 'a',
1925 );
1926 $params = wp_parse_args( $attr, $defaults );
1927
1928 $css_class_approved = ( $is_approved ) ? 'approved' : '';
1929 $short_dates_content = '';
1930 $short_dates_content_arr = array();
1931 $date_number = 0;
1932 $previous_formatted_date = '';
1933 $previous_short_dates_content_sup;
1934 foreach ( $short_dates_arr as $dt ) {
1935
1936 if ( '-' === $dt ) {
1937 $short_dates_content_arr[] = '<span class="date_tire"> - </span>';
1938 } elseif ( ',' === $dt ) {
1939 $short_dates_content_arr[] = '<span class="date_tire date_comma">, </span>';
1940 } else {
1941
1942 list( $formatted_date, $formatted_time ) = wpbc_get_date_in_correct_format( $dt );
1943
1944 $short_dates_content = '';
1945 $short_dates_content_sup = ''; // Times and booking resources.
1946
1947 if ( 'a' === $params['date_html_tag'] ) {
1948 $short_dates_content .= '<a href="javascript:void(0)" onclick="javascript:wpbc_ajx_click_on_dates_toggle(this);" ';
1949 } else {
1950 $short_dates_content .= '<' . $params['date_html_tag'];
1951 }
1952 $short_dates_content .= ' class="wpbc_label wpbc_label_booking_dates ' . $css_class_approved . '">';
1953
1954 $short_dates_content .= '<span>';
1955
1956 if ( $previous_formatted_date !== $formatted_date ) {
1957 $short_dates_content .= $formatted_date;
1958 $short_dates_content_sup .= '<sup class="field-booking-time">' . $formatted_time . '</sup>';
1959 } else {
1960 // same date (probaly it is one date) !
1961 if ( count( $short_dates_content_arr ) > 0 ) {
1962 // Unset tire: '-'.
1963 unset( $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ] );
1964 if ( ! empty( wp_strip_all_tags( $previous_short_dates_content_sup ) ) ) {
1965 $tag_closed_span_and_a = $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ];
1966 // unset time_sup
1967 unset( $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ] );
1968 $short_dates_content_arr[ count( $short_dates_content_arr ) - 1 ] = $tag_closed_span_and_a;
1969 }
1970 $short_dates_content_sup .= '<sup class="field-booking-time">' . wp_strip_all_tags( $previous_short_dates_content_sup ) . ' - ' . $formatted_time . '</sup>';
1971 }
1972 }
1973
1974 // BL.
1975 if (
1976 ( class_exists( 'wpdev_bk_biz_l' ) )
1977 && ( ! empty( $dates_type_id_arr[ $date_number ] ) )
1978 && ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
1979 ){
1980
1981 $resource_title = ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
1982 ? $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ]['title']
1983 : __( 'Resource not exist', 'booking' );
1984 $resource_title = wpbc_lang( $resource_title );
1985
1986 if ( strlen( $resource_title ) > 19 ) {
1987 $resource_title = substr( $resource_title, 0, 13 ) . '...' . substr( $resource_title, - 3 );
1988 }
1989
1990 $short_dates_content_sup .= '<sup class="field-booking-time date_from_dif_type"> ' . $resource_title . '</sup>';
1991 }
1992
1993 $short_dates_content_arr[] = $short_dates_content;
1994 $short_dates_content_arr[] = $short_dates_content_sup;
1995 $short_dates_content_arr[] = '</span></' . $params['date_html_tag'] . '>';
1996
1997
1998
1999 $previous_short_dates_content_sup = $short_dates_content_sup;
2000 $previous_formatted_date = $formatted_date;
2001 }
2002 $date_number++;
2003 }
2004
2005 $short_dates_content = implode( '', $short_dates_content_arr );
2006
2007 return $short_dates_content;
2008 }
2009
2010
2011 /**
2012 * Get Wide Dates showing data
2013 *
2014 * @param array $dates_arr - array of dates in sql string format
2015 * @param bool $is_approved - is approved (true) or pending (false)
2016 * @param array $dates_type_id_arr - array of $date->type_id from the dates SQL object
2017 * @param type $booking_resources_arr - array of booking resources objects
2018 *
2019 * @return string
2020 */
2021 function wpbc_get_formated_dates__wide( $dates_arr, $is_approved = false, $dates_type_id_arr = array(), $booking_resources_arr = array(), $attr = array() ) {
2022
2023 $defaults = array(
2024 'date_html_tag' => 'a',
2025 );
2026 $params = wp_parse_args( $attr, $defaults );
2027
2028 $wide_dates_arr = array();
2029
2030 $css_class_approved = ( $is_approved ) ? 'approved' : '';
2031
2032 foreach ( $dates_arr as $date_number => $sql_booking_date ) {
2033
2034 list( $formatted_date, $formatted_time ) = wpbc_get_date_in_correct_format( $sql_booking_date );
2035
2036 $wide_date = '';
2037 if ( 'a' === $params['date_html_tag'] ) {
2038 $wide_date .= '<a href="javascript:void(0)" onclick="javascript:wpbc_ajx_click_on_dates_toggle(this);" ';
2039 } else {
2040 $wide_date .= '<' . $params['date_html_tag'];
2041 }
2042 $wide_date .= ' class="wpbc_label wpbc_label_booking_dates ' . $css_class_approved . '">';
2043 $wide_date .= '<span>';
2044
2045 $wide_date .= $formatted_date;
2046 $wide_date .= '<sup class="field-booking-time">' . $formatted_time . '</sup>';
2047
2048 // BL
2049 if (
2050 ( class_exists( 'wpdev_bk_biz_l' ) )
2051 && ( '' != $dates_type_id_arr[ $date_number ] )
2052 && ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
2053 ){
2054 $resource_title = ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) )
2055 ? $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ]['title']
2056 : __( 'Resource not exist', 'booking' );
2057 $resource_title = wpbc_lang( $resource_title );
2058
2059 if ( strlen( $resource_title ) > 19 ) {
2060 $resource_title = substr( $resource_title, 0, 13 ) . '...' . substr( $resource_title, - 3 );
2061 }
2062 $wide_date .= '<sup class="field-booking-time date_from_dif_type"> ' . $resource_title . '</sup>';
2063 }
2064
2065 $wide_date .= '</span></' . $params['date_html_tag'] . '>';
2066
2067 $wide_dates_arr[] = $wide_date;
2068 }
2069
2070 $wide_dates_content = implode( '<span class="date_tire date_comma">, </span>' , $wide_dates_arr );
2071
2072 return $wide_dates_content;
2073 }
2074
2075
2076 /**
2077 * Parse booking "data field" and get array
2078 *
2079 * @param string $data - "id^2~booking_type^Standard~status^Approved~dates^2019-09-18 00:00:00 - 2019-09-20 00:00:00 , 2019-09-18 00:00:00 (Standard-1) - 2019-09-20 00:00:00 (Standard-1)~modification_date^2019-09-05 10:50:04~cost^100.00~pay_status^156766972609.7~selected_short_timedates_hint^09/18/2019 - 09/20/2019~nights_number_hint^2~cost_hint^$75.00~name^John test~secondname^Smith~email^user@beta.com~phone^~visitors^4~children^~details^~term_and_condition^~user^Support A~wpbc_other_action^~rangetime^~other_email^~visitorsselector^~visitors_fee^~visitors_fee_hint^~trash^~remark^Approved by:John Smith (user@beta.com) [2019-09-11 09:30] Declined by:John Smith (user@beta.com) [2019-09-11 09:30]"
2080 * @param array $attr - array( 'r_separator' => '~', 'f_separator' => '^' )
2081 *
2082 * @return array - Array (
2083 [id] => 2
2084 [booking_type] => Standard
2085 [status] => Approved
2086 ... )
2087 */
2088 function wpbc_parse_booking_data_fields( $data , $attr = array() ){
2089
2090 $defaults = array(
2091 'r_separator' => '~' ,
2092 'f_separator' => '^' ,
2093 'resource_id' => '1' ,
2094 'system_fields' => array(
2095 'booking_id',
2096 'trash',
2097 //'sync_gid',
2098 'is_new',
2099 'status',
2100 'sort_date',
2101 'modification_date',
2102 'hash',
2103 'booking_type',
2104 'remark',
2105 'cost',
2106 'pay_status',
2107 'pay_request',
2108 'id',
2109 'approved'
2110 )
2111 );
2112 $attr = wp_parse_args( $attr, $defaults );
2113
2114 $data_arr = array();
2115
2116 if ( ! empty( $data ) ) {
2117
2118 $data = explode( $attr['r_separator'] , $data ); // ~
2119
2120 foreach ( $data as $data_rows ) {
2121
2122 $data_rows = explode( $attr['f_separator'] , $data_rows ); // ^
2123
2124 $data_field = array( 'type' => $data_rows[0], 'name' => $data_rows[1], 'value' => $data_rows[2] );
2125
2126 // remove checkboxes suffix []
2127 $data_field['name'] = str_replace( '[]', '', $data_field['name'] );
2128
2129 // remove booking resource ID suffix
2130 $data_field['name'] = substr( $data_field['name'], 0, - 1 * strlen( strval( $attr['resource_id'] ) ) );
2131
2132 // System fields - adjust fields with same name
2133 if ( in_array( $data_field['name'], $attr['system_fields'] ) ) {
2134 $data_field['name'] .= '_data';
2135 }
2136
2137 //Checkboxes
2138 if ( ( 'checkbox' == $data_field['type'] ) && ( empty( $data_field['value'] ) ) ) {
2139 continue;
2140 }
2141 if ( ( 'checkbox' == $data_field['type'] ) && ( ! is_array( $data_field['value'] ) ) ) {
2142 $data_field['value'] = str_replace( array( 'true', 'false' ), array(
2143 strtolower( __( 'Yes', 'booking' ) ),
2144 strtolower( __( 'No', 'booking' ) )
2145 ), $data_field['value'] );
2146 }
2147
2148 // Several items with same name - multi checkboxes
2149 if ( ! isset( $data_arr[ $data_field['name'] ] ) ) {
2150 $data_arr[ $data_field['name'] ] = $data_field['value'];
2151 } else {
2152 if ( is_array( $data_arr[ $data_field['name'] ] ) ) {
2153 $data_arr[ $data_field['name'] ][] = $data_field['value'];
2154 } else {
2155 $data_arr[ $data_field['name'] ] = array( $data_arr[ $data_field['name'] ], $data_field['value'] );
2156 }
2157 }
2158
2159 }
2160 }
2161
2162 foreach ( $data_arr as $key => $value ) {
2163
2164 // Multi checkboxes: [9] => checkbox^my_multi_checkbx4[]^1 [10] => checkbox^my_multi_checkbx4[]^ [11] => checkbox^my_multi_checkbx4[]^3
2165 if ( is_array( $value ) ) {
2166 $value = implode( ',', $value );
2167 $data_arr[$key] = $value;
2168 }
2169 }
2170
2171 return $data_arr;
2172 }
2173
2174
2175 /**
2176 * Add system fields to Booking fields array and get final array of fields
2177 * @param array $booking_data_arr Original array of form fields from DB
2178 Array (
2179 [selected_short_dates_hint] => March 5, 2023
2180 [days_number_hint] => 1
2181 [cost_hint] => &amp;#36;95
2182 [rangetime] => 10:00 AM - 12:00 PM
2183 [name] => test
2184 [email] => test@wpbookingcalendar.com
2185 ...
2186 )
2187
2188 * @param array $booking_system_arr array of system fields from DB
2189 Array ( [booking_id] => 188
2190 [trash] => 0
2191 ...
2192 [cost] => 95.00
2193 [pay_status] => 165036591118.88
2194 [pay_request] => 0
2195 [id] => 188
2196 [approved] => 0
2197 )
2198
2199 * @param array $system_keys_arr system fields keys that need to be added, like this:
2200 Array ( booking_id, trash, sync_gid, is_new, status
2201 , sort_date, modification_date, hash, booking_type
2202 , remark, cost, pay_status, pay_request, id, approved )
2203
2204 * @return array array of form fields with system fields
2205 */
2206 function wpbc_add_system_booking_data_fields( $booking_data_arr, $booking_system_arr, $system_keys_arr ){
2207
2208 foreach ( $system_keys_arr as $key ) {
2209
2210 if (
2211 ( ! isset( $booking_system_arr[ $key ] ) )
2212 || ( is_null( $booking_system_arr[ $key ] ) )
2213 ) {
2214 $booking_system_arr[ $key ] = ''; //Some fields, like remark or booking_options can be null, so we define them as ''
2215 }
2216
2217 if ( isset( $booking_system_arr[ $key ] ) ) {
2218
2219 if ( ! isset( $booking_data_arr[ $key ] ) ) {
2220 $booking_data_arr[ $key ] = maybe_unserialize( $booking_system_arr[ $key ] );
2221 } else {
2222 $booking_data_arr[ $key . '_system' ] = maybe_unserialize( $booking_system_arr[ $key ] );
2223 }
2224 }
2225
2226 }
2227 return $booking_data_arr;
2228 }
2229
2230
2231 /**
2232 * Parse booking form fields format - for example: time fields in specific format
2233 * @param $data_arr
2234 *
2235 * @return array
2236 */
2237 function wpbc_parse_booking_data_fields_formats( $data_arr ){
2238
2239 foreach ( $data_arr as $key => $value ) {
2240
2241 if ( 'rangetime' == $key ) {
2242 $data_arr[$key] = wpbc_time_slot_in_format( $value );
2243 $data_arr[ $key . '_in_24_hour' ] = $value; // FixIn: 10.0.0.52.
2244 }
2245
2246 if ( in_array( $key, array( 'starttime', 'endtime' ) ) ) {
2247 $data_arr[$key] = wpbc_time_in_format( $value );
2248 $data_arr[ $key . '_in_24_hour' ] = $value; // FixIn: 10.0.0.52.
2249 }
2250
2251 if ( in_array( $key, array( 'modification_date', 'creation_date' ) ) ) {
2252
2253 //$data_arr[$key] = wpbc_get_dates_comma_string_localized( $value );
2254
2255
2256 // This date $values in GMT date/Time format. So we need to switch to WordPress locale with TIME sum of actual GMT date/time value + shift of timezone from WordPress.
2257 $is_add_wp_timezone = true;
2258 $its_for_default_datetime_format = '';
2259 $data_arr[ $key ] = wpbc_datetime_localized( $value, $its_for_default_datetime_format, $is_add_wp_timezone );
2260 $data_arr[ $key . '_in_24_hour' ] = $value; // FixIn: 10.0.0.52.
2261 }
2262
2263 if ( ( 'hash' === $key ) && ( empty( $value ) ) ) { //FixIn: 9.2.3.4 // FixIn: 9.4.3.10.
2264 // Update booking Hash if it was empty
2265 wpbc_hash__update_booking_hash( $data_arr['id'], $data_arr['booking_type'] );
2266 // Get new booking hash
2267 $hash__arr = wpbc_hash__get_booking_hash__resource_id( $data_arr['id'] );
2268 if ( ! empty( $hash__arr ) ) {
2269 $data_arr[ $key ] = $hash__arr[0];
2270 }
2271 }
2272 }
2273 return $data_arr;
2274 }
2275
2276
2277 /**
2278 * Get pure "Content of booking fields data" with shortcodes inside.
2279 * Can depend on booking resource (BM) or resource owner (MU).
2280 * Now also supports BFB DB resolver (published/preview-aware).
2281 *
2282 * @param int $resource_id
2283 * @param string $custom_booking_form_name Optional. Force this custom form if possible.
2284 *
2285 * @return string
2286 */
2287 function wpbc_get_content_booking_form_show( $resource_id, $custom_booking_form_name = '' ) { // FixIn: 9.4.3.12.
2288
2289 static $wpbc__form_show_cache = array();
2290
2291 $resource_id = (int) $resource_id;
2292 $custom_booking_form_name = (string) $custom_booking_form_name;
2293
2294 if ( - 1 === $resource_id ) {
2295 if ( function_exists( 'get__default_type' ) ) {
2296 $resource_id = (int) get__default_type();
2297 } else {
2298 $resource_id = 1;
2299 }
2300 }
2301
2302 // ------------------------------------------------------------
2303 // Determine a stable form slug early (avoid undefined var).
2304 // This is used for cache key and for resolver path.
2305 // ------------------------------------------------------------
2306 $my_booking_form_name = ( '' !== $custom_booking_form_name ) ? $custom_booking_form_name : 'standard';
2307
2308 // Preview-aware context (optional; usually "published" in Booking Listing).
2309 $ctx = array();
2310 if ( function_exists( 'wpbc_get_request_form_context' ) ) {
2311 $ctx = wpbc_get_request_form_context();
2312 }
2313 $form_status = ( isset( $ctx['form_status'] ) ) ? sanitize_key( $ctx['form_status'] ) : 'published';
2314 if ( in_array( $form_status, array( 'publish', 'published' ), true ) ) {
2315 $form_status = 'published';
2316 }
2317 if ( 'preview' !== $form_status ) {
2318 $form_status = 'published';
2319 }
2320
2321 // Cache key (important: this function is called per booking row).
2322 $cache_key = get_locale() . '|' . $form_status . '|' . $resource_id . '|' . $my_booking_form_name;
2323 if ( isset( $wpbc__form_show_cache[ $cache_key ] ) ) {
2324 return $wpbc__form_show_cache[ $cache_key ];
2325 }
2326
2327 // ------------------------------------------------------------
2328 // Legacy resolution (keep exactly as before).
2329 // ------------------------------------------------------------
2330 if ( ! class_exists( 'wpdev_bk_personal' ) ) {
2331
2332 $booking_form_show = wpbc_simple_form__get_form_show__as_shortcodes();
2333 $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $booking_form_show );
2334
2335 } else {
2336
2337 $booking_form_show = get_bk_option( 'booking_form_show' );
2338 $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $booking_form_show );
2339
2340 // BM / MU legacy forms logic.
2341 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
2342
2343 if ( '' !== $custom_booking_form_name ) { // FixIn: 9.4.3.12.
2344 $booking_form_show = apply_bk_filter( 'wpdev_get_booking_form_content', $booking_form_show, $custom_booking_form_name );
2345 $my_booking_form_name = $custom_booking_form_name;
2346 } else {
2347 // BM :: Get default Custom Form of Resource
2348 $my_booking_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', 'standard', $resource_id );
2349 if ( ( 'standard' !== $my_booking_form_name ) && ( '' !== $my_booking_form_name ) ) {
2350 $booking_form_show = apply_bk_filter( 'wpdev_get_booking_form_content', $booking_form_show, $my_booking_form_name );
2351 }
2352 }
2353
2354 // MU :: if resource belongs to Regular User -> load THAT owner's form (not logged-in user).
2355 $booking_form_show = apply_bk_filter( 'wpbc_multiuser_get_booking_form_show_of_regular_user', $booking_form_show, $resource_id, $my_booking_form_name ); // FixIn: 8.1.3.19.
2356 }
2357 }
2358
2359 // ------------------------------------------------------------
2360 // NEW: BFB resolver override (must be AFTER BM/MU legacy resolution).
2361 // This ensures BFB "content_form" wins and legacy doesn't clobber it.
2362 // ------------------------------------------------------------
2363 if ( class_exists( 'WPBC_FE_Form_Source_Resolver' ) && class_exists( 'WPBC_BFB_Form_Loader' ) ) {
2364
2365 $req = array(
2366 'resource_id' => (int) $resource_id,
2367 'form_slug' => (string) $my_booking_form_name,
2368 'form_status' => $form_status,
2369 'custom_params' => array(),
2370 'legacy_instance' => null,
2371 'ctx' => ( is_array( $ctx ) ? $ctx : array() ),
2372 );
2373
2374 $resolved = WPBC_FE_Form_Source_Resolver::resolve( $req );
2375
2376 // If preview requested but not found, try published as fallback.
2377 if ( ( empty( $resolved['engine'] ) || ( 'bfb_db' !== $resolved['engine'] ) ) && ( 'preview' === $form_status ) ) {
2378 $req['form_status'] = 'published';
2379 $resolved = WPBC_FE_Form_Source_Resolver::resolve( $req );
2380 }
2381
2382 if ( ! empty( $resolved['engine'] ) && ( 'bfb_db' === $resolved['engine'] ) ) {
2383
2384 $bfb_loader_args = array();
2385 if ( ! empty( $resolved['bfb_loader_args'] ) && is_array( $resolved['bfb_loader_args'] ) ) {
2386 $bfb_loader_args = $resolved['bfb_loader_args'];
2387 }
2388
2389 // We need "content_form" template for booking fields output.
2390 $bfb_loader_args['return'] = 'content_form';
2391
2392 $bfb_pair = wpbc_bfb_get_booking_form_pair( $bfb_loader_args );
2393
2394 $content_form = '';
2395 if ( is_array( $bfb_pair ) && isset( $bfb_pair['content'] ) ) {
2396 $content_form = (string) $bfb_pair['content'];
2397 }
2398
2399 if ( '' !== trim( $content_form ) ) {
2400 // Keep legacy behavior: custom html shortcodes.
2401 $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $content_form );
2402 }
2403 }
2404 }
2405
2406 // ------------------------------------------------------------
2407 // Language + cleanup (keep old behavior).
2408 // ------------------------------------------------------------
2409 $booking_form_show = wpbc_lang( $booking_form_show );
2410
2411 $search = array( "'(<br[ ]?[/]?>)+'si", "'(<[/]?p[ ]?>)+'si" );
2412 $replace = array( "&nbsp;&nbsp;", " &nbsp; ", " &nbsp; " );
2413 $booking_form_show = preg_replace( $search, $replace, $booking_form_show );
2414
2415 // Store cache by final slug (slug may have changed in BM branch).
2416 $final_cache_key = get_locale() . '|' . $form_status . '|' . $resource_id . '|' . $my_booking_form_name;
2417 $wpbc__form_show_cache[ $final_cache_key ] = $booking_form_show;
2418
2419 return $booking_form_show;
2420 }
2421
2422
2423
2424 /**
2425 * Get parsed "Content of booking fields data" - Shortcodes replaced by Values
2426 *
2427 * @param array $booking_data_arr
2428 * @param string $booking_form_show
2429 *
2430 * @return string
2431 */
2432 function wpbc_get_parsed_content_booking_form_show( $booking_data_arr, $booking_form_show ){
2433
2434 foreach ( $booking_data_arr as $key_param => $value_param ) {
2435 if ( ( gettype ( $value_param ) != 'array' )
2436 && ( gettype ( $value_param ) != 'object' )
2437 ) {
2438 $booking_form_show = str_replace( '['. $key_param .']', $value_param ,$booking_form_show);
2439 }
2440 }
2441 // Remove all shortcodes, which have not replaced early.
2442 $booking_form_show = preg_replace ('/[\s]{0,}\[[a-zA-Z0-9.,-_]{0,}\][\s]{0,}/', '', $booking_form_show);
2443
2444 $booking_form_show = str_replace( "&amp;", '&', $booking_form_show );
2445
2446 return $booking_form_show;
2447 }
2448
2449 // </editor-fold>
2450
2451
2452 // <editor-fold defaultstate="collapsed" desc=" F u n c t i o n s f o r C l e a n i ng s " >
2453
2454 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2455 // Escaping
2456 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2457
2458 /**
2459 * Escaping for inline JavaScript.
2460 * Based on WordPress esc_js()
2461 * plus removing \n in the code
2462 * and back converting escaped single quotes from \' to '
2463 *
2464 * This function has to be used in the code marked with double quote symbols, not single.
2465 * Example: onclick="javascript:<?php
2466 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2467 echo wpbc_esc_js( $item_params['action'] ); ?>"
2468 *
2469 * @param $text
2470 *
2471 * @return string
2472 */
2473 function wpbc_esc_js( $text ) {
2474
2475 $text = str_replace( "\n", '', $text ); // removing \n in the code
2476
2477 //$safe_text = esc_js( $text ); // js
2478
2479 // This code get from esc_js() and modified for correct working with (' symbols) in translations
2480 $safe_text = wp_check_invalid_utf8( $text );
2481 $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT );
2482 $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "\'", stripslashes( $safe_text ) );
2483 $safe_text = str_replace( "\r", '', $safe_text );
2484 $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) );
2485
2486 $safe_text = str_replace( "\'", "'", $safe_text ); // back converting escaped single quotes from \' to '
2487 $safe_text = str_replace( "\\\'", "\'", $safe_text ); // back converting escaped single quotes from \' to '
2488
2489 return $safe_text;
2490 }
2491
2492
2493 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2494 // DB
2495 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2496
2497 /**
2498 * Check $value for injections. Basically can be used in Requests params checking.
2499 *
2500 * @param type $value
2501 *
2502 * @return type
2503 */
2504 function wpbc_esc_clean_parameter( $value ) {
2505
2506 $value = preg_replace( '/<[^>]*>/', '', $value ); // clean any tags
2507 $value = str_replace( '<', ' ', $value );
2508 $value = str_replace( '>', ' ', $value );
2509 $value = wp_strip_all_tags( $value ); // Strip HTML and PHP tags from a string
2510
2511 // Clean SQL injection
2512 $value = esc_sql( $value );
2513 $value = esc_textarea( $value ); // FixIn: 7.1.1.2.
2514
2515 return $value;
2516 }
2517
2518
2519 function wpbc_esc_sql_like( $value_trimmed ) {
2520
2521 // check here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536
2522
2523 global $wpdb;
2524 if ( method_exists( $wpdb ,'esc_like' ) )
2525 return $wpdb->esc_like( $value_trimmed ); // Its require minimum WP 4.0.0
2526 else
2527 return addcslashes( $value_trimmed, '_%\\' ); // Direct implementation from $wpdb->esc_like(
2528 }
2529
2530
2531 /**
2532 * Clean user string for using in SQL LIKE statement - append to LIKE sql
2533 *
2534 * @param string $value - to clean
2535 *
2536 * @return string - escaped
2537 * Exmaple:
2538 * $search_escaped_like_title = wpbc_esc_clean_like_string_for_append_in_sql_for_db( $input_var );
2539 *
2540 * $where_sql = " WHERE title LIKE ". $search_escaped_like_title ." ";
2541 */
2542 function wpbc_esc_clean_like_string_for_append_in_sql_for_db( $value ) {
2543
2544 // check here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536
2545
2546 global $wpdb;
2547
2548 $value_trimmed = trim( stripslashes( $value ) );
2549
2550 $wild = '%';
2551 $like = $wild . wpbc_esc_sql_like( $value_trimmed ) . $wild;
2552
2553 /* phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.QuotedSimplePlaceholder */
2554 $sql = $wpdb->prepare( "'%s'", $like );
2555
2556 return $sql;
2557
2558
2559 /* Help:
2560 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
2561 * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security.
2562 *
2563 * Example Prepared Statement:
2564 *
2565 * $wild = '%';
2566 * $find = 'only 43% of planets';
2567 * $like = $wild . wpbc_esc_sql_like( $find ) . $wild;
2568 * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE '%s'", $like );
2569 *
2570 * Example Escape Chain:
2571 *
2572 * $sql = esc_sql( wpbc_esc_sql_like( $input ) );
2573 */
2574
2575 }
2576
2577
2578 /**
2579 * Clean string for using in SQL LIKE requests inside single quotes: WHERE title LIKE '%". $escaped_search_title ."%'
2580 * Replaced _ to \_ % to \% \ to \\
2581 *
2582 * @param string $value - to clean
2583 *
2584 * @return string - escaped
2585 * Exmaple:
2586 * $search_escaped_like_title = wpbc_esc_clean_like_string_for_db( $input_var );
2587 *
2588 * $where_sql = " WHERE title LIKE '%". $search_escaped_like_title ."%' ";
2589 *
2590 * Important! Use SINGLE quotes after in SQL query: LIKE '%".$data."%'
2591 */
2592 function wpbc_esc_clean_like_string_for_db( $value ){
2593
2594 // check here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536
2595
2596 global $wpdb;
2597
2598 $value_trimmed = trim( stripslashes( $value ) );
2599
2600 $value_trimmed = wpbc_esc_sql_like( $value_trimmed );
2601
2602 /* phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.QuotedSimplePlaceholder */
2603 $value = trim( $wpdb->prepare( "'%s'", $value_trimmed ) , "'" );
2604
2605 return $value;
2606
2607 /* Help:
2608 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
2609 * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security.
2610 *
2611 * Example Prepared Statement:
2612 *
2613 * $wild = '%';
2614 * $find = 'only 43% of planets';
2615 * $like = $wild . wpbc_esc_sql_like( $find ) . $wild;
2616 * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE '%s'", $like );
2617 *
2618 * Example Escape Chain:
2619 *
2620 * $sql = esc_sql( wpbc_esc_sql_like( $input ) );
2621 */
2622 }
2623
2624
2625 // </editor-fold>
2626
2627
2628 // <editor-fold defaultstate="collapsed" desc=" D B " >
2629
2630 /***
2631 * Get list of DB of this plugin
2632 * @return array
2633 */
2634 function wpbc_get_db_names(){
2635
2636 global $wpdb;
2637
2638 $db_names = array(
2639 'bookings' => $wpdb->prefix . 'booking',
2640 'dates' => $wpdb->prefix . 'bookingdates',
2641 'resources' => $wpdb->prefix . 'bookingtypes',
2642 'resources_meta' => $wpdb->prefix . 'booking_types_meta',
2643 'seasons' => $wpdb->prefix . 'booking_seasons',
2644 'coupons' => $wpdb->prefix . 'booking_coupons'
2645 );
2646
2647 return $db_names;
2648 }
2649
2650 // </editor-fold>
2651
2652
2653 // <editor-fold defaultstate="collapsed" desc=" E r r o r s H a n d l i n g " >
2654
2655 /**
2656 * PHP Fatal Error! Display expanded error info at Booking Listing page
2657 *
2658 * @param $message
2659 * @param $error
2660 *
2661 * @return mixed|string
2662 */
2663 function wpbc_php_error_message( $message, $error ) {
2664
2665 // Check to show this error, only from Booking Listing page, checking secure parameters from wpbc_ajx_booking_listing in ..{Booking Calendar Folder}/includes/page-bookings/_src/ajx_booking_listing.js
2666 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
2667 if ( ! ( ! isset( $_POST['search_params'] ) || empty( $_POST['search_params'] ) ) ) {
2668 // Security ----------------------------------------------------------------------------------------------- // in Ajax Post: 'nonce': wpbc_ajx_booking_listing.get_secure_param( 'nonce' ),
2669 $action_name = 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce';
2670 $nonce_post_key = 'nonce';
2671 // $result_check = check_ajax_referer( $action_name, $nonce_post_key );
2672 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
2673 if ( isset( $_REQUEST[ $nonce_post_key ] ) ) {
2674 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2675 $nonce_request = $_REQUEST[ $nonce_post_key ];
2676
2677 $result_verify_nonce = wp_verify_nonce( $nonce_request, $action_name );
2678
2679 if ( false !== $result_verify_nonce ) {
2680 if ( ( ! empty( $error ) ) && ( ! empty( $error['message'] ) ) ) {
2681 $message .= '<br>' . $error['message'];
2682 }
2683 }
2684 }
2685 }
2686
2687 return $message;
2688 }
2689 add_filter( 'wp_php_error_message', 'wpbc_php_error_message', 2 , 10 );
2690
2691
2692 /**
2693 * Nonce Error! Error Handing for not passed nonce, in booking Listing page.
2694 * Probably nonce was expired (more than 24 hours)
2695 *
2696 * @param $action
2697 * @param $result - 1 Good ( 0-12 hours ago ) , 2 Good ( 12-24 hours ago ) , false - Error ( > 24 hours - nonce is invalid )
2698 */
2699 function wpbc_check_ajax_referer__for_booking_listing( $action, $result ){
2700 if (
2701 ( false === $result )
2702 && ( 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce' === $action )
2703 && ( wp_doing_ajax() )
2704 ) {
2705 die( '<strong>Error!</strong> Probably nonce for this page has been expired. Please <a href="javascript:void(0)" onclick="javascript:location.reload();">reload the page</a>.' );
2706 }
2707 }
2708 add_action( 'check_ajax_referer', 'wpbc_check_ajax_referer__for_booking_listing', 2, 10 );
2709 // </editor-fold>