PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
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__actions.php

bookings__actions.php in Booking Calendar 11.8.4, at includes/page-bookings/bookings__actions.php

2,415 lines 109.3 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 AJX_Bookings
4 * @category AJX_Bookings Actions
5 * @author wpdevelop
6 *
7 * @web-site http://oplugins.com/
8 * @email info@oplugins.com
9 *
10 * @modified 2022-06-10
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
15 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 // Main Ajax handler
17 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18
19 /**
20 * Ajax Actions - Get Listing Data and Response to JS script
21 */
22 function wpbc_ajax_WPBC_AJX_BOOKING_ACTIONS() {
23
24 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
25 if ( ! isset( $_POST['action_params'] ) || empty( $_POST['action_params'] ) ) {
26 exit;
27 }
28
29 $ajax_errors = new WPBC_AJAX_ERROR_CATCHING();
30
31 // Security ----------------------------------------------------------------------------------------------- // in Ajax Post: 'nonce': wpbc_ajx_booking_listing.get_secure_param( 'nonce' ),
32 $action_name = 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce';
33 $nonce_post_key = 'nonce';
34 $result_check = check_ajax_referer( $action_name, $nonce_post_key );
35
36 $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
37
38 // Get clean Parameters for SQL ---------------------------------------------------------------------------
39 $request_rules_structure = array(
40 'booking_action' => array( 'validate' => array(
41 'set_booking_locale',
42 'set_booking_pending' ,
43 'set_booking_approved',
44 'move_booking_to_trash',
45 'restore_booking_from_trash',
46 'delete_booking_completely',
47 'set_booking_as_read',
48 'set_booking_as_unread',
49 'empty_trash',
50 'set_booking_note',
51 'change_booking_resource',
52 'duplicate_booking_to_other_resource',
53 'set_payment_status',
54 'set_booking_cost',
55 'send_payment_request',
56 'import_google_calendar',
57 'export_csv',
58 'feedback_01'
59
60 ), 'default' => '' ),
61 'booking_id' => array( 'validate' => 'digit_or_csd', 'default' => 0 ),
62 'selected_resource_id' => array( 'validate' => 'd', 'default' => 0 ),
63 'booking_meta_locale' => array( 'validate' => 's', 'default' => '' ),
64 'reason_of_action' => array( 'validate' => 's', 'default' => '' ),
65 'remark' => array( 'validate' => 's', 'default' => '' ),
66 'ui_clicked_element_id' => array( 'validate' => 's', 'default' => '' ),
67 'selected_payment_status' => array( 'validate' => 's', 'default' => '' ),
68 'booking_cost' => array( 'validate' => 's', 'default' => '' ),
69
70 'export_type' => array( 'validate' => array( 'csv_all', 'csv_page' ), 'default' => 'csv_page' ),
71 'csv_export_separator' => array( 'validate' => array( 'semicolon', 'comma' ), 'default' => ';' ),
72 'csv_export_skip_fields' => array( 'validate' => 's', 'default' => '' ),
73
74 'booking_gcal_events_from' => array( 'validate' => 's', 'default' => '' ),
75 'booking_gcal_events_from_offset' => array( 'validate' => 's', 'default' => '' ),
76 'booking_gcal_events_from_offset_type' => array( 'validate' => 's', 'default' => '' ),
77 'booking_gcal_events_until' => array( 'validate' => 's', 'default' => '' ),
78 'booking_gcal_events_until_offset' => array( 'validate' => 's', 'default' => '' ),
79 'booking_gcal_events_until_offset_type' => array( 'validate' => 's', 'default' => '' ),
80 'booking_gcal_events_max' => array( 'validate' => 'd', 'default' => 25 ),
81 'booking_gcal_resource' => array( 'validate' => 's', 'default' => '' ),
82
83 'feedback__note' => array( 'validate' => 's', 'default' => '' ),
84 'feedback_stars' => array( 'validate' => 'd', 'default' => 0 )
85 );
86
87 $user_request = new WPBC_AJX__REQUEST( array(
88 'db_option_name' => 'booking_listing_request_params',
89 'user_id' => wpbc_get_current_user_id(),
90 'request_rules_structure' => $request_rules_structure
91 )
92 );
93 $request_prefix = 'action_params';
94 $request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['action_params']['resource_id']
95
96
97
98
99
100 $action_result = array();
101
102 switch ( $request_params['booking_action'] ) {
103
104 case 'set_booking_locale':
105 $action_result = wpbc_booking_do_action__set_booking_locale( $request_params['booking_id']
106 , array(
107 'user_id' => $user_id,
108 'booking_locale' => $request_params['booking_meta_locale']
109 )
110 );
111 break;
112
113 case 'set_booking_pending': // Pending
114 $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id']
115 , array(
116 'user_id' => $user_id,
117 'reason_of_action' => $request_params['reason_of_action'],
118 'is_approve' => '0'
119 )
120 );
121 break;
122
123 case 'set_booking_approved': // Approve
124 $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id']
125 , array(
126 'user_id' => $user_id,
127 'reason_of_action' => $request_params['reason_of_action'],
128 'is_approve' => '1'
129 )
130 );
131 break;
132
133 case 'move_booking_to_trash': // Approve
134 $action_result = wpbc_booking_do_action__trash_booking_or_restore( $request_params['booking_id']
135 , array(
136 'user_id' => $user_id,
137 'reason_of_action' => $request_params['reason_of_action'],
138 'is_trash' => '1'
139 )
140 );
141 break;
142
143 case 'restore_booking_from_trash':
144 $action_result = wpbc_booking_do_action__trash_booking_or_restore( $request_params['booking_id']
145 , array(
146 'user_id' => $user_id,
147 'reason_of_action' => $request_params['reason_of_action'],
148 'is_trash' => '0'
149 )
150 );
151 break;
152
153 case 'delete_booking_completely':
154 $action_result = wpbc_booking_do_action__delete_booking_completely( $request_params['booking_id']
155 , array(
156 'user_id' => $user_id,
157 'reason_of_action' => $request_params['reason_of_action'],
158 )
159 );
160 break;
161
162 case 'set_booking_as_read':
163 $action_result = wpbc_booking_do_action__set_booking_as_read_unread( $request_params['booking_id']
164 , array(
165 'user_id' => $user_id,
166 'is_new' => '0'
167 )
168 );
169 break;
170
171 case 'set_booking_as_unread':
172 $action_result = wpbc_booking_do_action__set_booking_as_read_unread( $request_params['booking_id']
173 , array(
174 'user_id' => $user_id,
175 'is_new' => '1'
176 )
177 );
178 break;
179
180 case 'empty_trash':
181 $action_result = wpbc_booking_do_action__empty_trash( array(
182 'user_id' => $user_id
183 ) );
184 break;
185
186 case 'set_booking_note':
187 $action_result = wpbc_booking_do_action__set_booking_note( $request_params['booking_id']
188 , array(
189 'user_id' => $user_id,
190 'remark' => $request_params['remark'],
191 )
192 );
193 break;
194
195 case 'change_booking_resource': // Pending
196 $action_result = wpbc_booking_do_action__change_booking_resource( $request_params['booking_id']
197 , $request_params['selected_resource_id']
198 , array(
199 'user_id' => $user_id
200 )
201 );
202 break;
203 case 'duplicate_booking_to_other_resource':
204 $action_result = wpbc_booking_do_action__duplicate_booking_to_other_resource( $request_params['booking_id']
205 , $request_params['selected_resource_id']
206 , array(
207 'user_id' => $user_id
208 )
209 );
210 break;
211 case 'set_payment_status':
212 $action_result = wpbc_booking_do_action__set_payment_status( $request_params['booking_id']
213 , $request_params['selected_payment_status']
214 , array(
215 'user_id' => $user_id
216 )
217 );
218 break;
219 case 'set_booking_cost':
220 $action_result = wpbc_booking_do_action__set_booking_cost( $request_params['booking_id']
221 , $request_params['booking_cost']
222 , array(
223 'user_id' => $user_id
224 )
225 );
226 break;
227 case 'send_payment_request':
228 $action_result = wpbc_booking_do_action__send_payment_request( $request_params['booking_id']
229 , $request_params['reason_of_action']
230 , array(
231 'user_id' => $user_id
232 )
233 );
234 break;
235
236 case 'import_google_calendar':
237 $action_result = wpbc_booking_do_action__import_google_calendar( $request_params
238 , array(
239 'user_id' => $user_id
240 )
241 );
242 break;
243
244 case 'export_csv':
245
246 $action_result = wpbc_booking_do_action__export_csv( $request_params
247 , array(
248 'user_id' => $user_id
249 )
250 );
251 break;
252
253 case 'feedback_01':
254
255 $action_result = wpbc_booking_do_action__feedback_01( $request_params
256 , array(
257 'user_id' => $user_id
258 )
259 );
260 break;
261
262 default:
263 }
264
265
266 $defaults = array(
267 'new_listing_params' => false // required for Import Google Calendar bookings
268 , 'after_action_result' => false
269 /* translators: 1: ... */
270 , 'after_action_message' => sprintf( __( 'No actions %s has been processed.', 'booking')
271 , ' <strong>' . $request_params['booking_action'] . '</strong> ' )
272 );
273 $action_result = wp_parse_args( $action_result, $defaults );
274
275 // Check if there were some errors --------------------------------------------------------------------------------
276 $error_messages = $ajax_errors->get_error_messages();
277 if ( ! empty( $error_messages ) ) {
278 $action_result['after_action_message'] .= $error_messages;
279 }
280
281 // Hook for other integrations
282 do_action( 'wpbc_' . $request_params['booking_action'], $request_params, $action_result ); // FixIn: 9.5.3.3.
283
284 //------------------------------------------------------------------------------------------------------------------
285 // Send JSON. Its will make "wp_json_encode" - so pass only array, and This function call wp_die( '', '', array( 'response' => null, ) ) Pass JS OBJ: response_data in "jQuery.post( " function on success.
286 wp_send_json( array(
287 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
288 'ajx_action_params' => $_REQUEST['action_params'], // Do not clean input parameters.
289 'ajx_cleaned_params' => $request_params, // Cleaned input parameters.
290 'ajx_after_action_message' => $action_result['after_action_message'], // Message to show.
291 'ajx_after_action_result' => (int) $action_result['after_action_result'], // Result key 0 | 1.
292 'ajx_after_action_result_all_params_arr' => $action_result, // All result parameters.
293 ) );
294 }
295
296
297 // <editor-fold defaultstate="collapsed" desc=" == Ajax Actions for bookings == " >
298
299 /**
300 * Action: set booking as Locale
301 *
302 * @param int $booking_id ID of booking 10
303 * @param $params
304 *
305 * @return array
306 */
307 function wpbc_booking_do_action__set_booking_locale( $booking_id, $params ){
308
309 $booking_locale = $params['booking_locale'];
310
311 // LOG ---------------------------------------------------------------------------------------------------------
312 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
313 wpbc_db__add_log_info( $booking_id,
314 /* translators: 1: ... */
315 sprintf( __( 'Booking locale changed to %s by:', 'booking' ), $booking_locale )
316 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
317 );
318
319 // Action ---------------------------------------------------------------------------------------------------------
320 $option_arr = array( 'booking_meta_locale' => $booking_locale );
321
322 $result = wpbc_save_booking_meta_option( $booking_id, $option_arr );
323
324 if ( $result ) {
325 $after_action_result = true;
326 $after_action_message = ( ( false === strpos( $booking_id, ',' ) )
327 /* translators: 1: ... */
328 ? sprintf( __( 'Booking has been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" )
329 /* translators: 1: ... */
330 : sprintf( __( 'Bookings have been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" )
331 )
332 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id . '</strong> )</span>';
333 } else {
334 $after_action_result = false;
335 $after_action_message = ( ( false === strpos( $booking_id, ',' ) )
336 /* translators: 1: ... */
337 ? sprintf( __( 'Booking has NOT been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" )
338 /* translators: 1: ... */
339 : sprintf( __( 'Bookings have NOT been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" )
340 )
341 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id . '</strong> )</span>';
342 }
343
344 return array(
345 'after_action_result' => $after_action_result,
346 'after_action_message' => $after_action_message
347 );
348 }
349
350 /**
351 * Action: Get Google Calendar Link
352 *
353 * @param $booking_data array(
354 'form_data' => array( ... )
355 'form_show' => ....
356 'dates_short' => array( ... )
357 )
358 *
359 * @return string URL of encoded link for adding to Google Calendar
360 */
361 function wpbc_booking_do_action__get_google_calendar_link( $booking_data ){
362
363 $params = array();
364 $params['timezone'] = get_bk_option('booking_gcal_timezone');
365
366 $booking_gcal_events_form_fields = maybe_unserialize( get_bk_option( 'booking_gcal_events_form_fields') ); // array( [title]=>text^name, [description]=>textarea^details, [where]=>text^ )
367
368 // Fields ----------------------------------------------------------------------------------------------------------
369 $fields = array( 'title' => '', 'description' => '', 'where' => '' );
370
371 foreach ( $fields as $key_name => $field_value ) {
372
373 if ( ! empty( $booking_gcal_events_form_fields[ $key_name ] ) ) {
374
375 $field_name = explode( '^', $booking_gcal_events_form_fields[ $key_name ] );
376
377 $field_name = $field_name[ ( count( $field_name ) - 1 ) ]; // FixIn: 8.7.7.6.
378
379 if ( 'description' === $key_name ) { // FixIn: 8.1.3.2.
380
381 if ( isset( $booking_data['form_show'] ) ) { // FixIn: 8.7.3.14.
382 // FixIn: 8.7.11.4.
383 $fields[ $key_name ] = $booking_data['form_show'];
384 $fields[ $key_name ] = htmlspecialchars_decode($fields[ $key_name ], ENT_QUOTES );
385 $fields[ $key_name ] = urlencode($fields[ $key_name ]);
386 $fields[ $key_name ] = htmlentities($fields[ $key_name ] );
387 $fields[ $key_name ] = htmlspecialchars_decode ( $fields[ $key_name ], ENT_NOQUOTES );
388 }
389
390 } else if ( ( ! empty( $field_name ) )
391 && ( ! empty( $booking_data['form_data'] ) )
392 && ( ! empty( $booking_data['form_data'][ $field_name ] ) )
393 ) {
394 // FixIn: 8.7.11.4.
395 $fields[ $key_name ] = $booking_data['form_data'][ $field_name ];
396 $fields[ $key_name ] = htmlspecialchars_decode($fields[ $key_name ], ENT_QUOTES );
397 /**
398 * // Convert here from usual symbols to URL symbols https://www.url-encode-decode.com/
399 $fields[ $key_name ] = str_replace( array( '%','#', '+', '&' )
400 , array( '%25','%23', '%2B', '%26')
401 , $fields[ $key_name ]
402 );
403 */
404 $fields[ $key_name ] = urlencode($fields[ $key_name ]);
405 $fields[ $key_name ] = htmlentities($fields[ $key_name ] );
406 $fields[ $key_name ] = htmlspecialchars_decode ( $fields[ $key_name ], ENT_NOQUOTES );
407 }
408 }
409 }
410
411 // Dates -----------------------------------------------------------------------------------------------------------
412 $check_in_timestamp = $check_out_timestamp = '';
413 if ( ! empty( $booking_data[ 'dates_short' ] ) ) {
414
415 /**
416 * All day events, you can use 20161208/20161209 - note that the old google documentation gets it wrong.
417 * You must use the following date as the end date for a one day all day event,
418 * or +1 day to whatever you want the end date to be.
419 */
420
421 $check_in_timestamp = strtotime( $booking_data[ 'dates_short' ][ 0 ], current_time( 'timestamp' ) );
422 $check_out_timestamp = strtotime( $booking_data[ 'dates_short' ][ ( count( $booking_data[ 'dates_short' ] ) - 1 ) ], current_time( 'timestamp' ) );
423
424 if ( trim( substr( $booking_data[ 'dates_short' ][ 0 ], 11 ) ) == '00:00:00' ) {
425 if ( trim( substr( $booking_data[ 'dates_short' ][ ( count( $booking_data[ 'dates_short' ] ) - 1 ) ], 11 ) ) == '00:00:00' ) {
426 $check_in_timestamp = gmdate( "Ymd", $check_in_timestamp ); // All day
427 } else {
428 $check_in_timestamp = gmdate( "Ymd\T000000", $check_in_timestamp ); // All day starting on 00:00:00 // FixIn: 10.0.0.28.
429 }
430 } else {
431 $check_in_timestamp = gmdate( "Ymd\THis", $check_in_timestamp ); //$check_in_timestamp = gmdate( "Ymd\THis\Z", $check_in_timestamp );
432 }
433
434 if ( trim( substr( $booking_data[ 'dates_short' ][ ( count( $booking_data[ 'dates_short' ] ) - 1 ) ], 11 ) ) == '00:00:00' ) {
435 $check_out_timestamp = strtotime( '+1 day', $check_out_timestamp );
436 $check_out_timestamp = gmdate( "Ymd", $check_out_timestamp ); // All day
437 } else {
438 $check_out_timestamp = gmdate( "Ymd\THis", $check_out_timestamp ); //$check_out_timestamp = gmdate( "Ymd\THis\Z", $check_out_timestamp );
439 }
440 }
441
442 // Link -----------------------------------------------------------------------------------------------------------
443 /**
444 * Convert an ISO date/time to a UNIX timestamp
445 function iso_to_ts( $iso ) {
446 sscanf( $iso, "%u-%u-%uT%u:%u:%uZ", $year, $month, $day, $hour, $minute, $second );
447 return mktime( $hour, $minute, $second, $month, $day, $year );
448 20140127T224000Z
449 gmdate("Ymd\THis\Z", time());
450 */
451
452 /**
453 * action: action=TEMPLATE
454 A default required parameter.
455
456 src:
457 Example: src=default%40gmail.com
458 Format: src=text
459 This is not covered by Google help but is an optional parameter in order to add an event to a shared calendar rather than a user's default.
460
461 text:
462 Example: text=Garden%20Waste%20Collection
463 Format: text=text
464 This is a required parameter giving the event title.
465
466 dates:
467 Example: dates=20090621T063000Z/20090621T080000Z (i.e. an event on 21 June 2009 from 7.30am to 9.0am British Summer Time (=GMT+1)).
468 Format: dates=YYYYMMDDToHHMMSSZ/YYYYMMDDToHHMMSSZ
469 This required parameter gives the start and end dates and times (in Greenwich Mean Time) for the event.
470
471 location:
472 Example: location=Home
473 Format: location=text
474 The obvious location field.
475
476 trp:
477 Example: trp=false
478 Format: trp=true/false
479 Show event as busy (true) or available (false)
480
481 sprop:
482 Example: sprop=http%3A%2F%2Fwww.me.org
483 Example: sprop=name:Home%20Page
484 Format: sprop=website and/or sprop=name:website_name
485 */
486
487 //$link_add2gcal = 'http://www.google.com/calendar/event?action=TEMPLATE';
488 //$link_add2gcal .= '&text=' . $fields['title'];
489 $link_add2gcal = 'https://calendar.google.com/calendar/r/eventedit?'; // FixIn: 8.7.3.10.
490 $link_add2gcal .= 'text=' . $fields['title']; // FixIn: 8.7.11.4.
491 $link_add2gcal .= '&dates=' . $check_in_timestamp . '/' . $check_out_timestamp; //$link_add2gcal .= '&dates=[start-custom format='Ymd\\THi00\\Z']/[end-custom format='Ymd\\THi00\\Z']';
492 $link_add2gcal .= '&details=' . ( ( 'On' !== get_bk_option( 'booking_g_cal_export_no_data' ) ) ? $fields['description'] : '' ); //FixIn: 10.3.0.1 // FixIn: 8.7.11.4.
493 $link_add2gcal .= '&location=' . ( ( 'On' !== get_bk_option( 'booking_g_cal_export_no_data' ) ) ? $fields['where'] : '' ); // FixIn: 8.7.11.4.
494 $link_add2gcal .= '&trp=false';
495 if ( ! empty( $params['timezone'] ) ) {
496 $link_add2gcal .= '&ctz=' . str_replace( '%', '%25', $params['timezone'] ); //FixIn: 8.7.3.10 //TimeZone
497 }
498 //$link_add2gcal .= '&sprop=';
499 //$link_add2gcal .= '&sprop=name:';
500
501 return $link_add2gcal;
502 }
503
504 /**
505 * Action: move booking to Trash | Restore
506 *
507 * @param $booking_id_arr array or int of booking ID
508 * @param $params array array of parameters: array( 'user_id' => 1, 'reason_of_action' => 'Because...', 'is_trash' => '1' )
509 *
510 * @return array
511 *
512 * Example:
513 */
514 function wpbc_booking_do_action__trash_booking_or_restore( $booking_id_arr, $params ){
515
516 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
517
518 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
519 if ( ! is_array( $booking_id_arr ) ) {
520 $booking_id_arr = array( $booking_id_arr );
521 }
522 $booking_is_csd = join( ',', $booking_id_arr );
523 $booking_is_csd = wpbc_clean_digit_or_csd( $booking_is_csd );
524
525
526 // Get reason of action --------------------------------------------------------------------------------------------
527 $action_reason = $params['reason_of_action']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't
528
529 // Get reason of action --------------------------------------------------------------------------------------------
530 $is_trash_or_restore = $params['is_trash'];
531
532 // Is send email for this action ----------------------------------------------------------------------------------
533 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
534
535
536 // -----------------------------------------------------------------------------------------------------------------
537
538 if ( empty( $booking_is_csd ) ) {
539 $after_action_result = false;
540 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
541
542 } else {
543 $after_action_result = true;
544 if ( $is_trash_or_restore == '1' ) {
545 $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_is_csd ) ) .'</strong> '
546 . ( ( false === strpos( $booking_is_csd, ',' ) )
547 /* translators: 1: ... */
548 ? sprintf( __( 'Booking has been %1$s trashed %2$s', 'booking' ), '<strong>', '</strong>' )
549 /* translators: 1: ... */
550 : sprintf( __( 'Bookings have been %1$s trashed %2$s', 'booking' ) , '<strong>', '</strong>' )
551 )
552 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_is_csd . '</strong> )</span>';
553 } else {
554 $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_is_csd ) ) .'</strong> '
555 . ( ( false === strpos( $booking_is_csd, ',' ) )
556 /* translators: 1: ... */
557 ? sprintf( __( 'Booking has been set as %1$s restored %2$s', 'booking' ), '<strong>', '</strong>' )
558 /* translators: 1: ... */
559 : sprintf( __( 'Bookings have been set as %1$s restored %2$s', 'booking' ), '<strong>', '</strong>' )
560 )
561 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_is_csd . '</strong> )</span>';
562 }
563 // SQL ---------------------------------------------------------------------------------------------------
564 global $wpdb;
565 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
566 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET trash = %s WHERE booking_id IN ({$booking_is_csd})", $is_trash_or_restore ); // FixIn: 10.12.1.5.
567 if ( $is_trash_or_restore == '1' ) {
568 // Trash
569 $my_trash_date = wpbc_datetime_localized( gmdate( 'Y-m-d H:i:s' ), 'Y-m-d H:i:s' );
570 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
571 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET trash = %s, is_trash = %s WHERE booking_id IN ({$booking_is_csd})", $is_trash_or_restore, $my_trash_date ); // FixIn: 10.12.1.5.
572 } else {
573 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
574 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET trash = %s, is_trash = NULL WHERE booking_id IN ({$booking_is_csd})", $is_trash_or_restore ); // FixIn: 10.12.1.5.
575 }
576
577 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
578 $after_action_result = $wpdb->query( $prepared_sql );
579 if ( false === $after_action_result ) {
580 $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
581 } else {
582 $after_action_result = true;
583 }
584
585 // Update the Hash and Cost of the booking
586 $bk_id_arr = explode(',', $booking_is_csd ); // FixIn: 8.6.1.11.
587 foreach ( $bk_id_arr as $bk_id ) {
588 wpbc_hash__update_booking_hash( $bk_id );
589 }
590
591 // LOG ---------------------------------------------------------------------------------------------------------
592 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
593 wpbc_db__add_log_info( explode( ',', $booking_is_csd ),
594 ( ( $is_trash_or_restore == '1' ) ? __( 'Trashed by:', 'booking' ) : __( 'Restored by:', 'booking' ) )
595 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
596 );
597
598 // :: ? :: Update 'is_new' status of bookings in Database
599 // wpbc_db_update_number_new_bookings( explode( ',', $booking_is_csd ), '0', $params['user_id'] );
600
601 // Just action hook for some other addons
602 do_action( 'wpbc_booking_action__trash', $booking_is_csd, $is_trash_or_restore ); // FixIn: 8.7.6.2.
603
604 // Emails ------------------------------------------------------------------------------------------------------
605 if ( ! empty( $is_send_emeils ) ) {
606
607 if ( $is_trash_or_restore == '1' ) {
608 wpbc_send_email_trash( $booking_is_csd, $is_send_emeils, $action_reason );
609 } else {
610 //wpbc_send_email_approved( $booking_is_csd, $is_send_emeils, $action_reason );
611 //wpbc_send_email_deny( $booking_is_csd, $is_send_emeils, $action_reason );
612 }
613 }
614 }
615
616 return array(
617 'after_action_result' => $after_action_result,
618 'after_action_message' => $after_action_message
619 );
620 }
621
622 /**
623 * Action: set booking as Approved | Pending
624 *
625 * @param $booking_id_arr array or int of booking ID
626 * @param $params array array of parameters: array( 'user_id' => 1, 'reason_of_action' => 'Because...', 'is_approve' => '1' )
627 *
628 * @return array
629 *
630 * Example:
631 * Approved:
632 $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id']
633 , array(
634 'user_id' => $user_id,
635 'reason_of_action' => $request_params['reason_of_action'],
636 'is_approve' => '1'
637 )
638 );
639 * Pending:
640 $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id']
641 , array(
642 'user_id' => $user_id,
643 'reason_of_action' => $request_params['reason_of_action'],
644 'is_approve' => '0'
645 )
646 );
647 */
648 function wpbc_booking_do_action__set_booking_approved_or_pending( $booking_id_arr, $params ){
649
650 /**
651 *
652 * For creation of new bookings or editing use something like this:
653 *
654 // Be sure to make load in Booking Listing this: wp_enqueue_script( 'wpbc-main-client', wpbc_plugin_url( '/js/client.js' ), array( 'wpbc-datepick' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
655 new wpdev_booking(); // Define ability to work with shortcodes
656 $return_sh = do_shortcode('[booking type=1 nummonths=2]');
657 wp_send_json($return_sh); // Send calendar
658 */
659
660 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
661
662 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
663 if ( ! is_array( $booking_id_arr ) ) {
664 $booking_id_arr = array( $booking_id_arr );
665 }
666 $booking_id_csd = join( ',', $booking_id_arr );
667 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
668
669
670 // Get reason of action --------------------------------------------------------------------------------------------
671 $action_reason = $params['reason_of_action']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't
672
673 // Get reason of action --------------------------------------------------------------------------------------------
674 $is_approve_or_pending = $params['is_approve'];
675
676 // Is send email for this action ----------------------------------------------------------------------------------
677 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
678
679
680 // -----------------------------------------------------------------------------------------------------------------
681
682 if ( empty( $booking_id_csd ) ) {
683 $after_action_result = false;
684 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
685
686 } else {
687 $after_action_result = true;
688 if ( $is_approve_or_pending == '1' ) {
689 $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_id_csd ) ) .'</strong> '
690 . ( ( false === strpos( $booking_id_csd, ',' ) )
691 /* translators: 1: ... */
692 ? sprintf( __( 'Booking has been %1$s approved %2$s', 'booking' ), '<strong>', '</strong>' )
693 /* translators: 1: ... */
694 : sprintf( __( 'Bookings have been %1$s approved %2$s', 'booking' ) , '<strong>', '</strong>' )
695 )
696 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>';
697 } else {
698 $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_id_csd ) ) .'</strong> '
699 . ( ( false === strpos( $booking_id_csd, ',' ) )
700 /* translators: 1: ... */
701 ? sprintf( __( 'Booking has been set as %1$s pending %2$s', 'booking' ), '<strong>', '</strong>' )
702 /* translators: 1: ... */
703 : sprintf( __( 'Bookings have been set as %1$s pending %2$s', 'booking' ), '<strong>', '</strong>' )
704 )
705 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>';
706 }
707 // SQL ---------------------------------------------------------------------------------------------------
708 global $wpdb;
709 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
710 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}bookingdates SET approved = %s WHERE booking_id IN ({$booking_id_csd})", $is_approve_or_pending );
711
712 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
713 $after_action_result = $wpdb->query( $prepared_sql );
714 if ( false === $after_action_result ) {
715 $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
716 } else {
717 $after_action_result = true;
718 }
719
720 // LOG ---------------------------------------------------------------------------------------------------------
721 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
722 wpbc_db__add_log_info( explode( ',', $booking_id_csd ),
723 ( ( $is_approve_or_pending == '1' ) ? __( 'Approved by:', 'booking' ) : __( 'Declined by:', 'booking' ) )
724 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
725 );
726
727 // Update 'is_new' status of bookings in Database
728 wpbc_db_update_number_new_bookings( explode( ',', $booking_id_csd ), '0', $params['user_id'] );
729
730 // Just action hook for some other addons
731 do_action( 'wpbc_booking_action__approved', $booking_id_csd, $is_approve_or_pending ); // FixIn: 8.7.6.1.
732
733 // Emails ------------------------------------------------------------------------------------------------------
734 if ( ! empty( $is_send_emeils ) ) {
735
736 if ( $is_approve_or_pending == '1' ) {
737 wpbc_send_email_approved( $booking_id_csd, $is_send_emeils, $action_reason );
738 } else {
739 wpbc_send_email_deny( $booking_id_csd, $is_send_emeils, $action_reason );
740 }
741 }
742
743 // Cancel other pending bookings for the same date ------------------------------------------------------------
744 if ( $is_approve_or_pending == '1' ) {
745 $all_bk_id_what_canceled = apply_bk_filter( 'cancel_pending_same_resource_bookings_for_specific_dates', false, $booking_id_csd );
746 }
747 }
748
749 return array(
750 'after_action_result' => $after_action_result,
751 'after_action_message' => $after_action_message
752 );
753 }
754
755 /**
756 * Action: booking Completely Delete
757 *
758 * @param $booking_id_arr array or int of booking ID
759 * @param $params array array of parameters: array( 'user_id' => 1, 'reason_of_action' => 'Because...' )
760 *
761 * @return array
762 *
763 * Example:
764 */
765 function wpbc_booking_do_action__delete_booking_completely( $booking_id_arr, $params ){
766
767 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
768
769 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
770 if ( ! is_array( $booking_id_arr ) ) {
771 $booking_id_arr = array( $booking_id_arr );
772 }
773 $booking_is_csd = join( ',', $booking_id_arr );
774 $booking_is_csd = wpbc_clean_digit_or_csd( $booking_is_csd );
775
776
777 // Get reason of action --------------------------------------------------------------------------------------------
778 $action_reason = $params['reason_of_action']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't
779
780 // Is send email for this action ----------------------------------------------------------------------------------
781 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
782
783
784 // -----------------------------------------------------------------------------------------------------------------
785
786 if ( empty( $booking_is_csd ) ) {
787 $after_action_result = false;
788 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
789
790 } else {
791 $after_action_result = true;
792 $bookings_count = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_is_csd ) ) .'</strong> ';
793 $after_action_message = $bookings_count . ' '
794 . ( ( false === strpos( $booking_is_csd, ',' ) )
795 /* translators: 1: ... */
796 ? strtolower( sprintf( __( 'Booking has been %1$s deleted %2$s', 'booking' ), '<strong>', '</strong>' ) )
797 /* translators: 1: ... */
798 : strtolower( sprintf( __( 'Bookings have been %1$s deleted %2$s', 'booking' ) , '<strong>', '</strong>' ) )
799 )
800 . ' <span style="font-size:0.9em;">( ID = <strong>' . implode( ', ', explode( ',', $booking_is_csd ) ) . '</strong> )</span>';
801
802 // LOG ---------------------------------------------------------------------------------------------------------
803 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
804 wpbc_db__add_log_info( explode( ',', $booking_is_csd ),
805 __( 'Deleted by:', 'booking' )
806 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
807 );
808
809 // Just action hook for some other addons
810 do_action( 'wpbc_booking_action__delete', $booking_is_csd ); // FixIn: 8.7.6.3.
811
812 // Emails ------------------------------------------------------------------------------------------------------
813 if ( ! empty( $is_send_emeils ) ) {
814
815 wpbc_send_email_deleted( $booking_is_csd, $is_send_emeils, $action_reason );
816 }
817
818 // SQL ---------------------------------------------------------------------------------------------------
819 global $wpdb;
820
821 // Dates
822 $prepared_sql = "DELETE FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_is_csd})";
823 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
824 $after_action_result = $wpdb->query( $prepared_sql );
825 if ( false === $after_action_result ) {
826 $after_action_message = 'Error during deleting dates in DB. File:' . __FILE__ . ' on line: ' . __LINE__;
827 } else {
828 $after_action_result = true;
829 }
830 // Bookings
831 $prepared_sql = "DELETE FROM {$wpdb->prefix}booking WHERE booking_id IN ({$booking_is_csd})";
832 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
833 $after_action_result = $wpdb->query( $prepared_sql );
834 if ( false === $after_action_result ) {
835 $after_action_message = 'Error during deleting bookings in DB. File:' . __FILE__ . ' on line: ' . __LINE__;
836 } else {
837 $after_action_result = true;
838 }
839
840 }
841
842 return array(
843 'after_action_result' => $after_action_result,
844 'after_action_message' => $after_action_message
845 );
846 }
847
848 /**
849 * Action: set booking as Read (Old) | Unread (New)
850 *
851 * @param $booking_id_arr array or int of booking ID
852 * @param $params array array of parameters: array( 'user_id' => 1, 'is_new' => '1' )
853 *
854 * @return array
855 *
856 * Example:
857 $action_result = wpbc_booking_do_action__set_booking_as_read_unread( $request_params['booking_id']
858 , array(
859 'user_id' => $user_id,
860 'is_new' => '0'
861 )
862 );
863
864 */
865 function wpbc_booking_do_action__set_booking_as_read_unread( $booking_id_arr, $params ){
866
867 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
868
869 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
870 if ( ! is_array( $booking_id_arr ) ) {
871 $booking_id_arr = array( $booking_id_arr );
872 }
873 $booking_id_csd = join( ',', $booking_id_arr );
874 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
875
876 // Get reason of action --------------------------------------------------------------------------------------------
877 $is_new = $params['is_new'];
878
879 // Is send email for this action ----------------------------------------------------------------------------------
880 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
881
882 // -----------------------------------------------------------------------------------------------------------------
883
884 if ( empty( $booking_id_csd ) ) {
885 $after_action_result = false;
886 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
887
888 } else {
889 $after_action_result = true;
890 if ( $is_new == '1' ) {
891 $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) )
892 /* translators: 1: ... */
893 ? sprintf( __( 'Booking has been set as %1$s new %2$s', 'booking' ), '<strong>', '</strong>' )
894 /* translators: 1: ... */
895 : sprintf( __( 'Bookings have been set as %1$s new %2$s', 'booking' ) , '<strong>', '</strong>' )
896 )
897 . ' <span style="font-size:0.9em;">( ID = <strong>' . (( '-1' == $booking_id_csd ) ? __( 'all', 'booking' ) : $booking_id_csd) . '</strong> )</span>';
898 } else {
899 $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) )
900 /* translators: 1: ... */
901 ? sprintf( __( 'The booking has been marked as %1$s read %2$s', 'booking' ), '<strong>', '</strong>' )
902 /* translators: 1: ... */
903 : sprintf( __( 'Bookings have been marked as %1$s read %2$s', 'booking' ), '<strong>', '</strong>' )
904 )
905 . ' <span style="font-size:0.9em;">( ID = <strong>' . (( '-1' == $booking_id_csd ) ? __( 'all', 'booking' ) : $booking_id_csd) . '</strong> )</span>';
906 }
907 // SQL ---------------------------------------------------------------------------------------------------
908 global $wpdb;
909 if ('-1' == $booking_id_csd ){
910 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET is_new = %s", $is_new ); // FixIn: 10.12.1.5.
911
912 $prepared_sql .= " WHERE ( 1 = 1 ) ";
913 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
914 $prepared_sql = apply_bk_filter('update_where_sql_for_getting_bookings_in_multiuser', $prepared_sql );
915 } else {
916 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
917 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET is_new = %s WHERE booking_id IN ({$booking_id_csd})", $is_new ); // FixIn: 10.12.1.5.
918 }
919 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
920 $after_action_result = $wpdb->query( $prepared_sql );
921 if ( false === $after_action_result ) {
922 $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
923 } else {
924 $after_action_result = true;
925 }
926
927 // LOG ---------------------------------------------------------------------------------------------------------
928 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
929 wpbc_db__add_log_info( explode( ',', $booking_id_csd ),
930 ( ( $is_new == '1' ) ? __( 'Set as unread by:', 'booking' ) : __( 'Set as read by:', 'booking' ) )
931 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
932 );
933
934 // Just action hook for some other addons
935 do_action( 'wpbc_booking_action__changed_new_status', $booking_id_csd, $is_new ); // FixIn: 8.7.6.1.
936
937 // Emails ------------------------------------------------------------------------------------------------------
938 if ( ! empty( $is_send_emeils ) ) {
939
940 if ( $is_new == '1' ) {
941 //wpbc_send_email_approved( $booking_id_csd, $is_send_emeils, $action_reason );
942 } else {
943 //wpbc_send_email_deny( $booking_id_csd, $is_send_emeils, $action_reason );
944 }
945 }
946 }
947
948 return array(
949 'after_action_result' => $after_action_result,
950 'after_action_message' => $after_action_message
951 );
952 }
953
954 /**
955 * Action: Emty Trash
956 *
957 * @param $params array array of parameters: array( 'user_id' => 1 )
958 *
959 * @return array
960 *
961 * Example:
962 */
963 function wpbc_booking_do_action__empty_trash( $params ){
964
965 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
966
967 // Is send email for this action ----------------------------------------------------------------------------------
968 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
969
970 // Get bookings ID to delete -------------------------------------------------------------------------------
971 global $wpdb;
972
973 $sql = "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.trash = 1"; // FixIn: 10.12.1.5.
974
975 $sql = apply_bk_filter( 'update_where_sql_for_getting_bookings_in_multiuser', $sql, $params['user_id'] ); // Get booking resources of this user only: $user_id
976
977 $max_bookings_to_erase = 1000;
978 $sql .= " LIMIT 0, " . $max_bookings_to_erase;
979
980 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
981 $bookings_in_trash = $wpdb->get_results( $sql );
982
983 $bookings_id_in_trash_arr = array();
984
985 foreach ( $bookings_in_trash as $booking_obj ) {
986 $bookings_id_in_trash_arr[] = $booking_obj->booking_id;
987 }
988 $booking_is_csd = implode( ',', $bookings_id_in_trash_arr );
989
990 // Empty trash ------------------------------------------------------------------------------------------------
991
992 if ( empty( $booking_is_csd ) ) {
993 $after_action_result = false;
994 $after_action_message = __( 'No bookings in trash to erase.', 'booking' );
995
996 } else {
997 $after_action_result = true;
998 if ( count( $bookings_id_in_trash_arr ) < $max_bookings_to_erase ) {
999 $after_action_message = sprintf( __( 'Trash has been erased.', 'booking' ) , '<strong>', '</strong>' )
1000 . ' <span style="font-size:0.9em;">( ID = <strong>' . substr( $booking_is_csd, 0 , 500 ) . '</strong> )</span>';
1001 } else {
1002 /* translators: 1: ... */
1003 $after_action_message = sprintf( __( 'From trash has been erased %s bookings.', 'booking' ) , '<strong> ' . count( $bookings_id_in_trash_arr ) . ' </strong> ' ) ;
1004 }
1005
1006 // LOG -----------------------------------------------------------------------------------------------------
1007 // $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1008 // wpbc_db__add_log_info( explode( ',', $booking_is_csd ),
1009 // __( 'Deleted by:', 'booking' )
1010 // . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1011 // );
1012
1013 // Just action hook for some other addons
1014 do_action( 'wpbc_booking_action__empty_trash' ); // FixIn: 8.7.6.3.
1015
1016 // Emails ------------------------------------------------------------------------------------------------------
1017 if ( ! empty( $is_send_emeils ) ) {
1018
1019 // wpbc_send_email_deleted( $booking_is_csd, $is_send_emeils, __( 'Empty Trash', 'booking' ) );
1020 }
1021
1022 // SQL ---------------------------------------------------------------------------------------------------
1023
1024 // Dates
1025 $prepared_sql = "DELETE FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_is_csd})";
1026 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1027 $after_action_result = $wpdb->query( $prepared_sql );
1028 if ( false === $after_action_result ) {
1029 $after_action_message = 'Error during deleting dates in DB. File:' . __FILE__ . ' on line: ' . __LINE__;
1030 } else {
1031 $after_action_result = true;
1032 }
1033 // Bookings
1034 $prepared_sql = "DELETE FROM {$wpdb->prefix}booking WHERE booking_id IN ({$booking_is_csd})";
1035 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1036 $after_action_result = $wpdb->query( $prepared_sql );
1037 if ( false === $after_action_result ) {
1038 $after_action_message = 'Error during deleting bookings in DB. File:' . __FILE__ . ' on line: ' . __LINE__;
1039 } else {
1040 $after_action_result = true;
1041 }
1042
1043 }
1044
1045 return array(
1046 'after_action_result' => $after_action_result,
1047 'after_action_message' => $after_action_message
1048 );
1049 }
1050
1051 /**
1052 * Action: save booking Remark
1053 *
1054 * @param $booking_id_arr array or int of booking ID
1055 * @param $params array array of parameters: array( 'user_id' => 1, 'remark' => 'Because...')
1056 *
1057 * @return array
1058 *
1059 * Example:
1060 */
1061 function wpbc_booking_do_action__set_booking_note( $booking_id_arr, $params ){
1062
1063 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
1064
1065 // Get ID list of bookings, like '1' or '3,7,9' ------------------------------------------------------------
1066 if ( ! is_array( $booking_id_arr ) ) {
1067 $booking_id_arr = array( $booking_id_arr );
1068 }
1069 $booking_id_csd = join( ',', $booking_id_arr );
1070 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
1071
1072 // Get remark --------------------------------------------------------------------------------------------------
1073 $remark_text = $params['remark']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't
1074
1075 // Is send email for this action ------------------------------------------------------------------------------
1076 // $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1077
1078
1079 // -----------------------------------------------------------------------------------------------------------------
1080
1081 if ( empty( $booking_id_csd ) ) {
1082 $after_action_result = false;
1083 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
1084
1085 } else {
1086 $after_action_result = true;
1087 $after_action_message = __( 'Note has been saved', 'booking' )
1088 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>';
1089 // SQL ---------------------------------------------------------------------------------------------------
1090 global $wpdb;
1091 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1092 $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET remark = %s WHERE booking_id IN ({$booking_id_csd})", $remark_text );
1093 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1094 $after_action_result = $wpdb->query( $prepared_sql );
1095 if ( false === $after_action_result ) {
1096 $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
1097 } else {
1098 $after_action_result = true;
1099 }
1100
1101 // LOG ---------------------------------------------------------------------------------------------------------
1102 if (0) {
1103 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1104 wpbc_db__add_log_info( explode( ',', $booking_id_csd ),
1105 __( 'Note saved by:', 'booking' )
1106 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1107 );
1108 }
1109
1110 // Just action hook for some other addons
1111 do_action( 'wpbc_booking_action__note_saved', $booking_id_csd, $remark_text );
1112
1113 // Emails ------------------------------------------------------------------------------------------------------
1114 if ( 0 ) {
1115 if ( ! empty( $is_send_emeils ) ) {
1116 wpbc_send_email_approved( $booking_id_csd, $is_send_emeils, $remark_text );
1117 }
1118 }
1119 }
1120
1121 return array(
1122 'after_action_result' => $after_action_result,
1123 'after_action_message' => $after_action_message
1124 );
1125 }
1126
1127 /**
1128 * Action: change Booking Resource
1129 *
1130 * @param $booking_id_arr array or int of booking ID
1131 * @param $selected_resource_id int of booking resource
1132 * @param $params array array of parameters: array( 'user_id' => 1 )
1133 *
1134 * @return array
1135 *
1136 * Example:
1137 */
1138 function wpbc_booking_do_action__change_booking_resource( $booking_id_arr, $selected_resource_id, $params ) {
1139
1140 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
1141
1142 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
1143 if ( ! is_array( $booking_id_arr ) ) {
1144 $booking_id_arr = array( $booking_id_arr );
1145 }
1146 $booking_id_csd = join( ',', $booking_id_arr );
1147 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
1148
1149 // ID of booking resource ------------------------------------------------------------------------------------------
1150 $selected_resource_id = intval($selected_resource_id);
1151
1152 // Is send email for this action ----------------------------------------------------------------------------------
1153 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1154
1155 // -----------------------------------------------------------------------------------------------------------------
1156
1157 if ( empty( $booking_id_csd ) ) {
1158 $after_action_result = false;
1159 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
1160
1161 } else {
1162 $after_action_result = true;
1163
1164 $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) )
1165 /* translators: 1: ... */
1166 ? sprintf( __( 'Booking has been changed %1$s booking resource %2$s', 'booking' ), '<strong>', '</strong>' )
1167 /* translators: 1: ... */
1168 : sprintf( __( 'Bookings have been changed %1$s booking resource %2$s', 'booking' ), '<strong>', '</strong>' )
1169 )
1170 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>';
1171
1172
1173 $work_booking_id_arr = explode( ',', $booking_id_csd );
1174
1175 foreach ( $work_booking_id_arr as $selected_booking_id ) {
1176
1177 if ( 'On' !== get_bk_option('booking_change_resource_skip_checking') ) {
1178 $resource_change_check = apply_filters( 'wpbc_booking_validate_resource_change', true, $selected_booking_id, $selected_resource_id );
1179 if ( is_wp_error( $resource_change_check ) ) {
1180 $after_action_result = false;
1181 $after_action_message = $resource_change_check->get_error_message();
1182 continue;
1183 }
1184 }
1185 // SQL ---------------------------------------------------------------------------------------------------
1186 list( $after_action_result, $after_action_message, $formdata_new ) = wpbc__sql__change_booking_resource_for_booking( $selected_booking_id, $selected_resource_id );
1187
1188 if ( $after_action_result ) {
1189 // LOG ---------------------------------------------------------------------------------------------------------
1190 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1191 wpbc_db__add_log_info( explode( ',', $selected_booking_id ),
1192 __( 'Booking resource changed by:', 'booking' )
1193 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1194 );
1195
1196 // Just action hook for some other addons
1197 do_action( 'wpbc_booking_action__change_booking_resource', $selected_booking_id, $selected_resource_id );
1198
1199 // Emails ------------------------------------------------------------------------------------------------------
1200 if ( ! empty( $is_send_emeils ) ) {
1201 wpbc_send_email_modified( $selected_booking_id, $selected_resource_id, $formdata_new );
1202 }
1203 }
1204 }
1205 }
1206
1207 return array(
1208 'after_action_result' => $after_action_result,
1209 'after_action_message' => $after_action_message
1210 );
1211
1212 }
1213
1214 /**
1215 * Change booking resource for specific booking -- SQL manipulation
1216 * @param $selected_booking_id
1217 * @param $selected_resource_id
1218 *
1219 * @return array
1220 */
1221 function wpbc__sql__change_booking_resource_for_booking( $selected_booking_id, $selected_resource_id ){
1222
1223 global $wpdb;
1224
1225 $booking_id = intval( $selected_booking_id );
1226 $resource_id = intval( $selected_resource_id );
1227 $db_form_data_new = '';
1228
1229 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1230 // 1.Get dates of SOURCE booking
1231 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1232 if ( 1 ) {
1233 // 1.1.Get booking data of SOURCE booking
1234 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE booking_id = %d ", $booking_id );
1235
1236 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1237 $res = $wpdb->get_row( $sql );
1238
1239 $db_form_data_old = $res->form;
1240 $resource_id_old = $res->booking_type;
1241
1242 // 1.2. Get dates of SOURCE booking
1243 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bookingdates as dt WHERE booking_id = %d ORDER BY booking_date ASC ", $booking_id );
1244 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1245 $old_resource_dates_array = $wpdb->get_results( $sql );
1246 }
1247
1248
1249 //TODO: 2023-10-03 14:49 this is new workflow have to be:
1250 if (0){
1251 $booking_p = array(
1252 'dates' => TRANSFORM_IT( $old_resource_dates_array ) // -> array( '2017-06-23 14:00:01', '2017-06-24 00:00:00', '2017-06-25', '2017-06-26 12:00:02' )
1253 , 'resource_id' => $resource_id
1254 , 'params' => array() // 'is_use_booking_recurrent_time' => false ) // Commented, because get from Booking > Settings General page
1255 );
1256 $is_dates_booked = wpbc_api_is_dates_booked( $booking_p[ 'dates' ], $booking_p[ 'resource_id' ], $booking_p[ 'params' ] );
1257 }
1258
1259 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1260 // 2. Get bookings of selected booking resource - checking if some dates there is booked or not
1261 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1262 $exist_dates_results = wpbc_get_booking_dates_in_resource_for_folowing_dates( $old_resource_dates_array , $resource_id );
1263
1264
1265 if ( ( count( $exist_dates_results ) == 3 ) && ( false === $exist_dates_results[0] ) ){
1266 // // ERROR :: number of check in/dates does not equal to number of check out dates.
1267 return $exist_dates_results;
1268 }
1269
1270 if ( get_bk_option('booking_change_resource_skip_checking') === 'On' ) { // FixIn: 8.4.5.4.
1271 $is_date_time_booked = false;
1272 } else {
1273 $is_date_time_booked = wpbc_check_dates_intersections( $old_resource_dates_array, $exist_dates_results );
1274 }
1275
1276 if ( $is_date_time_booked ) {
1277
1278 $after_action_result = false;
1279 $after_action_message = __( 'Warning! The resource was not changed. Current dates are already booked there.', 'booking' );
1280
1281 } else { // Possible to change
1282
1283 $db_form_data_new = wpbc_update_resource_id_in_dbformatted_booking_data( $db_form_data_old, $resource_id_old, $resource_id );
1284
1285 // Update // FixIn: 10.12.1.5.
1286 $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET form=%s, booking_type=%d WHERE booking_id=%d;"
1287 , $db_form_data_new, $resource_id, $booking_id );
1288 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1289 if ( false === $wpdb->query( $update_sql ) ) {
1290 $after_action_result = false;
1291 $after_action_message = get_debuge_error( 'Error during updating booking reource type in BD', __FILE__, __LINE__ );
1292
1293 return array( $after_action_result, $after_action_message, $db_form_data_new );
1294 }
1295
1296
1297 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1298 $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}bookingdates SET type_id=NULL WHERE booking_id=%d ", $booking_id );
1299 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1300 if ( false === $wpdb->query( $update_sql ) ) {
1301 $after_action_result = false;
1302 $after_action_message = get_debuge_error( 'Error during updating dates type in BD', __FILE__, __LINE__ );
1303
1304 return array( $after_action_result, $after_action_message, $db_form_data_new );
1305 }
1306 }
1307
1308 $booking_resources_arr = wpbc_ajx_get_all_booking_resources_arr();
1309 $after_action_result = true;
1310 /* translators: 1: ... */
1311 $after_action_message = sprintf( __( 'Booking %1$s has been changed booking resource from %2$s to %3$s', 'booking' )
1312 , '<strong>[ID=' . $booking_id . ']</strong>'
1313 , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id_old ]['title'] ) . '</strong>'
1314 , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) . '</strong>'
1315 );
1316
1317 // Everything Cool :) - booking resource changed
1318 }
1319
1320 return array( $after_action_result, $after_action_message , $db_form_data_new );
1321 }
1322
1323 /**
1324 * Get booking dates (bookings obj) of selected booking resource - checking if some dates there is booked or not
1325 *
1326 * @param $old_resource_dates_array array of OBJ with ..->booking_date
1327 * @param int $resource_id Resource ID, where we get dates.
1328 *
1329 * @return array array of booking OBJ with ..->booking_date
1330 */
1331 function wpbc_get_booking_dates_in_resource_for_folowing_dates( $old_resource_dates_array , $resource_id ){
1332
1333 global $wpdb;
1334
1335 $dates_sql_between = '';
1336 $check_in_dates_arr = array();
1337 $check_out_dates_arr = array();
1338
1339 if ( 'On' === get_bk_option( 'booking_recurrent_time' ) ) { // If we are using recurrent time slots ?
1340
1341 foreach ( $old_resource_dates_array as $k => $v ) {
1342
1343 if ( ':02' == substr( $v->booking_date, - 3 ) ) {
1344 $check_out_dates_arr[] = $v->booking_date;
1345 }
1346 if ( ':01' == substr( $v->booking_date, - 3 ) ) {
1347 $check_in_dates_arr[] = $v->booking_date;
1348 }
1349 }
1350
1351 if ( count( $check_out_dates_arr ) == count( $check_in_dates_arr ) ) {
1352 $dates_sql_between_arr = array();
1353 foreach ( $check_in_dates_arr as $k => $v ) {
1354
1355 $dates_sql_between_arr [] = ' ( dt.booking_date BETWEEN "' . $check_in_dates_arr[ $k ] . '" AND "' . $check_out_dates_arr[ $k ] . '" ) ';
1356 }
1357 $dates_sql_between = implode( 'OR', $dates_sql_between_arr );
1358
1359 //TODO: remove (), if only 1 element in array
1360
1361 } else {
1362 // ERROR :: number of check in/dates does not equal to number of check out dates.
1363 $after_action_result = false;
1364 $after_action_message = '<strong>Error</strong>. Number of check in times of booking dates does not equal to number of check out days.'
1365 . '<br>Check in dates: ' . implode( ', ', $check_in_dates_arr )
1366 . '<br>Check out dates: ' . implode( ', ', $check_out_dates_arr );
1367
1368 return array( $after_action_result, $after_action_message, '' );
1369 }
1370 }
1371
1372 if ( '' == $dates_sql_between ) {
1373
1374 $temp_check_in = $old_resource_dates_array[0]->booking_date;
1375 $temp_check_out = $old_resource_dates_array[ ( count( $old_resource_dates_array ) - 1 ) ]->booking_date;
1376
1377 if ( ':02' != substr( $temp_check_out, - 3 ) ) {
1378 $temp_check_out = gmdate( 'Y-m-d H:i:s', strtotime( '+1 day -1 second', strtotime( $temp_check_out ) ) );
1379 }
1380
1381 $dates_sql_between .= ' dt.booking_date BETWEEN "' . $temp_check_in . '" AND "' . $temp_check_out . '" ';
1382 }
1383
1384
1385 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk
1386 INNER JOIN {$wpdb->prefix}bookingdates as dt
1387 ON bk.booking_id = dt.booking_id
1388 WHERE bk.trash != 1 AND bk.booking_type = %d", $resource_id );
1389 $sql .= " AND ( {$dates_sql_between} ) ";
1390
1391 // In BL version its does not check for booking belonging to several booking resources
1392 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1393 $sql .= " OR bk.booking_id IN ( "
1394 . " SELECT DISTINCT booking_id FROM {$wpdb->prefix}bookingdates as dtt
1395 WHERE dtt.type_id = {$resource_id} "
1396 //."AND DATE(dt.booking_date) IN ( {$dates_string} )"
1397 . " AND ( " . str_replace( 'dt.', 'dtt.', $dates_sql_between ) . " ) "
1398 . ") ";
1399 }
1400 $sql .= " ORDER BY bk.booking_id DESC, dt.booking_date ASC ";
1401
1402 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1403 $exist_dates_results = $wpdb->get_results( $sql );
1404
1405 // We have found only intersected dates. Now we need to get all dates from such bookings, for having correct "Start and end time times for the booking"
1406 // and does not add some "start time at the begining of the day inside of wpbc_check_dates_intersections( ) function
1407 if ( count( $exist_dates_results ) > 0 ) {
1408
1409 // Get ID of all bookings that inside of this interval
1410 $my_booking_id_arr = [];
1411 foreach ( $exist_dates_results as $key => $booking_obj ) {
1412 $my_booking_id_arr[] = $booking_obj->booking_id;
1413 }
1414 // Get all dates of such bookings (not only intersected!
1415 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk
1416 INNER JOIN {$wpdb->prefix}bookingdates as dt
1417 ON bk.booking_id = dt.booking_id
1418 WHERE bk.booking_id IN (" . implode( ',', $my_booking_id_arr ) . ") AND bk.trash != 1 AND bk.booking_type = %d", $resource_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
1419 $sql .= " ORDER BY bk.booking_id DESC, dt.booking_date ASC ";
1420
1421 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1422 $exist_dates_results = $wpdb->get_results( $sql );
1423 }
1424
1425 return $exist_dates_results;
1426 }
1427
1428 /**
1429 * Update "Content of booking fields data" from old booking resource id SUFFIX to new booking Resource ID
1430 *
1431 * @param string $db_form_data_old
1432 * @param int $resource_id_old
1433 * @param int $resource_id_new
1434 *
1435 * @return void
1436 */
1437 function wpbc_update_resource_id_in_dbformatted_booking_data( $db_form_data_old, $resource_id_old, $resource_id_new ) {
1438
1439 $db_form_data_new = array();
1440
1441 $form_data_arr = explode( '~', $db_form_data_old );
1442 $fields_count = count( $form_data_arr );
1443
1444 for ( $i = 0; $i < $fields_count; $i ++ ) {
1445
1446 list( $type, $element_name, $value ) = explode( '^', $form_data_arr[ $i ] );
1447
1448 if ( substr( $element_name, - 2 ) == '[]' ) {
1449 $element_name = str_replace( '[]', '', $element_name );
1450 }
1451
1452 $element_name = substr( $element_name, 0, - 1 * strlen( $resource_id_old ) ) . $resource_id_new; // Change resource ID in field
1453
1454 $db_form_data_new[] = $type . '^' . $element_name . '^' . $value;
1455 }
1456
1457 return implode( '~', $db_form_data_new );
1458 }
1459
1460 /**
1461 * Action: Duplicate Booking into other Resource
1462 *
1463 * @param $booking_id_arr array or int of booking ID
1464 * @param $selected_resource_id int of booking resource
1465 * @param $params array array of parameters: array( 'user_id' => 1 )
1466 *
1467 * @return array
1468 *
1469 * Example:
1470 */
1471 function wpbc_booking_do_action__duplicate_booking_to_other_resource( $booking_id_arr, $selected_resource_id, $params ) {
1472
1473 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
1474
1475 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
1476 if ( ! is_array( $booking_id_arr ) ) {
1477 $booking_id_arr = array( $booking_id_arr );
1478 }
1479 $booking_id_csd = join( ',', $booking_id_arr );
1480 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
1481
1482 // ID of booking resource ------------------------------------------------------------------------------------------
1483 $selected_resource_id = intval($selected_resource_id);
1484
1485 // Is send email for this action ----------------------------------------------------------------------------------
1486 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1487
1488 // -----------------------------------------------------------------------------------------------------------------
1489
1490 if ( empty( $booking_id_csd ) ) {
1491 $after_action_result = false;
1492 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
1493
1494 } else {
1495 $after_action_result = true;
1496
1497 $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) )
1498 /* translators: 1: ... */
1499 ? sprintf( __( 'Booking has been %1$s duplicated %2$s', 'booking' ), '<strong>', '</strong>' )
1500 /* translators: 1: ... */
1501 : sprintf( __( 'Bookings have been %1$s duplicated %2$s', 'booking' ), '<strong>', '</strong>' )
1502 )
1503 . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>';
1504
1505
1506 $work_booking_id_arr = explode( ',', $booking_id_csd );
1507
1508 foreach ( $work_booking_id_arr as $selected_booking_id ) {
1509
1510 // SQL ---------------------------------------------------------------------------------------------------
1511 list( $after_action_result, $after_action_message, $formdata_new ) = wpbc__sql__duplicate_booking_to_other_resource_for_booking( $selected_booking_id, $selected_resource_id, $params );
1512
1513 if ( $after_action_result ) {
1514 // LOG ---------------------------------------------------------------------------------------------------------
1515 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1516 wpbc_db__add_log_info( explode( ',', $selected_booking_id ),
1517 __( 'Booking resource changed by:', 'booking' )
1518 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1519 );
1520
1521 // Just action hook for some other addons
1522 do_action( 'wpbc_booking_action__duplicate_booking_to_other_resource', $selected_booking_id, $selected_resource_id );
1523
1524 // Emails ------------------------------------------------------------------------------------------------------
1525 if ( ! empty( $is_send_emeils ) ) {
1526 // We are sending emails about the new booking, if we have created it.
1527 // wpbc_send_email_modified( $selected_booking_id, $selected_resource_id, $formdata_new );
1528 }
1529 }
1530 }
1531 }
1532
1533 return array(
1534 'after_action_result' => $after_action_result,
1535 'after_action_message' => $after_action_message
1536 );
1537
1538 }
1539
1540 /**
1541 * Duplicate booking in another resource -- SQL manipulation
1542 * @param $selected_booking_id
1543 * @param $selected_resource_id
1544 *
1545 * @return array
1546 */
1547 function wpbc__sql__duplicate_booking_to_other_resource_for_booking( $selected_booking_id, $selected_resource_id, $params ){
1548 global $wpdb;
1549
1550 $booking_id = intval( $selected_booking_id );
1551 $resource_id = intval( $selected_resource_id );
1552 $db_form_data_new = '';
1553 $booking_resources_arr = wpbc_ajx_get_all_booking_resources_arr();
1554
1555 $is_send_emails = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1556
1557 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1558 // 1.Get dates of SOURCE booking
1559 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1560 if ( 1 ) {
1561 // 1.1.Get booking data of SOURCE booking
1562 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE booking_id = %d ", $booking_id );
1563 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1564 $res = $wpdb->get_row( $sql );
1565 $db_form_data_old = $res->form;
1566 $resource_id_old = $res->booking_type;
1567
1568 // 1.2. Get dates of SOURCE booking
1569 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bookingdates as dt WHERE booking_id = %d ORDER BY booking_date ASC ", $booking_id );
1570 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1571 $old_resource_dates_array = $wpdb->get_results( $sql );
1572 }
1573
1574 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1575 // 2. Get bookings of selected booking resource - checking if some dates there is booked or not
1576 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1577 $exist_dates_results = wpbc_get_booking_dates_in_resource_for_folowing_dates( $old_resource_dates_array , $resource_id );
1578
1579 if ( ( count( $exist_dates_results ) == 3 ) && ( false === $exist_dates_results[0] ) ){
1580 // // ERROR :: number of check in/dates does not equal to number of check out dates.
1581 return $exist_dates_results;
1582 }
1583
1584 if ( get_bk_option('booking_change_resource_skip_checking') === 'On' ) { // FixIn: 8.4.5.4.
1585 $is_date_time_booked = false;
1586 } else {
1587 $is_date_time_booked = wpbc_check_dates_intersections( $old_resource_dates_array, $exist_dates_results );
1588 }
1589
1590 if ( $is_date_time_booked ) {
1591
1592 $after_action_result = false;
1593 $after_action_message = '<strong>' . esc_html__( 'Warning', 'booking' ) . '!</strong> '
1594 /* translators: 1: ... */
1595 . sprintf( __( 'Booking %1$s has not been duplicated in booking resource %2$s. Current dates are already booked there.' , 'booking' )
1596 , '<strong style="font-size:0.9em;">[ID=' . $booking_id . ']</strong>'
1597 , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) . '</strong>'
1598 );
1599
1600 } else { // Possible to change
1601
1602 $db_form_data_new = wpbc_update_resource_id_in_dbformatted_booking_data( $db_form_data_old, $resource_id_old, $resource_id );
1603 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Recommended
1604 $wpdev_active_locale = isset( $_REQUEST['wpbc_ajx_locale'] ) ? sanitize_text_field( $_REQUEST['wpbc_ajx_locale'] ) : 'en_US';
1605
1606
1607 // Change dates from DateObj( $selected_date->booking_date = '2015-10-17' ) to array ( '17.10.2015' )
1608 $my_dates_for_sql = array();
1609 foreach ($old_resource_dates_array as $selected_date) {
1610 $selected_date = explode( '-', $selected_date->booking_date );
1611 $my_dates_for_sql[] = sprintf( "%02d.%02d.%04d", $selected_date[2], $selected_date[1], $selected_date[0] );
1612 }
1613 $my_dates_for_sql = implode( ', ', $my_dates_for_sql );
1614
1615 // Create a new booking
1616 $request_save_params = array(
1617 'resource_id' => $resource_id, // 2
1618 'dates_ddmmyy_csv' => $my_dates_for_sql, // '04.10.2023, 05.10.2023, 06.10.2023'
1619 'form_data' => $db_form_data_new, // 'text^cost_hint2^150.00฿~selectbox-multiple^rangetime2[]^14:00...'
1620 'booking_hash' => '', // 'sdfsf34534rf'
1621 'custom_form' => '', // 'custom_form_name'
1622 'is_emails_send' => $is_send_emails, // 0 | 1
1623 'is_show_payment_form' => 0 // 0 | 1
1624 // 'request_uri' => $_SERVER['HTTP_REFERER']
1625 // 'user_id' => wpbc_get_current_user_id()
1626 // 'sync_gid' => ''
1627 // 'is_approve_booking' => 0
1628 );
1629 if ( function_exists( 'wpbc_appointment_services_get_booking_service_id' ) ) {
1630 $duplicated_service_id = wpbc_appointment_services_get_booking_service_id( $booking_id );
1631 if ( $duplicated_service_id ) {
1632 $request_save_params['service_id'] = $duplicated_service_id;
1633 if ( function_exists( 'wpbc_booking_appointment_encode_submission_context' ) ) {
1634 $request_save_params['appointment_context_token'] = wpbc_booking_appointment_encode_submission_context( array(), $duplicated_service_id, $resource_id );
1635 }
1636 }
1637 }
1638 $booking_save_arr = wpbc_booking_save( $request_save_params );
1639
1640 if ( 'ok' === $booking_save_arr['ajx_data']['status'] ) { // Everything Cool :) - booking has been duplicated
1641
1642 $booking_id_new = $booking_save_arr['booking_id'];
1643 $after_action_result = true;
1644 /* translators: 1: ... */
1645 $after_action_message = sprintf( __( 'Booking %1$s has been duplicated in booking resource %2$s. New booking %3$s.', 'booking' )
1646 , '<strong style="font-size:0.9em;">[ID=' . $booking_id . ']</strong>'
1647 , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) . '</strong>'
1648 , '<strong style="font-size:0.9em;">[ID=' . $booking_id_new . ']</strong>'
1649 );
1650 } else { // Error
1651 $after_action_result = false;
1652 $after_action_message = $booking_save_arr['ajx_data']['ajx_after_action_message'];
1653 }
1654 }
1655
1656 return array( $after_action_result, $after_action_message , $db_form_data_new );
1657 }
1658
1659 /**
1660 * Action: Set payment status for the booking
1661 *
1662 * @param $booking_id_arr array or int of booking ID
1663 * @param $selected_payment_status string payment status of booking
1664 * @param $params array array of parameters: array( 'user_id' => 1 )
1665 *
1666 * @return array
1667 *
1668 * Example:
1669 */
1670 function wpbc_booking_do_action__set_payment_status( $booking_id_arr, $selected_payment_status, $params ) {
1671
1672 global $wpdb;
1673
1674 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
1675
1676 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
1677 if ( ! is_array( $booking_id_arr ) ) {
1678 $booking_id_arr = array( $booking_id_arr );
1679 }
1680 $booking_id_csd = join( ',', $booking_id_arr );
1681 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
1682
1683
1684 // Is send email for this action ----------------------------------------------------------------------------------
1685 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1686
1687 // -----------------------------------------------------------------------------------------------------------------
1688
1689 if ( empty( $booking_id_csd ) ) {
1690 $after_action_result = false;
1691 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
1692
1693 } else {
1694 $after_action_result = true;
1695 $after_action_message = '';
1696
1697 $work_booking_id_arr = explode( ',', $booking_id_csd );
1698
1699 foreach ( $work_booking_id_arr as $selected_booking_id ) {
1700
1701 // SQL ---------------------------------------------------------------------------------------------------
1702 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.booking_id= %d ", $selected_booking_id );
1703 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1704 $result_bk = $wpdb->get_results( $sql );
1705
1706 $old_pay_status = '';
1707
1708 if ( ( 0 == count( $result_bk ) ) ) {
1709 // Error
1710 $after_action_result = false;
1711 /* translators: 1: ... */
1712 $after_action_message .= sprintf( __( 'There is no booking %s', 'booking' )
1713 , ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'
1714 );
1715 } else {
1716 $old_pay_status = $result_bk[0]->pay_status;
1717 }
1718 // FixIn: 10.12.1.5.
1719 $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET pay_status= %s WHERE booking_id= %d ", $selected_payment_status, $selected_booking_id );
1720 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1721 if ( false === $wpdb->query( $update_sql ) ) {
1722 // Error
1723 $after_action_result = false;
1724 $after_action_message .= 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
1725 } else {
1726 // Success
1727 /* translators: 1: ... */
1728 $after_action_message .= sprintf( __( 'Payment status for Booking %1$s has been updated from %2$s to %3$s', 'booking' )
1729 , ' <span style="font-size:0.9em;">( ID = <strong>' . $selected_booking_id . '</strong> )</span>'
1730 , '<strong>"' . wpbc__format__get_payment_status_title( $old_pay_status ) . '"</strong>'
1731 , '<strong>"' . wpbc__format__get_payment_status_title( $selected_payment_status ) . '"</strong>'
1732 ) . '<br/>';
1733 }
1734
1735
1736 if ( $after_action_result ) {
1737 // LOG ---------------------------------------------------------------------------------------------------------
1738 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1739 wpbc_db__add_log_info( explode( ',', $selected_booking_id ),
1740 $after_action_message
1741 . '. ' . __( 'Changed by:', 'booking' )
1742 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1743 );
1744
1745 // Just action hook for some other addons
1746 do_action( 'wpbc_booking_action__set_payment_status', $selected_booking_id, $selected_payment_status , $old_pay_status );
1747
1748 // Emails ------------------------------------------------------------------------------------------------------
1749 if ( ! empty( $is_send_emeils ) ) {
1750 // We are sending emails about the new booking, if we have created it.
1751 // wpbc_send_email_modified( $selected_booking_id, $selected_resource_id, $formdata_new );
1752 }
1753 }
1754 }
1755 }
1756
1757 return array(
1758 'after_action_result' => $after_action_result,
1759 'after_action_message' => $after_action_message
1760 );
1761
1762 }
1763
1764 /**
1765 * Get title of the payment status
1766 *
1767 * @param $payment_status_key
1768 *
1769 * @return string
1770 */
1771 function wpbc__format__get_payment_status_title( $payment_status_key ){
1772
1773 $selected_payment_status_text = $payment_status_key;
1774
1775 $select_box_options = get_payment_status_titles();
1776 $select_box_options = array_flip( $select_box_options );
1777
1778 if ( ! empty( $select_box_options[ $payment_status_key ] ) ) {
1779 $selected_payment_status_text = $select_box_options[ $payment_status_key ];
1780 }
1781
1782 return $selected_payment_status_text;
1783 }
1784
1785
1786 /**
1787 * Action: Set Booking Cost
1788 *
1789 * @param $booking_id_arr array or int of booking ID
1790 * @param $booking_cost string booking cost
1791 * @param $params array array of parameters: array( 'user_id' => 1 )
1792 *
1793 * @return array
1794 *
1795 * Example:
1796 */
1797 function wpbc_booking_do_action__set_booking_cost( $booking_id_arr, $booking_cost, $params ) {
1798
1799 global $wpdb;
1800
1801 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
1802
1803 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
1804 if ( ! is_array( $booking_id_arr ) ) {
1805 $booking_id_arr = array( $booking_id_arr );
1806 }
1807 $booking_id_csd = join( ',', $booking_id_arr );
1808 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
1809
1810
1811 // Is send email for this action ----------------------------------------------------------------------------------
1812 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1813
1814 // -----------------------------------------------------------------------------------------------------------------
1815
1816 $booking_cost = str_replace(',', '.', $booking_cost);
1817 $booking_cost = floatval( $booking_cost );
1818
1819
1820 if ( empty( $booking_id_csd ) ) {
1821 $after_action_result = false;
1822 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
1823
1824 } else {
1825 $after_action_result = true;
1826 $after_action_message = '';
1827
1828 $work_booking_id_arr = explode( ',', $booking_id_csd );
1829
1830 foreach ( $work_booking_id_arr as $selected_booking_id ) {
1831
1832 // SQL ---------------------------------------------------------------------------------------------------
1833 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.booking_id= %d ", $selected_booking_id );
1834 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1835 $result_bk = $wpdb->get_results( $sql );
1836
1837 $old_booking_cost = '';
1838
1839 if ( ( 0 == count( $result_bk ) ) ) {
1840 // Error
1841 $after_action_result = false;
1842 /* translators: 1: ... */
1843 $after_action_message .= sprintf( __( 'There is no booking %s', 'booking' )
1844 , ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'
1845 );
1846 } else {
1847 $old_booking_cost = $result_bk[0]->cost;
1848 }
1849
1850 $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET cost = %f WHERE booking_id = %d ", $booking_cost, $selected_booking_id ); // FixIn: 10.12.1.5.
1851 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1852 if ( false === $wpdb->query( $update_sql ) ) {
1853 // Error
1854 $after_action_result = false;
1855 $after_action_message .= 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
1856 } else {
1857 // Success
1858 /* translators: 1: ... */
1859 $after_action_message .= sprintf( __( 'Cost for Booking %1$s has been updated from %2$s to %3$s', 'booking' )
1860 , ' <span style="font-size:0.9em;">( ID = <strong>' . $selected_booking_id . '</strong> )</span>'
1861 , '<strong>"' . wpbc__format__get_payment_status_title( $old_booking_cost ) . '"</strong>'
1862 , '<strong>"' . wpbc__format__get_payment_status_title( $booking_cost ) . '"</strong>'
1863 ) . '<br/>';
1864 }
1865
1866
1867 if ( $after_action_result ) {
1868 // LOG ---------------------------------------------------------------------------------------------------------
1869 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1870 wpbc_db__add_log_info( explode( ',', $selected_booking_id ),
1871 $after_action_message
1872 . '. ' . __( 'Changed by:', 'booking' )
1873 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1874 );
1875
1876 // Just action hook for some other addons
1877 do_action( 'wpbc_booking_action__set_booking_cost', $selected_booking_id, $booking_cost , $old_booking_cost );
1878
1879 // Emails ------------------------------------------------------------------------------------------------------
1880 if ( ! empty( $is_send_emeils ) ) {
1881
1882 if ( get_bk_option( 'booking_send_email_on_cost_change' ) == 'On' ) { // FixIn: 8.1.3.30.
1883 $booking_data = apply_bk_filter( 'wpbc_get_booking_data', $selected_booking_id );
1884 wpbc_send_email_modified( $selected_booking_id, $booking_data['type'], $booking_data['form'] );
1885 }
1886 }
1887
1888 }
1889 }
1890 }
1891
1892 return array(
1893 'after_action_result' => $after_action_result,
1894 'after_action_message' => $after_action_message
1895 );
1896 }
1897
1898
1899 /**
1900 * Action: Send Payment request
1901 *
1902 * @param $booking_id_arr array or int of booking ID
1903 * @param $booking_cost string booking cost
1904 * @param $params array array of parameters: array( 'user_id' => 1 )
1905 *
1906 * @return array
1907 */
1908 function wpbc_booking_do_action__send_payment_request($booking_id_arr, $reason_of_action, $params ) {
1909 global $wpdb;
1910
1911 make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
1912
1913 // Get ID list of bookings, like '1' or '3,7,9' ----------------------------------------------------------------
1914 if ( ! is_array( $booking_id_arr ) ) {
1915 $booking_id_arr = array( $booking_id_arr );
1916 }
1917 $booking_id_csd = join( ',', $booking_id_arr );
1918 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
1919
1920
1921 // Is send email for this action ----------------------------------------------------------------------------------
1922 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
1923
1924 // -----------------------------------------------------------------------------------------------------------------
1925
1926 if ( empty( $booking_id_csd ) ) {
1927 $after_action_result = false;
1928 $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' );
1929
1930 } else {
1931 $after_action_result = true;
1932 $after_action_message = '';
1933
1934 $work_booking_id_arr = explode( ',', $booking_id_csd );
1935
1936 foreach ( $work_booking_id_arr as $selected_booking_id ) {
1937
1938 // SQL ---------------------------------------------------------------------------------------------------
1939 $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.booking_id= %d ", $selected_booking_id );
1940 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1941 $result_bk = $wpdb->get_results( $sql );
1942
1943 $old_booking_cost = '';
1944
1945 if ( ( 0 == count( $result_bk ) ) ) {
1946 // Error
1947 $after_action_result = false;
1948 /* translators: 1: ... */
1949 $after_action_message .= sprintf( __( 'There is no booking %s', 'booking' )
1950 , ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'
1951 );
1952 } else {
1953 $old_booking_cost = $result_bk[0]->cost;
1954
1955 $is_email_payment_request_adress = get_bk_option( 'booking_is_email_payment_request_adress' );
1956 if ( 'Off' != $is_email_payment_request_adress ) {
1957
1958 $reason_of_action = htmlspecialchars( str_replace( '\"', '"', $reason_of_action ) );
1959 $reason_of_action = str_replace( "\'", "'", $reason_of_action );
1960
1961 foreach ( $result_bk as $res ) {
1962
1963 $is_send = wpbc_send_email_payment_request( $res->booking_id, $res->booking_type, $res->form, $reason_of_action );
1964
1965 if ( $is_send ) {
1966 // Update Payment request number
1967 $pay_request_numer = $res->pay_request + 1;
1968 // FixIn: 10.12.1.5.
1969 $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET pay_request= %d WHERE booking_id= %d ", $pay_request_numer, $res->booking_id );
1970 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1971 if ( false === $wpdb->query( $update_sql ) ) {
1972 // Error
1973 $after_action_result = false;
1974 $after_action_message .= 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__;
1975 } else {
1976 // Success
1977 /* translators: 1: ... */
1978 $after_action_message .= sprintf( __( 'Payment request for Booking %1$s has been sent. Cost for payment: %2$s', 'booking' )
1979 , ' <span style="font-size:0.9em;">( ID = <strong>' . $selected_booking_id . '</strong> )</span>'
1980 , '<strong>"' . wpbc__format__get_payment_status_title( $old_booking_cost ) . '"</strong>'
1981 ) . '<br/>';
1982 }
1983 }
1984 }
1985 }
1986 }
1987
1988 if ( $after_action_result ) {
1989 // LOG ---------------------------------------------------------------------------------------------------------
1990 $curr_user = get_user_by( 'id', (int) $params['user_id'] );
1991 wpbc_db__add_log_info( explode( ',', $selected_booking_id ),
1992 $after_action_message
1993 . '. ' . __( 'Send by:', 'booking' )
1994 . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')'
1995 );
1996
1997 // Just action hook for some other addons
1998 do_action( 'wpbc_booking_action__send_payment_request', $selected_booking_id, $reason_of_action , $old_booking_cost );
1999
2000 // Emails ------------------------------------------------------------------------------------------------------
2001 /*
2002 if ( ! empty( $is_send_emeils ) ) {
2003
2004 if ( get_bk_option( 'booking_send_email_on_cost_change' ) == 'On' ) {
2005 $booking_data = apply_bk_filter( 'wpbc_get_booking_data', $selected_booking_id );
2006 wpbc_send_email_modified( $selected_booking_id, $booking_data['type'], $booking_data['form'] );
2007 }
2008 }
2009 */
2010 }
2011 }
2012
2013 }
2014
2015 return array(
2016 'after_action_result' => $after_action_result,
2017 'after_action_message' => $after_action_message
2018 );
2019 }
2020
2021
2022 function wpbc_booking_do_action__import_google_calendar( $request_params, $params ) {
2023
2024 $return_array = array();
2025
2026 $user_bk_id = (int) $params['user_id'];
2027
2028 global $wpdb;
2029
2030 $wpbc_Google_Calendar = new WPBC_Google_Calendar();
2031
2032 $wpbc_Google_Calendar->setSilent();
2033
2034 $wpbc_Google_Calendar->set_timezone( get_bk_option('booking_gcal_timezone') );
2035
2036 $wpbc_Google_Calendar->set_events_from_with_array( array(
2037 $request_params['booking_gcal_events_from'],
2038 $request_params['booking_gcal_events_from_offset'],
2039 $request_params['booking_gcal_events_from_offset_type']
2040 ) );
2041
2042 $wpbc_Google_Calendar->set_events_until_with_array( array(
2043 $request_params['booking_gcal_events_until'],
2044 $request_params['booking_gcal_events_until_offset'],
2045 $request_params['booking_gcal_events_until_offset_type']
2046 ) );
2047
2048 $wpbc_Google_Calendar->set_events_max( $request_params['booking_gcal_events_max'] );
2049
2050 if ( ( isset( $request_params['booking_gcal_resource'] ) ) && ( empty( $request_params['booking_gcal_resource'] ) ) ) {
2051
2052 $wpbc_Google_Calendar->setUrl( get_bk_option( 'booking_gcal_feed') );
2053 $import_result = $wpbc_Google_Calendar->run();
2054
2055 } else {
2056
2057 if ( $request_params['booking_gcal_resource'] != 'all' ) { // One resource
2058
2059 $wpbc_booking_resource_id = intval( $request_params['booking_gcal_resource'] );
2060
2061 $wpbc_Google_Calendar->setResource( $wpbc_booking_resource_id );
2062
2063 $wpbc_booking_resource_feed = get_booking_resource_attr( $wpbc_booking_resource_id );
2064 $wpbc_booking_resource_feed = $wpbc_booking_resource_feed->import;
2065 $wpbc_Google_Calendar->setUrl( $wpbc_booking_resource_feed );
2066
2067 $import_result = $wpbc_Google_Calendar->run();
2068 } else { // All resources
2069
2070 $where = ''; // Where for the different situation: BL and MU
2071
2072 if ( class_exists( 'wpdev_bk_multiuser' ) ) { // MultiUser - only specific booking resources for specific Regular User in Admin panel.
2073
2074 $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_bk_id );
2075
2076 if ( ! $is_user_super_admin ) {
2077 $where .= ' WHERE users = ' . intval( $user_bk_id ) . ' ';
2078 }
2079 }
2080
2081 $my_sql = "SELECT booking_type_id, import FROM {$wpdb->prefix}bookingtypes {$where}";
2082 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
2083 $types_list = $wpdb->get_results( $my_sql );
2084
2085 foreach ($types_list as $wpbc_booking_resource) {
2086 $wpbc_booking_resource_id = $wpbc_booking_resource->booking_type_id;
2087 $wpbc_booking_resource_feed = $wpbc_booking_resource->import;
2088 if ( ( ! empty( $wpbc_booking_resource_feed ) ) && ( $wpbc_booking_resource_feed != null ) && ( $wpbc_booking_resource_feed != '/' ) ) {
2089
2090 $wpbc_Google_Calendar->setUrl( $wpbc_booking_resource_feed );
2091 $wpbc_Google_Calendar->setResource( $wpbc_booking_resource_id );
2092 $import_result = $wpbc_Google_Calendar->run();
2093 }
2094 }
2095 }
2096 }
2097
2098
2099 if ( ( isset( $import_result ) ) && ( false != $import_result ) ) {
2100 $after_action_result = true;
2101 /* translators: 1: ... */
2102 $after_action_message = sprintf( __( '%s new bookings have been imported', 'booking' )
2103 , ' <span style="font-size:1em;"> <strong>' . count( $wpbc_Google_Calendar->events ) . '</strong> </span>'
2104 ) ;
2105 if ( 0 != count( $wpbc_Google_Calendar->events ) ) {
2106 $after_action_message .= '<br/><br/>' . esc_html__( 'The filter settings have been updated to reflect these imported bookings. The page will be reloaded.', 'booking' );
2107 }
2108
2109 if ( ! empty( $wpbc_Google_Calendar->getErrorMessage() ) ) {
2110 $after_action_message .= '<div style="max-width:60rem;margin:2em 10px;">' . $wpbc_Google_Calendar->getErrorMessage() . '</div>';
2111 $return_array['after_action_result_delay'] = 100000000000000;
2112 }
2113
2114 } else {
2115 $after_action_result = false;
2116 $after_action_message = __( 'No bookings have been imported.', 'booking' )
2117 . '<br/><br/>'
2118 . sprintf( __( 'Please configure settings for import Google Calendar events', 'booking' ), '<b>', ',</b>' )
2119 . ' <a href="' . esc_url( wpbc_get_settings_url() . '&tab=sync&subtab=gcal' ). '">' . esc_html__('here' ,'booking') . '.</a>'
2120 . '<br/><br/>'
2121 . $wpbc_Google_Calendar->getErrorMessage();
2122 $return_array['after_action_result_delay'] = 100000000000000;
2123 }
2124
2125
2126 if ( 0 == count( $wpbc_Google_Calendar->events ) ) {
2127 $new_listing_params = false;
2128 } else {
2129 $new_listing_params = array(
2130 "sort" => "booking_id",
2131 "sort_type" => "DESC",
2132 "page_num" => 1,
2133 "page_items_count" => "50",
2134 "create_date" => "",
2135 "keyword" => "",
2136 "source" => "",
2137 "wh_booking_type" => array( "0" ),
2138 "wh_approved" => "",
2139 "wh_booking_date" => array( "3" ),
2140 "ui_wh_booking_date_radio" => 0,
2141 "ui_wh_booking_date_next" => 1,
2142 "ui_wh_booking_date_prior" => 1,
2143 "ui_wh_booking_date_checkin" => "",
2144 "ui_wh_booking_date_checkout" => "",
2145 "wh_what_bookings" => "imported",
2146 "wh_modification_date" => array( "1" ),
2147 "ui_wh_modification_date_prior" => "1",
2148 "ui_wh_modification_date_checkin" => "",
2149 "ui_wh_modification_date_checkout" => "",
2150 "wh_pay_status" => array( "all" ),
2151 "ui_wh_pay_status_radio" => "",
2152 "ui_wh_pay_status_custom" => "",
2153 "wh_cost" => "",
2154 "wh_cost2" => "",
2155 "wh_sort" => "booking_id__desc",
2156 "wh_trash" => "any",
2157 'reload_url_params' => htmlspecialchars_decode( esc_url( wpbc_get_bookings_url() . '&tab=vm_booking_listing' ) )
2158 );
2159 }
2160
2161
2162 $return_array['after_action_result'] = $after_action_result;
2163 $return_array['after_action_message'] = $after_action_message;
2164 $return_array['new_listing_params'] = $new_listing_params;
2165
2166 return $return_array;
2167 }
2168
2169
2170 function wpbc_booking_do_action__export_csv( $request_params, $params ){
2171
2172 global $wpdb;
2173
2174 make_bk_action( 'check_multiuser_params_for_client_side_by_user_id', $params['user_id'] );
2175
2176 $booking_id_csd = $request_params['booking_id'];
2177 $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd );
2178 if ( empty( $booking_id_csd ) ) {
2179 // Export all bookings (no selected bookings was in the listing
2180 }
2181
2182 $export_type = $request_params['export_type']; // csv_page | csv_all
2183
2184 // Is send email for this action ----------------------------------------------------------------------------------
2185 $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] );
2186
2187 // -----------------------------------------------------------------------------------------------------------------
2188
2189 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
2190 if ( ! isset( $_POST['search_params'] ) || empty( $_POST['search_params'] ) ) {
2191
2192 $after_action_result = false;
2193 $after_action_message = __('Error', 'booking') . '! ' . 'Search parameters for CSV generating are empty.';
2194
2195 } else {
2196
2197
2198 $user_request = new WPBC_AJX__REQUEST( array(
2199 'db_option_name' => 'booking_listing_request_params',
2200 'user_id' => wpbc_get_current_user_id(),
2201 'request_rules_structure' => wpbc_ajx_get__request_params__names_default()
2202 )
2203 );
2204 $request_prefix = 'search_params';
2205 $request_params_for_listing = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['search_params']['resource_id']
2206
2207
2208
2209 // $data_arr = wpbc_ajx_get_booking_data_arr( $request_params_for_listing );
2210
2211 $export_csv_url = wpbc_csv_get_url_export( $request_params_for_listing );
2212
2213 $after_action_result = true;
2214 $after_action_message = __('Processing' ,'booking') . '... ';
2215 }
2216
2217 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Recommended
2218 $wpbc_ajx_locale = ( isset( $_REQUEST['wpbc_ajx_locale'] ) ) ? sanitize_text_field( $_REQUEST['wpbc_ajx_locale'] ) : 'en_US';
2219
2220 return array(
2221
2222 'export_csv_url' => $export_csv_url
2223 . '&export_type=' . $export_type
2224 . '&selected_id=' . $booking_id_csd
2225 . '&csv_export_separator=' . $request_params['csv_export_separator']
2226 . '&csv_export_skip_fields=' . $request_params['csv_export_skip_fields']
2227 . '&wpbc_ajx_locale=' . $wpbc_ajx_locale
2228 . '&wpbc_ajx_locale_reload=force' ,
2229 'after_action_result' => $after_action_result,
2230 'after_action_message' => $after_action_message
2231 );
2232 }
2233 // </editor-fold>
2234
2235
2236 // <editor-fold defaultstate="collapsed" desc=" == Button Actions Templates for UI == " >
2237
2238 /**
2239 * Show Read booking Button
2240 */
2241 function wpbc_for_booking_template__action_read(){
2242
2243 $booking_action = 'set_booking_as_read';
2244
2245 if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) {
2246 return false;
2247 }
2248
2249 $params = array(
2250 'type' => 'button',
2251 'title' => '',
2252 'hint' => array(
2253 'title' => __( 'New booking', 'booking' ),
2254 'position' => 'top'
2255 ),
2256 'link' => 'javascript:void(0)',
2257 'action' => " wpbc_ajx_booking_ajax_action_request( {
2258 'booking_action' : '{$booking_action}',
2259 'booking_id' : {{data['parsed_fields']['booking_id']}}
2260 } );
2261 wpbc_button_enable_loading_icon( this ); ",
2262 'icon' => array(
2263 'icon_font' => 'wpbc_icn_fiber_manual_record',// 'wpbc_icn_visibility',
2264 'position' => 'left',
2265 'icon_img' => ''
2266 ),
2267 'class' => 'wpbc_is_new_button',
2268 'style' => '',
2269 'mobile_show_text' => true,
2270 'attr' => array()
2271 );
2272
2273 ?><# if ( '1' == data.parsed_fields.is_new ) { #><?php
2274 wpbc_flex_button( $params );
2275 ?><# } #><?php
2276 }
2277
2278 // </editor-fold>
2279
2280
2281
2282 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2283 // Support functions
2284 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2285
2286 /**
2287 * Catch some errors, if such errors exist during our Ajx request
2288 */
2289 class WPBC_AJAX_ERROR_CATCHING{
2290
2291 public $errors_arr;
2292
2293 function __construct() {
2294
2295 $this->errors_arr = array();
2296
2297 // Catch Error messages
2298 add_action( 'wp_error_added', array( $this, 'wpbc_wp_error_added' ), 10, 4 );
2299
2300 if ( ! defined( 'WPBC_AJAX_ERROR_CATCH' ) ) { define( 'WPBC_AJAX_ERROR_CATCH', true ); } // Check somewhere to not show error messages: if ( ( defined( 'WPBC_AJAX_ERROR_CATCH' ) ) && ( WPBC_AJAX_ERROR_CATCH ) ) { return false; }
2301 }
2302
2303 /**
2304 * Catch Error messages
2305 *
2306 * @param $code
2307 * @param $message
2308 * @param $data
2309 * @param $this_link
2310 *
2311 * @return void
2312 */
2313 function wpbc_wp_error_added( $code, $message, $data, $this_link ){
2314
2315 $this->errors_arr[] = array(
2316 'code' => $code,
2317 'message' => $message,
2318 'data' => $data,
2319 'this_link' => $this_link
2320 ) ;
2321 }
2322
2323 /**
2324 * Get summary of all errors
2325 * @return string
2326 */
2327 function get_error_messages(){
2328
2329 $error_message = array();
2330
2331 foreach ( $this->errors_arr as $error ) {
2332 $error_message[] = 'Error: ' . $error['code'] . '. ' . $error['message'];
2333 }
2334 $error_message = implode( '<br/>', $error_message );
2335
2336 if ( ! empty( $error_message ) ) {
2337 $error_message = '<div class="wpbc_ajx_errors">'
2338 .'<br/><strong>' . esc_html__( 'Some errors were encountered.', 'booking' ) . '</strong><br/>'
2339 . $error_message
2340 . '</div>';
2341 }
2342 return $error_message;
2343 }
2344 }
2345
2346
2347 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2348 // Check what user can do
2349 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2350
2351 /**
2352 * Check permission of this user on specific actions, like approving or deleting of bookings
2353 *
2354 * @param string $action like 'set_pnding'
2355 * @param int $user_id like 1
2356 *
2357 * @return bool
2358 */
2359 function wpbc_is_user_can( $action, $user_id = 0 ){
2360
2361 if ( 0 == $user_id ) {
2362 $user_id = wpbc_get_current_user_id();
2363 }
2364 $user = get_userdata( $user_id );
2365 $user_roles = (array) ( empty( $user ) ? array() : $user->roles ); // Standard WordPress Roles: 'administrator' | 'editor' | 'author' | 'contributor' | 'subscriber'
2366
2367
2368 // Get here list of actions that user can do
2369 switch ( $action ) {
2370 case 'set_booking_pending':
2371 break;
2372 case 'set_booking_approved':
2373 break;
2374 case 'move_booking_to_trash':
2375 break;
2376 case 'restore_booking_from_trash':
2377 break;
2378 case 'delete_booking_completely':
2379 // if ( ! in_array( 'administrator', $user_roles ) ) { return false; }
2380 break;
2381 case 'booking_add_google_calendar':
2382 break;
2383 case 'set_booking_locale':
2384 break;
2385 case 'set_booking_as_read':
2386 break;
2387 case 'set_booking_as_unread':
2388 break;
2389 case 'empty_trash':
2390 break;
2391 case 'set_booking_note':
2392 break;
2393 case 'edit_booking':
2394 break;
2395 case 'change_booking_resource':
2396 break;
2397 case 'duplicate_booking_to_other_resource':
2398 break;
2399 case 'set_payment_status':
2400 break;
2401 case 'set_booking_cost':
2402 break;
2403 case 'send_payment_request':
2404 break;
2405 case 'import_google_calendar':
2406 break;
2407 case 'export_csv':
2408 break;
2409 default:
2410 // Default
2411 }
2412
2413 return true;
2414 }
2415