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

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

1,415 lines 79.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly //FixIn: 9.8.0.4
4
5 // ---------------------------------------------------------------------------------------------------------------------
6 // == Ajax Response on creation of new booking
7 // ---------------------------------------------------------------------------------------------------------------------
8
9 /**
10 * Response to Ajax request, about loading calendar data
11 *
12 * @return void
13 */
14 function ajax_WPBC_AJX_BOOKING__CREATE() {
15
16 /**
17 * Tip / translation /
18 * Please note, translation was loaded on hook add_action( 'plugins_loaded', 'wpbc_load_translation', 1000 ); and use $_REQUEST['wpbc_ajx_locale'], so do not worry about it.
19 */
20
21 // Security ------------------------------------------------------------------------------------------------------ // in Ajax Post: 'nonce': _wpbc.get_secure_param( 'nonce' ),
22 $action_name = 'wpbc_calendar_load_ajx' . '_wpbcnonce';
23 $nonce_post_key = 'nonce';
24 if ( wpbc_is_use_nonce_at_front_end() ) { //FixIn: 10.1.1.2
25 $result_check = check_ajax_referer( $action_name, $nonce_post_key );
26 }
27
28 // Response AJAX parameters
29 $ajx_data_arr = array();
30 $ajx_data_arr['status'] = 'ok';
31
32 $admin_uri = ltrim( str_replace( get_site_url( null, '', 'admin' ), '', admin_url( 'admin.php?' ) ), '/' ); // 'wp-admin/admin.php?'
33
34 // Local parameters
35 $local_params = array();
36 $local_params['is_from_admin_panel'] = ( false !== strpos( $_SERVER['HTTP_REFERER'], $admin_uri ) ); // true | false
37 $local_params['user_id'] = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); // 1
38
39 // Request parameters
40 $user_request = new WPBC_AJX__REQUEST( array( // Using this class here only for escaping variables
41 'db_option_name' => 'booking__wpbc_booking_create__request_params', // Not necessary, because we not save request, only sanitize it
42 'user_id' => $local_params['user_id'], // Not necessary, because we not save request, only sanitize it
43 'request_rules_structure' => array(
44 'resource_id' => array( 'validate' => 'd', 'default' => 1 ), // 'digit_or_csd'
45
46 'aggregate_resource_id_arr' => array( 'validate' => 'digit_or_csd', 'default' => '' ),
47
48 'dates_ddmmyy_csv' => array( 'validate' => 'csv_dates', 'default' => '' ), //FixIn: 9.9.1.1
49 'formdata' => array( 'validate' => 'strong', 'default' => '' ),
50 'booking_hash' => array( 'validate' => 'strong', 'default' => '' ),
51 'custom_form' => array( 'validate' => 'strong', 'default' => '' ),
52
53 'captcha_chalange' => array( 'validate' => 'strong', 'default' => '' ),
54 'captcha_user_input' => array( 'validate' => 'strong', 'default' => '' ),
55
56 'is_emails_send' => array( 'validate' => 'd', 'default' => 1 ),
57 'active_locale' => array( 'validate' => 'strong', 'default' => '' )
58 )
59 ));
60
61 // Escape of request params in Ajax Post. We use prefix 'calendar_request_params', if Ajax sent - $_REQUEST['calendar_request_params']['resource_id'], ...
62 $request_prefix = 'calendar_request_params';
63
64 //$_REQUEST['calendar_request_params']['dates_ddmmyy_csv'] .= "'%2b(select+'box'+from(select+sleep(2)+from+dual+where+1=1*)a)%2b'-02-21+00:00:00";
65
66 $request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['calendar_request_params']['resource_id']
67
68 $request_params['request_uri'] = $_SERVER['HTTP_REFERER']; // Parameter needed for Error in booking saving and reloading calendar again with these actual parameters.
69
70 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- CAPTCHA " >
71 wpbc_captcha__in_ajx__check( $request_params, $local_params['is_from_admin_panel'], $_REQUEST[ $request_prefix ] );
72 // </editor-fold>
73
74 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- BOOKING_RESOURCE ID " >
75 if ( $request_params['resource_id'] <= 0 ) {
76 $ajx_data_arr['status'] = 'error';
77 $ajx_data_arr['status_error'] = 'resource_id_incorrect';
78 $ajx_data_arr['ajx_after_action_message'] = 'Wrong ID of booking resource: ' . ' [ request ID: ' . $_REQUEST['calendar_request_params']['resource_id'] . ' | parsed ID: ' . $request_params['resource_id'] . ' ]';
79 $ajx_data_arr['ajx_after_action_message_status'] = 'error';
80 wp_send_json( array( 'ajx_data' => $ajx_data_arr,
81 'ajx_search_params' => $_REQUEST[ $request_prefix ],
82 'ajx_cleaned_params' => $request_params,
83 'resource_id' => $request_params['resource_id']
84 ) );
85 }
86 // </editor-fold>
87
88
89 $request_save_params = array(
90 'resource_id' => $request_params['resource_id'],
91 'dates_ddmmyy_csv' => $request_params['dates_ddmmyy_csv'],
92 'form_data' => $request_params['formdata'],
93 'aggregate_resource_id_arr' => $request_params['aggregate_resource_id_arr'], // Optional can be ''
94
95 'booking_hash' => $request_params['booking_hash'],
96 'custom_form' => $request_params['custom_form'],
97
98 'is_emails_send' => $request_params['is_emails_send'],
99 'is_show_payment_form' => 1,
100 'user_id' => $local_params['user_id'],
101 'request_uri' => $_SERVER['HTTP_REFERER']
102 );
103 $booking_save_arr = wpbc_booking_save( $request_save_params );
104
105 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- BOOKING " >
106 if ( 'ok' !== $booking_save_arr['ajx_data']['status'] ) {
107
108 wp_send_json( array( 'ajx_data' => $booking_save_arr['ajx_data'],
109 'ajx_search_params' => $_REQUEST[ $request_prefix ],
110 'ajx_cleaned_params' => $request_params,
111 'resource_id' => $request_params['resource_id']
112 ));
113 }
114 // </editor-fold>
115
116 $ajx_data_arr = $booking_save_arr['ajx_data'];
117
118
119
120 // TODO: If we have the calendar with specific capacity, then maybe showing by dots (the booked child booking resources) the slots and not the time slot !
121
122 if ( empty( $ajx_data_arr['ajx_after_action_message_status'] ) ) {
123 $ajx_data_arr['ajx_after_action_message_status'] = 'success';
124 }
125 if ( empty( $ajx_data_arr['ajx_after_action_message'] ) ) {
126 $ajx_data_arr['ajx_after_action_message'] = '';
127 }
128
129 // $ajx_data_arr['ajx_after_action_message'] .= __( 'Booking was created with ID: ' . $booking_save_arr[ 'booking_id' ] , 'booking' );
130 // $ajx_data_arr['ajx_after_action_message'] .= '<hr>Total time: <strong>' . $booking_save_arr['php_performance']['total'] . ' s. </strong>';
131 // $ajx_data_arr['ajx_after_action_message'] .= str_replace( array( ',', '{', '}' ), '<br>', json_encode( $booking_save_arr['php_performance'] ) );
132 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133
134
135
136 /* if admin edit ?
137 var my_message = '<?php echo html_entity_decode( esc_js( __('Updated successfully' ,'booking') ),ENT_QUOTES) ; ?>';
138 wpbc_admin_show_message( my_message, 'success', 3000 );
139 location.href='<?php echo wpbc_get_bookings_url() ;?>&view_mode=vm_listing&tab=actions&wh_booking_id=<?php echo $is_edit_booking['booking_id'] ; ?>';
140 */
141
142
143 // -----------------------------------------------------------------------------------------------------------------
144 // == Ajax ===
145 // -----------------------------------------------------------------------------------------------------------------
146 /**
147 * Send JSON. It will make "wp_json_encode" - so pass only array, and This function call wp_die( '', '', array( 'response' => null, ) ) .
148 * Pass JS OBJ: response_data in "jQuery.post " function on success.
149 *
150 * Other End Ajax actions:
151 * $error_obj = new WP_Error( 'WPBC_CREATE', __( 'test error.' ), 'some/data' ); wp_send_json_error( $error_obj );
152 * wp_send_json_error( array( 'message' => 'invalid-api-key' ) );
153 * wp_send_json_success( array( 'message' =>'Ok:)' ) );
154 */
155 wp_send_json( array(
156 'booking_id' => $booking_save_arr['booking_id'],
157 'resource_id' => $request_params['resource_id'],
158 'ajx_data' => $ajx_data_arr,
159 'ajx_confirmation' => $booking_save_arr['confirmation'],
160
161 // For debug purpose <- comment in live serv
162 'php_process_times' => $booking_save_arr['php_performance'],
163 'booking_arr' => $booking_save_arr ['booking_arr'],
164
165 // Not needed ?
166 // 'ajx_search_params' => $_REQUEST[ $request_prefix ],
167 // 'ajx_cleaned_params' => $request_params,
168
169 ) );
170 }
171
172 // Ajax Hooks
173 if ( is_admin() && ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) {
174 add_action( 'wp_ajax_nopriv_' . 'WPBC_AJX_BOOKING__CREATE', 'ajax_' . 'WPBC_AJX_BOOKING__CREATE' ); // Client (not logged in)
175 add_action( 'wp_ajax_' . 'WPBC_AJX_BOOKING__CREATE', 'ajax_' . 'WPBC_AJX_BOOKING__CREATE' ); // Logged In users (or admin panel)
176 }
177
178
179 // ---------------------------------------------------------------------------------------------------------------------
180 // == Save Booking
181 // ---------------------------------------------------------------------------------------------------------------------
182
183 /**
184 * Save Booking - ADD NEW or UPDATE exist booking
185 *
186 * @param $request_params = [
187 * resource_id = 2 REQUIRED Default: 1
188 * dates_ddmmyy_csv = '27.10.2023, 28.10.2023, 29.10.2023' REQUIRED
189 * form_data = 'text^selected_short_dates_hint2^Fri, ...9, 2023~text^...' REQUIRED
190 * booking_hash = '' Optional Default: ''
191 * custom_form = '' Optional Default: ''
192 * is_emails_send = 1 Optional Default: 1
193 * is_show_payment_form => 1 Optional Default: 1
194 * user_id = 1 Optional Default: 0 or ID of logged-in user
195 * request_uri = 'http://beta/resource-id2/', // Optional Default: for front-end: $_SERVER['REQUEST_URI'] | ajax: $_SERVER['HTTP_REFERER']
196 *
197 * 'sync_gid' => 'ghjgjgjgh5f5f45f' // Really Optional: can be passed only during import .ics
198 * 'is_approve_booking' => 0 // Really Optional: 0 | 1
199 * 'save_booking_even_if_unavailable' => 0 // Really Optional: 0 | 1, if 1 then force save booking even if dates unavailable.
200 * ]
201 *
202 * @return [] ok: [
203 *
204 * ]
205 * error: [
206 * 'ajx_data': [ 'status':'error', 'status_error':'booking_can_not_save', 'ajx_after_action_message': 'Can not save booking', 'ajx_after_action_message_status': 'warning' ]
207 * ]
208 *
209 * Example:
210 *
211 * wpbc_booking_save( array(
212 * 'resource_id' => 2,
213 * 'dates_ddmmyy_csv' => '04.10.2023, 05.10.2023, 06.10.2023',
214 * 'form_data' => 'text^cost_hint2^150.00฿~selectbox-multiple^rangetime2[]^14:00 - 16:00~text^name2^John~text^secondname2^Smith~email^email2^john.smith@server.com~selectbox-one^visitors2^2~selectbox-one^children2^0~textarea^details2^test',
215 * 'booking_hash' => '',
216 * 'custom_form' => '',
217 * 'is_emails_send' => 1,
218 * 'is_show_payment_form' => 1,
219 * 'user_id' => 1,
220 * 'request_uri' => 'http://beta/resource-id2/'
221 * ) );
222 *
223 */
224 function wpbc_booking_save( $request_params ){
225 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
226 $php_performance = php_performance_START( 'total', array() );
227 // </editor-fold>
228 $ajx_data_arr = array();
229 $ajx_data_arr['status'] = 'ok';
230
231 // -----------------------------------------------------------------------------------------------------------------
232 // 1. Direct Clean Params
233 // -----------------------------------------------------------------------------------------------------------------
234 $validate_arr_rules = array(
235 'resource_id' => array( 'validate' => 'd', 'default' => 1 ), // INT
236 'dates_ddmmyy_csv' => array( 'validate' => 'csv_dates', 'default' => '' ), //FixIn: 9.9.1.1
237 'form_data' => array( 'validate' => 'strong', 'default' => '' ),
238 'booking_hash' => array( 'validate' => 'strong', 'default' => '' ),
239 'custom_form' => array( 'validate' => 'strong', 'default' => '' ),
240 'is_emails_send' => array( 'validate' => 'd', 'default' => 1 ), // 0 | 1
241 'is_show_payment_form' => array( 'validate' => 'd', 'default' => 1 ), // 0 | 1
242 'user_id' => array( 'validate' => 'd', 'default' => wpbc_get_current_user_id() ), // INT
243 'request_uri' => array( 'validate' => 'strong', 'default' => ( ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) ? $_SERVER['HTTP_REFERER'] : $_SERVER['REQUEST_URI'] ), // front-end: $_SERVER['REQUEST_URI'] | ajax: $_SERVER['HTTP_REFERER']
244 // Really Optional:
245 'aggregate_resource_id_arr' => array( 'validate' => 'digit_or_csd', 'default' => '' ),
246 //TODO: this parameter does not transfer during saving, so here will be always default value 'bookings_only' //FixIn: 10.0.0.7
247 'aggregate_type' => array( 'validate' => 'strong', 'default' => 'bookings_only' ), // Optional. 'all' | 'bookings_only' <- it is depends on shortcode parameter: options="{aggregate type=bookings_only}"
248 'is_approve_booking' => array( 'validate' => 'd', 'default' => 0 ), // 0 | 1
249 'save_booking_even_if_unavailable' => array( 'validate' => 'd', 'default' => 0 ), // 0 | 1
250 'sync_gid' => array( 'validate' => 'strong', 'default' => '' ),
251 'is_use_booking_recurrent_time' => array( 'validate' => 'd', 'default' => intval( ( 'On' === get_bk_option( 'booking_recurrent_time' ) ) ) )
252 );
253 $re_cleaned_params = wpbc_sanitize_params_in_arr( $request_params, $validate_arr_rules );
254
255 $admin_uri = ltrim( str_replace( get_site_url( null, '', 'admin' ), '', admin_url( 'admin.php?' ) ), '/' ); // wp-admin/admin.php?
256
257
258 // -----------------------------------------------------------------------------------------------------------------
259 // Local parameters
260 // -----------------------------------------------------------------------------------------------------------------
261 $local_params = array();
262 $local_params['is_from_admin_panel'] = ( false !== strpos( $re_cleaned_params['request_uri'], $admin_uri ) ); // true | false
263 $local_params['user_id'] = $re_cleaned_params['user_id']; // 1
264 $local_params['sync_gid'] = $re_cleaned_params['sync_gid']; // ''
265 $local_params['is_approve_booking'] = $re_cleaned_params['is_approve_booking']; // 0 | 1
266 $local_params['is_use_booking_recurrent_time'] = ( 1 === $re_cleaned_params['is_use_booking_recurrent_time'] ); // false | true
267
268 // -----------------------------------------------------------------------------------------------------------------
269 // Parse Local parameters for later use
270 // -----------------------------------------------------------------------------------------------------------------
271 /**
272 * Get parsed booking form: = [ name = "John", secondname = "Smith", email = "john.smith@server.com", visitors = "2",... ]
273 */
274 $local_params['structured_booking_data_arr'] = wpbc_get_parsed_booking_data_arr( $re_cleaned_params["form_data"], $re_cleaned_params["resource_id"], array( 'get' => 'value' ) );
275 $local_params['all_booking_data_arr'] = wpbc_get_parsed_booking_data_arr( $re_cleaned_params["form_data"], $re_cleaned_params["resource_id"] );
276 // Important! : [ 64800, 72000 ]
277 $local_params['time_as_seconds_arr'] = wpbc_get_in_booking_form__time_to_book_as_seconds_arr( $local_params['structured_booking_data_arr'] );
278 // [ "18:00:00", "20:00:00" ]
279 $time_as_seconds_arr = $local_params['time_as_seconds_arr'];
280 $time_as_seconds_arr[0] = ( 0 != $time_as_seconds_arr[0] ) ? $time_as_seconds_arr[0] + 1 : $time_as_seconds_arr[0]; // set check in time with ended 1 second
281 $time_as_seconds_arr[1] = ( ( 24 * 60 * 60 ) != $time_as_seconds_arr[1] ) ? $time_as_seconds_arr[1] + 2 : $time_as_seconds_arr[1]; // set check out time with ended 2 seconds
282 if ( ( 0 != $time_as_seconds_arr[0] ) && ( ( 24 * 60 * 60 ) == $time_as_seconds_arr[1] ) ) {
283 //FixIn: 10.0.0.49 - in case if we have start time != 00:00 and end time as 24:00 then set end time as 23:59:52
284 $time_as_seconds_arr[1] += - 8;
285 }
286 $local_params['time_as_his_arr'] = array(
287 wpbc_transform__seconds__in__24_hours_his( $time_as_seconds_arr[0] ),
288 wpbc_transform__seconds__in__24_hours_his( $time_as_seconds_arr[1] )
289 );
290 // [ '2023-09-10', '2023-09-11' ]
291 $local_params['dates_only_sql_arr'] = wpbc_convert_dates_str__dd_mm_yyyy__to__yyyy_mm_dd( $re_cleaned_params["dates_ddmmyy_csv"] );
292 $local_params['dates_only_sql_arr'] = explode( ',', $local_params['dates_only_sql_arr'] );
293
294 $local_params['is_show_payment_form'] = $re_cleaned_params["is_show_payment_form"];
295
296 //FixIn: 9.9.0.35
297 if ( $local_params['is_show_payment_form'] ) {
298 $local_params['is_show_payment_form'] = ( false !== strpos( $re_cleaned_params['request_uri'], 'is_show_payment_form=Off' ) )
299 ? 0
300 : $local_params['is_show_payment_form']; // 1|0
301 }
302
303 // Get EDIT booking data
304 $local_params['edit_resource_id'] = '';
305 $local_params['skip_booking_id'] = '';
306 $local_params['is_edit_booking'] = 0;
307 $local_params['is_duplicate_booking'] = 0;
308 $is_edit_booking = wpbc_get_data__if_edit_booking( $re_cleaned_params['booking_hash'], $re_cleaned_params['request_uri'] );
309 if ( false !== $is_edit_booking ) {
310 $local_params['edit_resource_id'] = $is_edit_booking['resource_id']; // can be parent booking resource, where we edit the booking
311 $local_params['skip_booking_id'] = $is_edit_booking['booking_id']; // booking ID
312 $local_params['is_edit_booking'] = $is_edit_booking['booking_id']; // booking ID
313 if (
314 ( ! empty( $local_params['structured_booking_data_arr']['wpbc_other_action'] ) )
315 && ( 'duplicate_booking' === $local_params['structured_booking_data_arr']['wpbc_other_action'] )
316 ){
317 $local_params['is_duplicate_booking'] = 1;
318 }
319 }
320 // It can be request resource ID or if we edit booking, it can be 'edit resource' - (e.g. child resource)
321 $local_params['initial_resource_id'] = ( ! empty( $local_params['edit_resource_id'] ) ) ? $local_params['edit_resource_id'] : $re_cleaned_params['resource_id'];
322
323 // 2
324 $local_params['how_many_items_to_book'] = wpbc_get__how_many_items_to_book__in_booking_form( $local_params['structured_booking_data_arr'], $local_params['initial_resource_id'] );
325
326
327 $local_params['aggregate_resource_id_arr'] = explode( ',', $re_cleaned_params['aggregate_resource_id_arr'] );
328 $local_params['aggregate_resource_id_arr'] = array_filter( $local_params['aggregate_resource_id_arr'] ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
329 $local_params['aggregate_resource_id_arr'] = array_unique( $local_params['aggregate_resource_id_arr'] ); // Erase duplicates
330
331 // -----------------------------------------------------------------------------------------------------------------
332 // Here GO
333 // -----------------------------------------------------------------------------------------------------------------
334
335 // Force - resource saving parameters, instead of wpbc__where_to_save_booking()
336 if ( ! empty( $re_cleaned_params["save_booking_even_if_unavailable"] ) ) {
337
338 $local_params['how_many_items_to_book'] = 1;
339
340 $dates_keys_arr = array_values( $local_params['dates_only_sql_arr'] ); // [ '2023-09-23', '2023-09-24' ]
341
342 $resources_in_dates = array_fill_keys( $dates_keys_arr , array( $local_params['initial_resource_id'] ) ); // [ 2023-09-23 = [ 2 ], 2023-09-24 = [ 2 ] ]
343
344 $where_to_save_booking = array();
345 $where_to_save_booking['result'] = 'ok';
346 $where_to_save_booking['resources_in_dates'] = $resources_in_dates; // [ 2023-09-23 = [ 2, 10, 11 ], 2023-09-24 = [ 2, 10, 11 ]
347 $where_to_save_booking['time_to_book'] = $local_params['time_as_his_arr']; // [ "00:00:00", "24:00:00" ]
348 $where_to_save_booking['main__resource_id'] = $local_params['initial_resource_id']; // here edit or request (parent/single) resource
349
350 } else {
351 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
352 $php_performance = php_performance_START( 'wpbc__where_to_save_booking' , $php_performance );
353 // </editor-fold>
354
355 /**
356 * Get slots [] where we can save booking = [ 'resources_in_dates' => [ 2023-10-18 = [ 2, 12, 10, 11 ]
357 * 2023-10-19 = [ 2, 12, 10, 11 ]
358 * 2023-10-20 = [ 2, 12, 10, 11 ]
359 * ],
360 * 'time_to_book' => [ "14:00:01" , "12:00:01" ],
361 * 'result' => 'ok'
362 * 'main__resource_id' => 2
363 * ]
364 * OR
365 * [ 'result' => 'error', 'message' => 'Booking can not be saved ...' ]
366 */
367 $where_to_save_booking = wpbc__where_to_save_booking( array(
368 'resource_id' => $local_params['initial_resource_id'], // 2 //TODO: If edit booking. What to pass 'edit' or 'parent' resource ID?
369 'skip_booking_id' => $local_params['skip_booking_id'], // '', | 125 if edit booking
370 'dates_only_sql_arr' => $local_params['dates_only_sql_arr'], // [ "2023-10-18", "2023-10-25", "2023-11-25" ]
371 'time_as_seconds_arr' => $local_params['time_as_seconds_arr'], // [ 36000, 39600 ]
372 'how_many_items_to_book' => $local_params['how_many_items_to_book'], // 1
373 'request_uri' => $re_cleaned_params['request_uri'], // 'http://beta/resource-id2/'
374 'is_use_booking_recurrent_time' => $local_params['is_use_booking_recurrent_time'], // true | false
375 'as_single_resource' => false, // false
376 'aggregate_resource_id_arr' => $local_params['aggregate_resource_id_arr'], // Optional can be ''
377 'aggregate_type' => $re_cleaned_params['aggregate_type'], //TODO: this parameter does not transfer during saving, so here will be always default value 'bookings_only' //FixIn: 10.0.0.7
378 'custom_form' => $re_cleaned_params['custom_form'] //FixIn: 10.0.0.10
379 ));
380 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- NO SLOTS TO SAVE " >
381 if ( 'error' == $where_to_save_booking['result'] ) {
382 $ajx_data_arr['status'] = 'error';
383 $ajx_data_arr['status_error'] = 'booking_can_not_save';
384 $ajx_data_arr['ajx_after_action_message'] = $where_to_save_booking['message'];
385 $ajx_data_arr['ajx_after_action_message_status'] = 'warning';
386 return array( 'ajx_data' => $ajx_data_arr );
387 }
388 // </editor-fold>
389
390 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
391 $php_performance = php_performance_END( 'wpbc__where_to_save_booking' , $php_performance );
392 // </editor-fold>
393 }
394
395
396 // Get parameters, from REQUEST
397 $create_params = $local_params;
398 $create_params['resource_id'] = ( ! empty( $local_params['edit_resource_id'] ) )
399 ? $local_params['edit_resource_id'] // If we edit, then use original resource ???
400 : $where_to_save_booking['main__resource_id']; // Here is important TIP, resource can be where is free, and not where we submit
401 /**
402 * TODO: I think it's resolved! Just test about this situation, when we edit the booking - and it's means that we have $local_params['edit_resource_id']
403 * but what, if $where_to_save_booking do not contain this $local_params['edit_resource_id'] as available resource.
404 * or even we have $local_params['edit_resource_id'] = 2 and $where_to_save_booking contain resources like [ 1, 2, 3, 4 ]
405 * we make booking for 3 slots
406 * in this case, main resource will be 2
407 * but then when we loop resources in wpbc_db__booking_save() we will save child booking resources for dates like: 2, 3, 4 ( and it's wrong )
408 * "(205, '2023-10-04 00:00:00', 0, NULL)" <- main resource '2' e.g. $local_params['edit_resource_id'] = 2
409 * "(205, '2023-10-04 00:00:00', 0, 2)" ? <- child resource '2' e.g. [ .., 2, .. ] in $where_to_save_booking WHICH IS WRONG
410 */
411 $create_params['is_emails_send'] = $re_cleaned_params['is_emails_send'];
412 $create_params['custom_form'] = $re_cleaned_params['custom_form'];
413
414 make_bk_action( 'check_multiuser_params_for_client_side', $create_params['resource_id'] ); // Activate working with specific user in WP MU
415
416 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
417 $php_performance = php_performance_START( 'wpbc_db__booking_save' , $php_performance );
418 // </editor-fold>
419
420 // -----------------------------------------------------------------------------------------------------------------
421 // == CREATE_THE 'NEW_BOOKING' ==
422 // -----------------------------------------------------------------------------------------------------------------
423 $create_booking_params = array(
424 'resource_id' => $create_params['resource_id'],
425 'custom_form' => $create_params['custom_form'],
426 'all_booking_data_arr' => $create_params['all_booking_data_arr'],
427 'dates_only_sql_arr' => $create_params['dates_only_sql_arr'],
428 'time_as_his_arr' => $create_params['time_as_his_arr'],
429 'is_from_admin_panel' => $create_params['is_from_admin_panel'],
430 'is_edit_booking' => $create_params['is_edit_booking'],
431 'is_duplicate_booking' => $create_params['is_duplicate_booking'],
432 'is_approve_booking' => $create_params['is_approve_booking'],
433 'how_many_items_to_book' => $create_params['how_many_items_to_book'],
434 'is_use_booking_recurrent_time' => $create_params['is_use_booking_recurrent_time'] // true | false
435 );
436 if ( ! empty( $create_params['sync_gid'] ) ) { $create_booking_params['sync_gid'] = $create_params['sync_gid']; }
437
438 $booking_new_arr = wpbc_db__booking_save( $create_booking_params, $where_to_save_booking );
439
440 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- BOOKING CREATION " >
441 if ( 'ok' !== $booking_new_arr['status'] ) {
442 $ajx_data_arr['status'] = $booking_new_arr['status'];
443 $ajx_data_arr['status_error'] = 'booking_can_not_save';
444 $ajx_data_arr['ajx_after_action_message'] = $booking_new_arr['message'];
445 $ajx_data_arr['ajx_after_action_message_status'] = 'error';
446 return array( 'ajx_data' => $ajx_data_arr );
447 }
448 // </editor-fold>
449
450 //FixIn: 9.9.0.36
451 if (
452 ( 0 !== $create_params['is_edit_booking'] ) // If edit booking
453 && ( 1 != $create_params['is_duplicate_booking'] ) // If not duplicate
454 ) {
455 // Log the cost info.
456 $is_add_timezone_offset = true;
457 $booking_note = wpbc_date_localized( gmdate( 'Y-m-d H:i:s' ), '[Y-m-d H:i]', $is_add_timezone_offset ) . ' ';
458 $booking_note .= __( 'The booking has been edited', 'booking' ) . '. | Edit URL: ' . esc_url_raw( $re_cleaned_params['request_uri'] ) . '';
459 make_bk_action( 'wpdev_make_update_of_remark', $booking_new_arr['booking_id'], $booking_note, true );
460 }
461 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
462 $php_performance = php_performance_END( 'wpbc_db__booking_save' , $php_performance );
463 // </editor-fold>
464
465 // -----------------------------------------------------------------------------------------------------------------
466 // Get payment form(s) and Update COST of the booking
467 // -----------------------------------------------------------------------------------------------------------------
468 $payment_params = array();
469
470 // Usually we have this: ( $str_dates__dd_mm_yyyy == $create_params['dates_only_sql_arr'] ) - but for ensure, use saved dates, e.g. $str_dates__dd_mm_yyyy
471 $payment_params['booked_dates_times_arr'] = array(
472 'dates_ymd_arr' => array_keys( $where_to_save_booking['resources_in_dates'] ), // [ 2023-10-20=>[], 2023-10-25=>[] ] -> [ "2023-10-20", "2023-10-25" ]
473 'times_his_arr' => $where_to_save_booking['time_to_book'] // ['16:00:01', '18:00:02']
474 );
475 $str_dates__dd_mm_yyyy = wpbc_convert_dates_arr__yyyy_mm_dd__to__dd_mm_yyyy( $payment_params['booked_dates_times_arr']['dates_ymd_arr'] ); // ['2023-10-20','2023-10-25'] => ['20.10.2023','25.10.2023']
476 $payment_params['str_dates__dd_mm_yyyy'] = implode( ',', $str_dates__dd_mm_yyyy ); // REQUIRED -- '14.11.2023, 15.11.2023, 16.11.2023, 17.11.2023'
477 $payment_params['booking_id'] = $booking_new_arr['booking_id']; // REQUIRED -- '2'
478 $payment_params['resource_id'] = $create_params['resource_id']; // REQUIRED -- '2' can be child resource (changed in wpbc_where_to_save() )
479 $payment_params['initial_resource_id'] = $local_params['initial_resource_id']; // REQUIRED -- '2' initial calendar - parent resource
480 $payment_params['form_data'] = $booking_new_arr['form_data']; // we re-save it, because here can be sync_guid and custom form new data from wpbc_db__booking_save(..) // REQUIRED -- 'text^selected_short_timedates_hint4^06/11/2018 14:00...'
481 $payment_params['times_array'] = array(
482 explode( ':', $where_to_save_booking['time_to_book'][0] ), // ["10","00","00"]
483 explode( ':', $where_to_save_booking['time_to_book'][1] ) // ["12","00","00"]
484 );
485 // Additional options
486 $payment_params['is_edit_booking'] = $create_params['is_edit_booking']; // => 0 0 | int - ID of the booking
487 $payment_params['custom_form'] = $create_params['custom_form']; // => '' '' | 'some_name'
488 $payment_params['is_duplicate_booking'] = $create_params['is_duplicate_booking']; // => 0 0 | 1
489 $payment_params['is_from_admin_panel'] = $create_params['is_from_admin_panel']; // => false true | false
490 $payment_params['is_show_payment_form'] = $create_params['is_show_payment_form']; // => 1 0 | 1
491 if ( $payment_params['is_from_admin_panel'] ) {
492 // $payment_params['is_show_payment_form'] = 0; //FixIn: 9.9.0.21
493 }
494 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
495 $php_performance = php_performance_START( 'wpbc_maybe_get_payment_form' , $php_performance );
496 // </editor-fold>
497
498 // GET PAYMENT FORMS ===============================================================================================
499 if ( function_exists( 'wpbc_maybe_get_payment_form' ) ) {
500
501 $response__payment_form__arr = wpbc_maybe_get_payment_form( $payment_params );
502
503 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- COSTS || PAYMENT_SYSTEMS " >
504 if (
505 ( ! empty( $response__payment_form__arr['status'] ) )
506 && ( 'ok' != $response__payment_form__arr['status'] )
507 ) {
508 $ajx_data_arr['status'] = $response__payment_form__arr['status'];
509 $ajx_data_arr['status_error'] = 'booking_can_not_save';
510 $ajx_data_arr['ajx_after_action_message'] = $response__payment_form__arr['message'];
511 $ajx_data_arr['ajx_after_action_message_status'] = 'error';
512 return array( 'ajx_data' => $ajx_data_arr );
513 }
514 // </editor-fold>
515
516 if ( ! empty( $response__payment_form__arr['costs_arr']['form_data'] ) ) {
517 $payment_params['form_data'] = $response__payment_form__arr['costs_arr']['form_data']; // we re-save it, because here can be [cost_correction] shortcode data
518 }
519 //TODO: Do we really need this in output $ajx_data_arr ???, because it stored in $confirmation
520 if ( ! empty( $response__payment_form__arr['gateways_output_arr'] ) ) {
521 $ajx_data_arr['gateways_output_arr'] = $response__payment_form__arr['gateways_output_arr'];
522 }
523 if ( function_exists( 'wpbc_if_zero_cost__approve_booking_dates' ) ) {
524 wpbc_if_zero_cost__approve_booking_dates( $payment_params['booking_id'] );
525 }
526
527 } else {
528 $response__payment_form__arr = $payment_params;
529 $response__payment_form__arr['status'] = 'ok';
530 }
531
532
533 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
534 $php_performance = php_performance_END( 'wpbc_maybe_get_payment_form' , $php_performance );
535
536 $php_performance = php_performance_START( 'emails_sending' , $php_performance );
537 // </editor-fold>
538
539 // -----------------------------------------------------------------------------------------------------------------
540 // == Emails ===
541 // -----------------------------------------------------------------------------------------------------------------
542 if ( 1 == $re_cleaned_params['is_emails_send'] ) {
543
544 $email_content = $payment_params['form_data'];
545
546 // If we output any text, then probably it's errors or warnings, we need to catch them
547 ob_start();
548 ob_clean();
549
550 if (
551 ( 0 === $local_params['is_edit_booking'] )
552 || ( 1 === $local_params['is_duplicate_booking'] ) //FixIn: 10.0.0.42
553 ){
554
555 // New booking to Admin
556 wpbc_send_email_new_admin( $payment_params['booking_id'], $payment_params['resource_id'], $email_content );
557
558 // New pending to Visitor
559 wpbc_send_email_new_visitor( $payment_params['booking_id'], $payment_params['resource_id'], $email_content ) ;
560
561 $is_booking_approved = wpbc_is_booking_approved( $payment_params['booking_id'] );
562 if ( $is_booking_approved ) {
563 // New approved to Visitor / Admin
564 wpbc_send_email_approved( $payment_params['booking_id'], 1 );
565 }
566
567 // Payment request from admin panel, if needed
568 if(
569 ( $payment_params['is_from_admin_panel'] )
570 && ( 'On' == get_bk_option( 'booking_payment_request_auto_send_in_bap' ) )
571 && ( function_exists( 'wpbc_send_email_payment_request' ) )
572 ){
573 $payment_reason = '';
574 $is_send = wpbc_send_email_payment_request( $payment_params['booking_id'], $payment_params['resource_id'], $email_content , $payment_reason );
575 }
576
577 do_action( 'wpbc_booking_approved' , $payment_params['booking_id'] , (int) $is_booking_approved );
578
579 } else {
580
581 // Edited booking to Visitor / Admin
582 if ( function_exists( 'wpbc_send_email_modified' ) ) {
583 wpbc_send_email_modified( $payment_params['booking_id'], $payment_params['resource_id'], $email_content );
584 }
585 }
586
587 $errors_on_email_sending_html = ob_get_contents();
588 ob_end_clean();
589
590 if ( ! empty( $errors_on_email_sending_html ) ) {
591 // Show these messages as warning after creation of the booking
592 $errors_on_email_sending_html = strip_tags( $errors_on_email_sending_html );
593 $errors_on_email_sending_html = esc_attr( $errors_on_email_sending_html );
594 $errors_on_email_sending_html = str_replace( "\\n", '', $errors_on_email_sending_html );
595
596 $ajx_data_arr['ajx_after_action_message_status'] = 'warning';
597 $ajx_data_arr['ajx_after_action_message'] = $errors_on_email_sending_html;
598 }
599 }
600
601 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
602 $php_performance = php_performance_END( 'emails_sending' , $php_performance );
603 // </editor-fold>
604
605 // -----------------------------------------------------------------------------------------------------------------
606 // == Track booking - New | Edit ===
607 // -----------------------------------------------------------------------------------------------------------------
608 /**
609 * Useful hook for Google Ads Conversion tracking. How to use this hook?
610 *
611 * Add code similar to this in your functions.php file in your theme, or in some other php file:
612 *
613 // Track adding new booking
614 //
615 // @param $params = array (
616 // 'str_dates__dd_mm_yyyy' => '08.10.2023,09.10.2023,10.10.2023,11.10.2023',
617 // 'booking_id' => 254,
618 // 'resource_id' => 11, // child or parent or single
619 // 'initial_resource_id' => 2, // parent or single
620 // 'form_data' => 'text^selected_short_dates_hint11^Sun...',
621 // 'times_array' => array ( array ( '14', '00', '01' ), array( '12', '00', '02' ) ),
622 // 'is_edit_booking' => 0,
623 // 'custom_form' => '',
624 // 'is_duplicate_booking' => 0,
625 // 'is_from_admin_panel' => false,
626 // 'is_show_payment_form' => 1
627 // )
628 function my_booking_tracking( $params ){
629 // Your code here
630 ?><!-- Google Code for Booking Conversion Page -->
631 <script type="text/javascript">
632 // Insert bellow your Google Conversion Code
633 </script><?php
634 }
635 add_action( 'wpbc_track_new_booking', 'my_booking_tracking' );
636 *
637 *
638 *
639 * Useful hook booking edit tracking
640 *
641 * Add code similar to this in your functions.php file in your theme, or in some other php file:
642 *
643 // Track edit existing booking
644 //
645 // @param $params = array (
646 // 'str_dates__dd_mm_yyyy' => '08.10.2023,09.10.2023,10.10.2023,11.10.2023',
647 // 'booking_id' => 254,
648 // 'resource_id' => 11, // child or parent or single
649 // 'initial_resource_id' => 2, // parent or single
650 // 'form_data' => 'text^selected_short_dates_hint11^Sun...',
651 // 'times_array' => array ( array ( '14', '00', '01' ), array( '12', '00', '02' ) ),
652 // 'is_edit_booking' => 1,
653 // 'custom_form' => '',
654 // 'is_duplicate_booking' => 0,
655 // 'is_from_admin_panel' => false,
656 // 'is_show_payment_form' => 1
657 // )
658 function my_edit_booking_tracking( $params ){
659 // Your code here
660 ?><!-- Google Code for Booking Conversion Page -->
661 <script type="text/javascript">
662 // Insert bellow your Google Conversion Code
663 </script><?php
664
665 }
666 add_action( 'wpbc_track_edit_booking', 'my_edit_booking_tracking' );
667 */
668 if ( 0 === $local_params['is_edit_booking'] ) {
669 do_action( 'wpbc_track_new_booking', $payment_params );
670 } else {
671 do_action( 'wpbc_track_edit_booking', $payment_params );
672 }
673
674
675 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
676 $php_performance = php_performance_START( 'confirmation' , $php_performance );
677 // </editor-fold>
678
679 // <editor-fold defaultstate="collapsed" desc=" == Confirmation data == " >
680
681
682 $confirmation_params_arr = array(
683 'is_from_admin_panel' => $payment_params['is_from_admin_panel'],
684
685 'booking_id' => $booking_new_arr['booking_id'], // 16102023
686 'resource_id' => $payment_params['resource_id'], // 1
687 'form_data' => $payment_params['form_data'], // 'text^selected_short_dates_hint11^Sun...',
688 'dates_ymd_arr' => $payment_params['booked_dates_times_arr']['dates_ymd_arr'], // [ '2023-10-20', '2023-10-25' ]
689 'times_his_arr' => $payment_params['booked_dates_times_arr']['times_his_arr'], // [ '16:00:01', '18:00:02' ]
690
691 'total_cost' => ( isset( $response__payment_form__arr['costs_arr'] ) && isset( $response__payment_form__arr['costs_arr']['total_cost'] ) )
692 ? $response__payment_form__arr['costs_arr']['total_cost']
693 : 0,
694 'deposit_cost' => ( isset( $response__payment_form__arr['costs_arr'] ) && isset( $response__payment_form__arr['costs_arr']['deposit_cost'] ) )
695 ? $response__payment_form__arr['costs_arr']['deposit_cost']
696 : 0,
697 'booking_summary' => ( ( ! empty( $response__payment_form__arr['gateways_output_arr'] ) ) && ( ! empty( $response__payment_form__arr['gateways_output_arr']['booking_summary'] ) ) )
698 ? $response__payment_form__arr['gateways_output_arr']['booking_summary']
699 : '',
700 'gateway_rows' => ( ( ! empty( $response__payment_form__arr['gateways_output_arr'] ) ) && ( ! empty( $response__payment_form__arr['gateways_output_arr']['gateway_rows'] ) ) )
701 ? $response__payment_form__arr['gateways_output_arr']['gateway_rows']
702 : ''
703 );
704 // It will not show payment form in Booking > Add booking page and if defined, do not make redirect
705 if ( $payment_params['is_from_admin_panel'] ) {
706
707 $confirmation_params_arr['ty_is_redirect'] = 'message'; // Do not make redirect, if it's in admin panel!
708
709 // But if we edit / duplicate the booking, then do redirection to Booking Listing page //FixIn: 9.9.0.3
710 if (
711 ( 0 !== $local_params['is_edit_booking'] )
712 // && ( empty( $local_params['is_duplicate_booking'] ) )
713 ){
714 $confirmation_params_arr['ty_is_redirect'] = 'page';
715 $confirmation_params_arr['ty_url'] = wpbc_get_bookings_url() . '&view_mode=vm_listing&tab=actions&wh_booking_id=' . $confirmation_params_arr['booking_id'];
716 }
717 }
718 $confirmation = wpbc_booking_confirmation( $confirmation_params_arr );
719
720 // </editor-fold>
721
722 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
723 $php_performance = php_performance_END( 'confirmation' , $php_performance );
724 // </editor-fold>
725
726
727 make_bk_action( 'finish_check_multiuser_params_for_client_side', $create_params['resource_id'] ); // Deactivate working with specific user in WP MU
728
729
730 // <editor-fold defaultstate="collapsed" desc=" = PERFORMANCE = " >
731 $php_performance = php_performance_END( 'total' , $php_performance );
732 $php_performance['other_code'] = - 1 * array_reduce( $php_performance,
733 function ( $sum, $item ) {
734 $sum += $item;
735 return $sum;
736 }
737 , - 2 * $php_performance['total'] ); // PERFORMANCE OTHER - after TOTAL
738 // </editor-fold>
739
740
741 return array( 'ajx_data' => $ajx_data_arr, // [ 'status' => "ok", 'wpbc_payment_output' => "<p>Dear John<br..." ]
742 'booking_id' => $booking_new_arr['booking_id'], // 254
743 'booking_arr' => $payment_params,
744 'php_performance' => $php_performance, // [ ... ]
745 'confirmation' => $confirmation // [ ]
746 );
747 }
748
749
750 // ---------------------------------------------------------------------------------------------------------------------
751 // New booking creation sub functions
752 // ---------------------------------------------------------------------------------------------------------------------
753
754 /**
755 * Save booking in DB
756 *
757 * @param array $create_params = [
758 * 'resource_id' => 10,
759 * 'dates_only_sql_arr' => [ '2023-10-04', '2023-10-05', '2023-10-06'],
760 * 'time_as_his_arr' => [ '14:00:01', '16:00:02' ],
761 * 'is_from_admin_panel' => false,
762 * 'is_edit_booking' => 0,
763 * 'is_duplicate_booking' => 0,
764 * 'is_approve_booking' => 0,
765 * 'how_many_items_to_book' => 2,
766 * 'custom_form' => '',
767 * 'is_use_booking_recurrent_time' => false,
768 * 'all_booking_data_arr' => [ 'rangetime' => [
769 * 'type' => 'selectbox-multiple',
770 * 'original_name' => 'rangetime2[]', //NOTE: here RESOURCE ID (2) can be from Parent resource, but resource_id can rely on child (10) resource
771 * 'name' => 'rangetime',
772 * 'value' => '14:00 - 16:00',
773 * ],
774 * 'name' => [ 'type' => 'text', 'original_name' => 'name2', ... ],
775 * ...
776 * ]
777 * ]
778 *
779 * @param $where_to_save_booking = [
780 * 'result' = 'ok',
781 * 'main__resource_id' = 2
782 * 'resources_in_dates' = [ 2023-10-18 = [ 2, 12, 10, 11 ]
783 * 2023-10-19 = [ 2, 12, 10, 11 ]
784 * 2023-10-20 = [ 2, 12, 10, 11 ]
785 * ],
786 * 'time_to_book' = [ "14:00:01" , "16:00:02" ]
787 * ]
788 *
789 * @return [
790 * 'status' => 'ok' 'ok' | 'error' | 'warning'
791 * 'booking_id' => 100 int
792 * 'message' => '' 'If error, then here can be description of error'
793 * 'form_data' => If 'ok' form data can be different here, 'custom_form' parameter, so it can add 'wpbc_custom_booking_form' field for identification, what custom booking form was used,
794 * ]
795 */
796 function wpbc_db__booking_save( $create_params, $where_to_save_booking ) {
797
798 /**
799 * Tip: $create_params['all_booking_data_arr'] - contain: [ 'field_name' => [ 'type' = "checkbox", 'original_name' = "fixed_fee2[]", 'name' = "fixed_fee", 'value' = "true" ] , ... ]
800 * $create_params['structured_booking_data_arr'] - contain: [ 'field_name' => 'field_value' , ... ]
801 */
802
803 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- 'Wrong resource ID " >
804 if ( empty( $create_params['resource_id'] ) ) {
805 return array( 'status' => 'error', 'message' => 'Wrong ID of booking resource: ' . $create_params['resource_id'] );
806 }
807 // </editor-fold>
808
809
810 $defaults = array(
811 'is_use_booking_recurrent_time' => ( 'On' === get_bk_option( 'booking_recurrent_time' ) )
812 );
813 $create_params = wp_parse_args( $create_params, $defaults );
814
815
816 $sql_field_arr = array();
817
818
819
820 // Is it was used custom booking form ?
821 if ( ! empty( $create_params['custom_form'] ) ) {
822 $create_params['all_booking_data_arr']['wpbc_custom_booking_form'] = array(
823 'type' => 'text',
824 'original_name' => 'wpbc_custom_booking_form' . $create_params['resource_id'],
825 'name' => 'wpbc_custom_booking_form',
826 'value' => $create_params['custom_form']
827 );
828 }
829
830 if ( ! empty( $create_params['sync_gid'] ) ) {
831 /**
832 * Such fields are comming from '../wp-content/plugins/booking/core/sync/wpbc-gcal-class.php' in function run()
833 */
834
835 // Escape any XSS injection from values in booking form
836 list( $create_params['sync_gid'] ) = wpbc_escape_any_xss_in_arr( array( $create_params['sync_gid'] ) );
837
838 $sql_field_arr[] = array( 'name' => 'sync_gid', 'type' => '%s', 'value' => $create_params['sync_gid'] );
839 }
840
841 // Escape any XSS injection from values in booking form
842 $create_params['all_booking_data_arr'] = wpbc_escape_any_xss_in_arr( $create_params['all_booking_data_arr'] );
843
844
845 //Set LAST check out day as AVAILABLE - remove it
846 if (
847 ( 'On' === get_bk_option( 'booking_last_checkout_day_available' ) )
848 && ( ! empty( $create_params['dates_only_sql_arr'] ) )
849 && ( count( $create_params['dates_only_sql_arr'] ) > 1 )
850 ) {
851 unset( $create_params['dates_only_sql_arr'][ ( count( $create_params['dates_only_sql_arr'] ) - 1 ) ] ); // Remove LAST selected day in calendar //FixIn: 6.2.3.6
852 // Delete last item //FixIn: 9.9.0.19
853 $resources_in_dates_last_key = key( array_slice( $where_to_save_booking['resources_in_dates'], - 1, 1, true ) );
854 unset( $where_to_save_booking['resources_in_dates'][ $resources_in_dates_last_key ] );
855 }
856
857 // :: ERROR ::
858 if ( empty( $create_params['dates_only_sql_arr'] ) ) { // No dates :?
859 return array( 'status' => 'error', 'message' => 'Sent request with no dates.' );
860 }
861
862 // <editor-fold defaultstate="collapsed" desc=" :: ERROR :: <- CHECK_IN_DATE_OLDER_THAN_CHECK_OUT " >
863 if ( count( $create_params['dates_only_sql_arr'] ) == 1 ) { // Is it single selected date ?
864
865 // Is 'check in' date/time older than 'check out' date/time when SINGLE day for booking? Then show error.
866
867 /**
868 * If we are having "change over" days activated and selected only 1 day in calendar,
869 * then we can have error: "Warning! Number of check in != check out times.", because "check in" day older than "check out" date.
870 */
871
872 $is_apply__check_in_out__10s = false;
873 $datestamp_check_in = wpbc_convert__sql_date__to_seconds( $create_params['dates_only_sql_arr'][0] . ' ' . $create_params['time_as_his_arr'][0], $is_apply__check_in_out__10s );
874 $datestamp_check_out = wpbc_convert__sql_date__to_seconds( $create_params['dates_only_sql_arr'][0] . ' ' . $create_params['time_as_his_arr'][1], $is_apply__check_in_out__10s );
875
876
877 if ( $datestamp_check_in > $datestamp_check_out ) {
878 $error_message = sprintf( 'Error! Your check in date %s older than check out date %s. <br>Try to select more dates or use different time.'
879 , '<strong>' . wpbc_convert__seconds__to_sql_date( $datestamp_check_in, $is_apply__check_in_out__10s ) . '</strong>'
880 , '<strong>' . wpbc_convert__seconds__to_sql_date( $datestamp_check_out, $is_apply__check_in_out__10s ) . '</strong>'
881 );
882 $error_message .= '<br>' . '<strong>Settings that can be reason of the issue:</strong> ';
883 if( 'On' === get_bk_option( 'booking_last_checkout_day_available' )){
884 $error_message .= '<br>' . 'You have enabled <strong>"Set check out date as available"</strong> option at Booking > Settings General page in "Calendar" section. ';
885 }
886 if ( 'On' === get_bk_option( 'booking_range_selection_time_is_active' ) ){
887 $error_message .= '<br>' . 'You have enabled <strong>"Use changeover days"</strong> option at Booking > Settings General page in "Calendar" section with check-in/out times: ' . get_bk_option( 'booking_range_selection_start_time' ) . '/' . get_bk_option( 'booking_range_selection_end_time' );
888 }
889 if ( $create_params['is_use_booking_recurrent_time'] ) {
890 $error_message .= '<br>' . 'You have enabled <strong>"Use time selections as recurrent time slots"</strong> option at Booking > Settings General page in "Calendar" section. ';
891 }
892 return array( 'status' => 'error', 'message' => $error_message );
893 }
894 }
895 // </editor-fold>
896
897 // Compose form data for DB. Can be different resource: 'selectbox-multiple^rangetime10[]^14..' <-> 'selectbox-multiple^rangetime2[]^14..' -> 'rangetime10' - child res. Previously 'rangetime2' - parent
898 $form_data = wpbc_encode_booking_data_to_string( $create_params['all_booking_data_arr'], $create_params['resource_id'] );
899
900
901 // -----------------------------------------------------------------------------------------------------------------
902 // APPROVED / PENDING
903 // -----------------------------------------------------------------------------------------------------------------
904 // Is approve booking
905 $auto_approve_new_bookings_is_active = trim( get_bk_option( 'booking_auto_approve_new_bookings_is_active' ) );
906 $is_approved_dates = ( $auto_approve_new_bookings_is_active == 'On' ) ? 1 : intval( $create_params['is_approve_booking'] );
907
908 // Auto approve only for specific booking resources
909 /**
910 * How to use "Auto approve bookings only for specific booking resources" ?
911 * Add code similar to this in your functions.php file in your theme, or in some other php file:
912 *
913 function my_wpbc_get_booking_resources_arr_to_auto_approve( $resources_to_approve ) {
914 $resources_to_approve = array( 9, 12, 33 ); // Array of booking resources ID, which you need to auto approve
915 return $resources_to_approve;
916 }
917 add_filter( 'wpbc_get_booking_resources_arr_to_auto_approve', 'my_wpbc_get_booking_resources_arr_to_auto_approve' );
918 */
919 $booking_resources_to_approve = array();
920 $booking_resources_to_approve = apply_filters( 'wpbc_get_booking_resources_arr_to_auto_approve', $booking_resources_to_approve ); //FixIn: 8.5.2.27
921 if ( in_array( $create_params['resource_id'], $booking_resources_to_approve ) ) {
922 $is_approved_dates = 1;
923 }
924
925 if (
926 ( $create_params['is_from_admin_panel'] ) // true | false
927 && ( get_bk_option( 'booking_auto_approve_bookings_if_added_in_admin_panel' ) == 'On' )
928 ){ //FixIn: 8.1.3.27
929 $is_approved_dates = 1;
930 }
931
932 // <editor-fold defaultstate="collapsed" desc=" == Save Booking == " >
933 // -----------------------------------------------------------------------------------------------------------------
934 // Save Booking
935 // -----------------------------------------------------------------------------------------------------------------
936 global $wpdb;
937
938 $sql_field_arr[] = array( 'name' => 'form', 'type' => '%s', 'value' => $form_data );
939 $sql_field_arr[] = array( 'name' => 'booking_type', 'type' => '%d', 'value' => $create_params['resource_id'] );
940 $sql_field_arr[] = array( 'name' => 'modification_date', 'type' => '%s', 'value' => gmdate( 'Y-m-d H:i:s' ) );
941 $sql_field_arr[] = array( 'name' => 'sort_date', 'type' => '%s', 'value' => $create_params['dates_only_sql_arr'][0] . ' ' . $create_params['time_as_his_arr'][0] );
942 $sql_field_arr[] = array( 'name' => 'hash', 'type' => 'MD5(%s)', 'value' => time() . '_' . rand( 1000, 1000000 ) );
943
944
945 if (
946 ( 0 == $create_params['is_edit_booking'] ) // If not edit, then INSERT
947 || ( 1 == $create_params['is_duplicate_booking'] ) // If duplicate, then INSERT
948 ){
949 // Saved only for new booking creation.
950 $sql_field_arr[] = array( 'name' => 'creation_date', 'type' => '%s', 'value' => gmdate( 'Y-m-d H:i:s' ) );
951
952 $sql_prepare_arr = array();
953 $sql_prepare_arr['name'] = array_map( function ( $value ) { return $value['name']; }, $sql_field_arr );
954 $sql_prepare_arr['type'] = array_map( function ( $value ) { return $value['type']; }, $sql_field_arr );
955 $sql_prepare_arr['value'] = array_map( function ( $value ) { return $value['value']; }, $sql_field_arr );
956
957 $sql_prepare_arr['name'] = implode( ', ', $sql_prepare_arr['name'] );
958 $sql_prepare_arr['type'] = implode( ', ', $sql_prepare_arr['type'] );
959
960 $sql = $wpdb->prepare( "INSERT INTO {$wpdb->prefix}booking "
961 . " ( {$sql_prepare_arr['name']} )"
962 . " VALUES ( {$sql_prepare_arr['type']} )"
963 , $sql_prepare_arr['value']
964 );
965
966 if ( false === $wpdb->query( $sql ) ) {
967 return array( 'status' => 'error','message' => 'Error. INSERT New Data in DB.' . ' FILE:' . __FILE__ . ' LINE:' . __LINE__ . ' SQL:' . $sql );
968 }
969 // Get ID of booking
970 $booking_id = (int) $wpdb->insert_id;
971
972 } else { // Edit - UPDATE
973
974 $booking_id = (int) $create_params['is_edit_booking'];
975
976 $sql_prepare_arr = array();
977 $sql_prepare_arr['set'] = array_map( function ( $value ) { return $value['name'] . '=' . $value['type']; }, $sql_field_arr );
978 $sql_prepare_arr['value'] = array_map( function ( $value ) { return $value['value']; }, $sql_field_arr );
979
980 $sql_prepare_arr['set'] = implode( ', ', $sql_prepare_arr['set'] );
981
982 $sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET "
983 . " {$sql_prepare_arr['set']} "
984 . " WHERE booking_id={$booking_id};"
985 , $sql_prepare_arr['value']
986 );
987 if ( false === $wpdb->query( $sql ) ){
988 return array( 'status' => 'error','message' => 'Error. UPDATE Exist Data in DB.' . ' FILE:' . __FILE__ . ' LINE:' . __LINE__ . ' SQL:' . $sql );
989 }
990
991 // Check if dates previously was approved.
992 $slct_sql = "SELECT approved FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_id}) LIMIT 0,1";
993 $slct_sql_results = $wpdb->get_results( $slct_sql );
994 $is_approved_dates = ( count( $slct_sql_results ) > 0 ) ? $slct_sql_results[0]->approved : $is_approved_dates;
995
996
997 $delete_sql = "DELETE FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_id})";
998 if ( false === $wpdb->query( $delete_sql ) ){
999 return array( 'status' => 'error','message' => 'Error. DELETE Old Dates in DB.' . ' FILE:' . __FILE__ . ' LINE:' . __LINE__ . ' SQL:' . $delete_sql );
1000 }
1001 }
1002 // </editor-fold>
1003
1004
1005 // <editor-fold defaultstate="collapsed" desc=" == Compose D A T E S for DB == " >
1006 // -----------------------------------------------------------------------------------------------------------------
1007 // Compose D A T E S for DB
1008 // -----------------------------------------------------------------------------------------------------------------
1009
1010 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1011 $field_names_arr = array( 'booking_id', 'booking_date', 'approved', 'type_id' );
1012 } else {
1013 $field_names_arr = array( 'booking_id', 'booking_date', 'approved' );
1014 }
1015 $field_names = implode( ', ', $field_names_arr );
1016
1017 $dates_sql = "INSERT INTO {$wpdb->prefix}bookingdates ( {$field_names} ) VALUES ";
1018 $insert_dates_arr = array();
1019
1020 $how_many_items_to_book = $create_params['how_many_items_to_book'];
1021 // $i - INDEX of child booking resource to book (if $how_many_items_to_book=1, then index always = 0 ) in [ 'resources_in_dates' = [ '2023-10-18' = [ 9, 12, 10, 11 ], ... ]...] - e.g. here = 9
1022 for( $i = 0; $i < $how_many_items_to_book; $i++) {
1023
1024 $date_number = 0;
1025 foreach ( $where_to_save_booking['resources_in_dates'] as $only_date_sql => $resources_in_date_arr ) {
1026
1027 $date_resource_id = $resources_in_date_arr[ $i ];
1028
1029 // $create_params['resource_id'] <- Main resource (saved in wp_booking )
1030 // $only_date_sql <- '2023-09-12'
1031 // $date_resource_id <- Child resource (need to save in wp_bookingdates) OR if ( $create_params['resource_id'] == $date_resource_id ) then NULL
1032
1033 // ---------------------------------------------------------------------------------------------------------
1034 // Is full day booking:
1035 if (
1036 ( '00:00' === substr( $where_to_save_booking['time_to_book'][0], 0, 5 ) )
1037 && (
1038 ( '24:00' === substr( $where_to_save_booking['time_to_book'][1], 0, 5 ) )
1039 || ( '00:00' === substr( $where_to_save_booking['time_to_book'][1], 0, 5 ) )
1040 )
1041 ){
1042 // Full days *******************************************************************************************
1043 $full_date_sql = $only_date_sql . ' 00:00:00';
1044
1045 $insert_dates_arr[] = wpbc_prepare_date_row( $booking_id, $full_date_sql, $is_approved_dates, $date_resource_id, $create_params['resource_id'] );
1046
1047 } else { // Times
1048
1049 if (
1050 ( $create_params['is_use_booking_recurrent_time'] ) // Activated option to book times as 'time-slots' OR
1051 || ( 1 === count( $where_to_save_booking['resources_in_dates'] ) ) // Selected only 1 date, so use time as time-slot
1052 ) {
1053 // Time slots in each day **************************************************************************
1054
1055 // Start Time
1056 $full_date_sql = $only_date_sql . ' ' . $where_to_save_booking['time_to_book'][0];
1057 $insert_dates_arr[] = wpbc_prepare_date_row( $booking_id, $full_date_sql, $is_approved_dates, $date_resource_id, $create_params['resource_id'] );
1058
1059 // End Time
1060 $full_date_sql = $only_date_sql . ' ' . $where_to_save_booking['time_to_book'][1];
1061 $insert_dates_arr[] = wpbc_prepare_date_row( $booking_id, $full_date_sql, $is_approved_dates, $date_resource_id, $create_params['resource_id'] );
1062
1063 } else {
1064 // Check in/out ************************************************************************************
1065
1066 if ( 0 == $date_number ) { // Is check in ?
1067
1068 $full_date_sql = $only_date_sql . ' ' . $where_to_save_booking['time_to_book'][0];
1069
1070 } else if ( ( count( $where_to_save_booking['resources_in_dates'] ) - 1 ) == $date_number ) { // Is check out ?
1071
1072 $full_date_sql = $only_date_sql . ' ' . $where_to_save_booking['time_to_book'][1];
1073
1074 } else { // Middle date - Full Date
1075 $full_date_sql = $only_date_sql . ' 00:00:00';
1076 }
1077
1078 $insert_dates_arr[] = wpbc_prepare_date_row( $booking_id, $full_date_sql, $is_approved_dates, $date_resource_id, $create_params['resource_id'] );
1079
1080 }
1081 }
1082 // ---------------------------------------------------------------------------------------------------------
1083 $date_number++;
1084 }
1085 }
1086
1087 $dates_sql .= implode( ', ', $insert_dates_arr );
1088
1089 if ( false === $wpdb->query( $dates_sql ) ) {
1090 return array( 'status' => 'error','message' => 'Error. INSERT "D A T E S" in DB.' . ' FILE:' . __FILE__ . ' LINE:' . __LINE__ . ' SQL:' . $dates_sql );
1091 }
1092
1093 // -----------------------------------------------------------------------------------------------------------------
1094 // End D A T E S
1095 // -----------------------------------------------------------------------------------------------------------------
1096 // </editor-fold>
1097
1098
1099 return array(
1100 'status' => 'ok'
1101 , 'booking_id' => $booking_id
1102 , 'form_data' => $form_data
1103 , 'message' => ''
1104 );
1105 }
1106
1107
1108 /**
1109 * Get SQL ROWs of VALUES for INSERT to DB
1110 *
1111 * @param int $booking_id 101 ID of the booking
1112 * @param string $full_date_sql '2023-09-12 10:00:01' SQL date
1113 * @param int $is_approved_dates 1 1 - approved, 0 - pending
1114 * @param int $date_resource_id ( >= biz_l ): 4 ID of child booking resource (if we save ONE booking in SEVERAL booking resources) field 'type_id' in wp_bookingdates
1115 * @param int $main_resource_id ( >= biz_l ): 1 ID of main (parent booking resource)
1116 *
1117 * @return string - SQL for dates VALUES to insert
1118 */
1119 function wpbc_prepare_date_row( $booking_id, $full_date_sql, $is_approved_dates, $date_resource_id, $main_resource_id ) {
1120
1121 global $wpdb;
1122
1123 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1124 $insert_dates_arr = ( $main_resource_id != $date_resource_id )
1125 ? $wpdb->prepare( "(%d, %s, %d, %d)", $booking_id, $full_date_sql, $is_approved_dates, $date_resource_id )
1126 : $wpdb->prepare( "(%d, %s, %d, NULL)", $booking_id, $full_date_sql, $is_approved_dates );
1127 } else {
1128 $insert_dates_arr = $wpdb->prepare( "(%d, %s, %d)", $booking_id, $full_date_sql, $is_approved_dates );
1129 }
1130
1131 return $insert_dates_arr;
1132 }
1133
1134
1135 // ---------------------------------------------------------------------------------------------------------------------
1136 // Support
1137 // ---------------------------------------------------------------------------------------------------------------------
1138
1139 /**
1140 * Get booking_id and resource_id if we are editing the booking, by booking hash
1141 *
1142 * @param $booking_hash
1143 * @param $server_request_url
1144 *
1145 * @return array | false false if not edit Otherwise [ 'booking_id': 100, 'resource_id': 3 ]
1146 */
1147 function wpbc_get_data__if_edit_booking( $booking_hash, $server_request_url ) {
1148
1149 $is_edit_booking = false;
1150 if ( ! empty( $booking_hash ) ) {
1151
1152 $my_booking_id_type = wpbc_hash__get_booking_id__resource_id( $booking_hash );
1153 if ( $my_booking_id_type !== false ) {
1154
1155 $is_edit_booking = array();
1156 $is_edit_booking['booking_id'] = intval( $my_booking_id_type[0] );
1157 $is_edit_booking['resource_id'] = intval( $my_booking_id_type[1] );
1158
1159 //TODO: test it. Check situation when we have editing "child booking resource", so need to re-update calendar and form to have it for parent resource. //FixIn: 6.1.1.9
1160 if ( strpos( $server_request_url, 'resource_no_update' ) === false ) { //FixIn: 9.4.2.3
1161
1162 if ( ( function_exists( 'wpbc_is_this_child_resource' ) ) && ( wpbc_is_this_child_resource( $is_edit_booking['resource_id'] ) ) ) {
1163 $bk_parent_br_id = wpbc_get_parent_resource( $is_edit_booking['resource_id'] );
1164
1165 $is_edit_booking['resource_id'] = intval( $bk_parent_br_id );
1166 }
1167 }
1168 }
1169 }
1170 return $is_edit_booking;
1171 }
1172
1173
1174 /**
1175 * Get how many items to book. Usually it's from [selectbox visitors "1" ... ] field.
1176 *
1177 * @param booking_form_data__arr = [
1178 * selected_short_dates_hint = "September 27, 2023 - September 28, 2023"
1179 * days_number_hint = "2"
1180 * rangetime = "16:00 - 18:00"
1181 * starttime = "21:00"
1182 * durationtime = "00:30"
1183 * name = "John"
1184 * secondname = "Smith"
1185 * email = "john.smith@server.com"
1186 * visitors = "1"
1187 * children = "0"
1188 * details = ""
1189 * ]
1190 *
1191 * @return int
1192 */
1193 function wpbc_get__how_many_items_to_book__in_booking_form( $booking_form_data__arr, $resource_id ){
1194
1195 $how_many_items_to_book = 1;
1196
1197 //TODO: Check about some URL parameter: '&resource_no_update' to book parent resource as single resource!
1198 if (
1199 ( class_exists( 'wpdev_bk_biz_l' ) )
1200 && ( 0 !== wpbc_get_child_resources_number( $resource_id ) ) // Here several child booking resources
1201 ) {
1202 $booking_capacity_field = wpbc_get__booking_capacity_field__name();
1203 if (
1204 ( ! empty( $booking_capacity_field ) )
1205 && ( isset( $booking_form_data__arr[ $booking_capacity_field ] ) )
1206 ){
1207 $how_many_items_to_book = intval( $booking_form_data__arr[ $booking_capacity_field ] ); // Get value of how many booking resources to book
1208 $how_many_items_to_book = ( $how_many_items_to_book > 0 ) ? $how_many_items_to_book : 1;
1209 }
1210 }
1211
1212 return $how_many_items_to_book;
1213 }
1214
1215
1216 /**
1217 * Get capacity field -- 'pure name'
1218 *
1219 * @return string - field name, or empty string - '' if not defined
1220 *
1221 * In DB, we are saved field name type and possible name of custom booking form in format: 'custom_form_name^field_type^capacity_field_name' -> 'minimal^select^adults'
1222 * or for standard form: 'select^visitors'
1223 * and here we get only field name: 'visitors'
1224 */
1225 function wpbc_get__booking_capacity_field__name() {
1226
1227 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1228
1229 if ( 'On' == get_bk_option( 'booking_quantity_control' ) ) {
1230
1231 $booking_capacity_field = get_bk_option( 'booking_capacity_field' );
1232
1233 if ( ! empty( $booking_capacity_field ) ) {
1234
1235 $booking_capacity_field = explode( '^', $booking_capacity_field );
1236
1237 if ( ! empty( $booking_capacity_field ) ) {
1238
1239 $booking_capacity_field_name = $booking_capacity_field[ count( $booking_capacity_field ) - 1 ];
1240
1241 return $booking_capacity_field_name;
1242 }
1243 }
1244 }
1245 }
1246 return '';
1247 }
1248
1249
1250 /**
1251 * Get time for booking from the booking form, as array of seconds: [ 0, 24 * 60 * 60 ] OR [ 10*60*60, 14*60*60 ]. If timefields not exist, then get time for full day booking.
1252 * @param $booking_form_data__arr
1253 *
1254 * @return array [ 0, 24 * 60 * 60 ] OR [ 10*60*60, 14*60*60 ] <- start and end time in seconds
1255 *
1256 * Example:
1257 *
1258 * // Firstly, we need to Get parsed booking form: [ name = "John", secondname = "Smith", email = "john.smith@server.com", visitors = "2",... ]
1259 * $structured_booking_data_arr = wpbc_get_parsed_booking_data_arr( $params["form_data"], $params["resource_id"], array( 'get' => 'value' ) );
1260 *
1261 * // Now get start/end times as seconds: [ 64800, 72000 ]
1262 * $time_as_seconds_arr = wpbc_get_in_booking_form__time_to_book_as_seconds_arr( $structured_booking_data_arr );
1263 */
1264 function wpbc_get_in_booking_form__time_to_book_as_seconds_arr( $booking_form_data__arr ){
1265
1266 $selected_time_fields = wpbc_get__selected_time_fields__in_booking_form__as_arr( $booking_form_data__arr );
1267
1268 // 2.2 Get selected SECONDS to book ---------------------------------------------------------------------------
1269 $time_as_seconds_arr = array( 0, 24 * 60 * 60 ); // Full day booking by default
1270
1271 foreach ( $selected_time_fields as $time_fields_obj ) { // { times_as_seconds: [ 21600, 23400 ], value_option_24h: '06:00 - 06:30', name: 'rangetime'}
1272
1273 if ( false !== strpos( $time_fields_obj['name'], 'rangetime' ) ) {
1274 $time_as_seconds_arr[ 0 ] = $time_fields_obj['times_as_seconds'][ 0 ];
1275 $time_as_seconds_arr[ 1 ] = $time_fields_obj['times_as_seconds'][ 1 ];
1276 //break; // If we have range-time then skip this loop
1277 }
1278 if ( false !== strpos( $time_fields_obj['name'], 'starttime' ) ) {
1279 $time_as_seconds_arr[ 0 ] = $time_fields_obj['times_as_seconds'][ 0 ];
1280 }
1281 if ( false !== strpos( $time_fields_obj['name'], 'endtime' ) ) {
1282 $time_as_seconds_arr[ 1 ] = $time_fields_obj['times_as_seconds'][ 0 ];
1283 }
1284 }
1285
1286 // For duration time we need to make a new loop, because we need to be sure that was defined START_TIME before this,
1287 // and end time was NOT defined, e.g. == (otherwise it's means that we already used END_TIME or RANGE_TIME)
1288 if (
1289 ( ( 0 ) !== $time_as_seconds_arr[ 0 ] )
1290 && ( (24 * 60 * 60 ) === $time_as_seconds_arr[ 1 ] )
1291 ){
1292 foreach ( $selected_time_fields as $time_fields_obj ) { // { times_as_seconds: [ 21600 ], value_option_24h: '06:00', name: 'durationtime'}
1293
1294 if ( false !== strpos( $time_fields_obj['name'], 'durationtime' ) ) {
1295 $time_as_seconds_arr[ 1 ] = $time_as_seconds_arr[ 0 ] + $time_fields_obj['times_as_seconds'][ 0 ];
1296 break;
1297 }
1298 }
1299 }
1300
1301 return $time_as_seconds_arr;
1302 }
1303
1304
1305 /**
1306 * Get all time fields in the booking form as array of objects
1307 *
1308 * @param booking_form_data__arr = [
1309 * selected_short_dates_hint = "September 27, 2023 - September 28, 2023"
1310 * days_number_hint = "2"
1311 * rangetime = "16:00 - 18:00"
1312 * starttime = "21:00"
1313 * durationtime = "00:30"
1314 * name = "John"
1315 * secondname = "Smith"
1316 * email = "john.smith@server.com"
1317 * visitors = "1"
1318 * children = "0"
1319 * details = ""
1320 * ]
1321 * @returns []
1322 *
1323 * Example:
1324 * [
1325 * [
1326 * name = "rangetime"
1327 * value_option_24h = "16:00 - 18:00"
1328 * times_as_seconds = [ 57600, 64800 ]
1329 * ]
1330 * [
1331 * name = "starttime"
1332 * value_option_24h = "21:00"
1333 * times_as_seconds = [ 75600 ]
1334 * ]
1335 * [
1336 * name = "durationtime"
1337 * value_option_24h = "00:30"
1338 * times_as_seconds = [ 1800 ]
1339 * ]
1340 * ]
1341 */
1342 function wpbc_get__selected_time_fields__in_booking_form__as_arr( $booking_form_data__arr ){
1343
1344 /**
1345 * Fields with [] like this select[name="rangetime1[]"]
1346 * it's when we have 'multiple' in shortcode: [select* rangetime multiple "06:00 - 06:30" ... ]
1347 */
1348 $time_fields_arr = array( 'rangetime', 'starttime', 'endtime', 'durationtime' );
1349
1350 $time_fields_obj_arr = array();
1351
1352 // Loop all Time Fields
1353 for ( $ctf = 0; $ctf < count( $time_fields_arr ); $ctf ++ ) {
1354
1355 $time_field = $time_fields_arr[ $ctf ];
1356 if ( isset( $booking_form_data__arr[ $time_field ] ) ) {
1357
1358 $value_option_seconds_arr = explode( '-', $booking_form_data__arr[ $time_field ] );
1359 $times_as_seconds_arr = array();
1360
1361 foreach ( $value_option_seconds_arr as $time_val ) {
1362 $time_val = trim( $time_val );
1363 if ( ! empty( $time_val ) ) {
1364 $start_end_times_arr = explode( ':', $time_val );
1365 $time_in_seconds = intval( $start_end_times_arr[0] ) * 60 * 60 + intval( $start_end_times_arr[1] ) * 60;
1366 $times_as_seconds_arr[] = $time_in_seconds;
1367 }
1368 }
1369
1370 if (! empty($times_as_seconds_arr)) {
1371
1372 $time_fields_obj_arr[] = array(
1373 'name' => $time_field,
1374 'value_option_24h' => $booking_form_data__arr[ $time_field ],
1375 'times_as_seconds' => $times_as_seconds_arr
1376 );
1377 }
1378 }
1379 }
1380
1381 return $time_fields_obj_arr;
1382 }
1383
1384
1385 //TODO: 2023-10-13 16:37
1386 // - create new function for confirmation section
1387 // - Update payment request
1388 // - create redirection to the "Thank you." page and show there conformation, and payment request"
1389 // - define in the settings new Stripe and PayPal button design as default !
1390 // - Be sure that 'booking_log_booking_actions' active by default
1391 // - test it in dark theme
1392 // - test closing booked dates if all time slot was booked - it's relative to 'different time slots in dif dates'
1393 // - add migrate support old dates selection variables
1394 // - check and remove other global Js vars
1395 // - Create wizard booking form style with steps ?
1396 // - Check Booking > Availability page relative new functionality of calendar_load !
1397 // - Update last func in wpbc-booking-new.php and remove it.
1398 // - Test capacity in dates and time slots
1399 // - Next 9.9 Customizer Wizard
1400 // - Next 9.9 Update search admin UI
1401 // - Next 9.9 - update functionality in Search functionality based on similar to where_to_save function.
1402 // - Next 9.9 refactor Dates functions.
1403 // Done. - Next 9.9 Update Booking > Settings General page to show tabs vertically in left column
1404 // Create the same navigation panel at the Pro Booking > Settings > Form page. At left column custom forms, at top tolbar selectio of Booking form and "Content of booking fields data" form.
1405 // Create the same navigation for Emails.
1406 /**
1407 * TODO: Performance improvement:
1408 * "other_code": 0.003080129623413086
1409 * "wpbc__where_to_save_booking": 0.060331106185913086
1410 * "wpbc_db__booking_save": 0.023384809494018555
1411 * "wpbc_maybe_get_payment_form": 1.3650128841400146 <-
1412 * "emails_sending": 1.5024309158325195 <-
1413 * "total": 2.9542438983917236
1414 */
1415