PluginProbe
Booking Calendar / 11.8.2
Booking Calendar v11.8.2
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 10.11.3 All 202 releases
booking / includes / _front_end / class-fe-render.php

class-fe-render.php in Booking Calendar 11.8.2, at includes/_front_end/class-fe-render.php

395 lines 17.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Front-End Render (Booking form, Calendar)
4 *
5 * File: /wp-content/plugins/booking/includes/_front_end/class-fe-render.php
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 class WPBC_FE_Render {
13
14 /**
15 * Echo or return helper (to preserve legacy API behavior).
16 *
17 * @param string $html - already escaped/sanitizing HTML content.
18 * @param bool $is_echo - do we need to echo it?.
19 *
20 * @return string|void
21 */
22 private static function echo_or_return( $html, $is_echo ) {
23
24 if ( $is_echo ) {
25
26 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
27
28 return;
29 }
30
31 return $html;
32 }
33
34 // -----------------------------------------------------------------------------------------------------------------
35
36 /**
37 * Render Booking Form (Calendar + Form).
38 *
39 * @param array $params_arr
40 *
41 * @return string|void
42 */
43 public static function render_booking_form( $params_arr = array() ) {
44
45 // Default parameters (keep identical to legacy).
46 $default_params = array(
47 'resource_id' => 1,
48 'cal_count' => 1,
49 'is_echo' => 1,
50 'custom_booking_form' => 'standard',
51 'selected_dates_without_calendar' => '',
52 'start_month_calendar' => false,
53 'shortcode_param__options' => '',
54 'calendar_dates_start' => '',
55 'calendar_dates_end' => '',
56 'booking_hash' => '',
57 'form_status' => 'published',
58 'booking_workflow' => 'classic',
59 'calendar_request_overrides' => array(),
60 );
61 $params_arr = wp_parse_args( $params_arr, $default_params );
62 $is_echo = ( ! empty( $params_arr['is_echo'] ) );
63
64 // ---------------------------------------------------------------------
65 // Hash resolution, e.g. $_GET['booking_hash'] for Booking Form rendering.
66 // ---------------------------------------------------------------------
67 $hash_res = WPBC_FE_Attr_Postprocessor::resolve_booking_hash_and_maybe_get_parent_resource_id( $params_arr, 'form' );
68 if ( ! $hash_res['ok'] ) {
69 return self::echo_or_return( $hash_res['error_html'], $is_echo );
70 }
71 $params_arr = $hash_res['params_arr'];
72
73 // ---------------------------------------------------------------------
74 // Normalize aggregate resource IDs. - "5;3;9" -> [ 'resource_id' => 5, 'aggregate_resource_id_arr' => [5,3,9] ].
75 // ---------------------------------------------------------------------
76 $aggregate_resource_id_arr = array();
77 $split = WPBC_FE_Attr_Postprocessor::split_aggregate_resource_id( $params_arr['resource_id'] );
78 $params_arr['resource_id'] = $split['resource_id'];
79 $aggregate_resource_id_arr = $split['aggregate_resource_id_arr'];
80
81 // ---------------------------------------------------------------------
82 // Validate resource_id parameter and check if booking resource exists.
83 // ---------------------------------------------------------------------
84 $resource_validation = WPBC_FE_Attr_Postprocessor::validate_resource_id( $params_arr['resource_id'] );
85 if ( true !== $resource_validation ) {
86 return self::echo_or_return( $resource_validation, $is_echo );
87 }
88
89 // ---------------------------------------------------------------------
90 // == MU ==
91 // ---------------------------------------------------------------------
92 make_bk_action( 'check_multiuser_params_for_client_side', $params_arr['resource_id'] );
93
94 // Render a focused cancellation confirmation instead of loading the complete booking form and calendar.
95 if ( WPBC_GET_Request::has_get( 'booking_cancel' ) && function_exists( 'wpbc_customer_access_render_cancellation_confirmation' ) ) {
96 $booking_hash = sanitize_text_field( wp_unslash( (string) $params_arr['booking_hash'] ) );
97 if ( '' === $booking_hash ) {
98 $booking_hash = WPBC_GET_Request::get_sanitized( 'booking_hash' );
99 }
100
101 $cancellation_html = wpbc_customer_access_render_cancellation_confirmation( $booking_hash, $params_arr['resource_id'] );
102
103 /**
104 * Filters the complete visitor cancellation confirmation markup.
105 *
106 * @param string $cancellation_html Rendered confirmation markup.
107 * @param int $resource_id Resource ID used by the front-end form container.
108 * @param string $booking_hash Sanitized booking credential from the cancellation URL.
109 */
110 $cancellation_html = apply_filters(
111 'wpbc_customer_booking_cancellation_confirmation_html',
112 $cancellation_html,
113 absint( $params_arr['resource_id'] ),
114 $booking_hash
115 );
116
117 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
118 $my_result = apply_filters( 'wpdev_booking_form', ' ' . $cancellation_html . ' ', $params_arr['resource_id'] );
119
120 make_bk_action( 'finish_check_multiuser_params_for_client_side', $params_arr['resource_id'] );
121
122 return self::echo_or_return( $my_result, $is_echo );
123 }
124
125 // ---------------------------------------------------------------------
126 // Normalize calendar_dates_start/end.
127 // ---------------------------------------------------------------------
128 $calendar_dates_range = WPBC_FE_Attr_Postprocessor::normalize_calendar_dates_range( $params_arr['calendar_dates_start'], $params_arr['calendar_dates_end'] );
129 $classic_booking_context_token = '';
130 if ( function_exists( 'wpbc_classic_booking_context_encode' ) ) {
131 $classic_booking_context_token = wpbc_classic_booking_context_encode(
132 array(
133 'booking_workflow' => $params_arr['booking_workflow'],
134 'resource_id' => $params_arr['resource_id'],
135 'calendar_dates_start' => $calendar_dates_range['start'],
136 'calendar_dates_end' => $calendar_dates_range['end'],
137 'custom_form' => $params_arr['custom_booking_form'],
138 'aggregate_resource_ids' => $aggregate_resource_id_arr,
139 )
140 );
141 }
142
143 // ---------------------------------------------------------------------
144 // Calendar load params (keep identical keys).
145 // ---------------------------------------------------------------------
146 $calendar_load_params = array(
147 'resource_id' => $params_arr['resource_id'],
148 'aggregate_resource_id_arr' => $aggregate_resource_id_arr,
149 'selected_dates_without_calendar' => $params_arr['selected_dates_without_calendar'],
150 'calendar_number_of_months' => $params_arr['cal_count'],
151 'start_month_calendar' => $params_arr['start_month_calendar'],
152 'shortcode_options' => $params_arr['shortcode_param__options'],
153 'custom_form' => $params_arr['custom_booking_form'],
154 'calendar_dates_start' => $calendar_dates_range['start'],
155 'calendar_dates_end' => $calendar_dates_range['end'],
156 'classic_booking_context_token' => $classic_booking_context_token,
157 'calendar_request_overrides' => $params_arr['calendar_request_overrides'],
158 );
159
160 $start_script_code = wpbc__calendar__load( $calendar_load_params );
161
162 // Disable booked time slots when selected date is predefined (legacy behavior).
163 if ( '' !== $params_arr['selected_dates_without_calendar'] ) {
164 $assets_key = 'wpbc:disable_time_fields_in_booking_form:' . intval( $params_arr['resource_id'] );
165
166 // Fire on all booking dates loaded. // FixIn: 10.14.17.2.
167 $local_js_code = " jQuery( 'body' ).on( 'wpbc_calendar_ajx__loaded_data', function ( event, loaded_resource_id ){ ";
168 $local_js_code .= ' if ( loaded_resource_id == ' . intval( $params_arr['resource_id'] ) . ' ){ ';
169 $local_js_code .= ' wpbc_disable_time_fields_in_booking_form(' . intval( $params_arr['resource_id'] ) . ')';
170 $local_js_code .= ' }';
171 $local_js_code .= '} );';
172
173 $added = WPBC_FE_Assets::add_jq_ready_js_to_wp_script( 'wpbc_all', $local_js_code, $assets_key );
174 if ( ! $added ) {
175 $start_script_code .= WPBC_FE_Assets::add_inline_js( $local_js_code, $assets_key ); // Fallback to direct inline JS, if previosly not edded script.
176 }
177 }
178
179 // ---------------------------------------------------------------------
180 // For Phase #1 we still use legacy HTML builder for the form body. (Later phases will move it fully.)
181 // ---------------------------------------------------------------------
182 $legacy = wpbc_get_legacy_booking_instance();
183 if ( ! $legacy ) {
184 $err = '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__( 'Oops!', 'booking' ) . '</strong> ' . esc_html__( 'Booking Calendar front-end renderer is not available. Please contact support.', 'booking' ) . '</div></div></div>';
185 return self::echo_or_return( $err, $is_echo );
186 }
187
188 $form_html = WPBC_FE_Form_Body_Renderer::render(
189 array(
190 'resource_id' => $params_arr['resource_id'],
191 'custom_booking_form' => $params_arr['custom_booking_form'],
192 'form_status' => $params_arr['form_status'],
193 'selected_dates_without_calendar' => $params_arr['selected_dates_without_calendar'],
194 'cal_count' => $params_arr['cal_count'],
195 'shortcode_param__options' => $params_arr['shortcode_param__options'],
196 'booking_hash' => $params_arr['booking_hash'],
197 'legacy_instance' => $legacy,
198 )
199 );
200
201 $my_result = ' ' . $form_html . ' ' . $start_script_code;
202
203
204 // Add DIV structure, where to show payment form.
205 $my_result = apply_filters( 'wpdev_booking_form', $my_result, $params_arr['resource_id'] ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
206
207 // == MU ==
208 make_bk_action( 'finish_check_multiuser_params_for_client_side', $params_arr['resource_id'] );
209
210 return self::echo_or_return( $my_result, $is_echo );
211 }
212
213
214 /**
215 * Render Availability Calendar Only.
216 *
217 * @param array $params_arr
218 *
219 * @return string|void
220 */
221 public static function render_calendar_only( $params_arr = array() ) {
222
223 $default_params = array(
224 'resource_id' => 1,
225 'cal_count' => 1,
226 'is_echo' => 1,
227 'start_month_calendar' => false,
228 'shortcode_param__options' => '',
229 'calendar_dates_start' => '',
230 'calendar_dates_end' => '',
231 'booking_hash' => '',
232 'calendar_request_overrides' => array(),
233 );
234 $params_arr = wp_parse_args( $params_arr, $default_params );
235 $is_echo = ( ! empty( $params_arr['is_echo'] ) );
236
237 // ---------------------------------------------------------------------
238 // Hash resolution, e.g. $_GET['booking_hash'] for Booking Form rendering.
239 // ---------------------------------------------------------------------
240 $hash_res = WPBC_FE_Attr_Postprocessor::resolve_booking_hash_and_maybe_get_parent_resource_id( $params_arr, 'calendar' );
241 if ( ! $hash_res['ok'] ) {
242 return self::echo_or_return( $hash_res['error_html'], $is_echo );
243 }
244 $params_arr = $hash_res['params_arr'];
245
246 // ---------------------------------------------------------------------
247 // Normalize aggregate resource IDs. - "5;3;9" -> [ 'resource_id' => 5, 'aggregate_resource_id_arr' => [5,3,9] ].
248 // ---------------------------------------------------------------------
249 $aggregate_resource_id_arr = array();
250 $split = WPBC_FE_Attr_Postprocessor::split_aggregate_resource_id( $params_arr['resource_id'] );
251 $params_arr['resource_id'] = $split['resource_id'];
252 $aggregate_resource_id_arr = $split['aggregate_resource_id_arr'];
253
254
255 // ---------------------------------------------------------------------
256 // Validate resource_id parameter and check if booking resource exists.
257 // ---------------------------------------------------------------------
258 $resource_validation = WPBC_FE_Attr_Postprocessor::validate_resource_id( $params_arr['resource_id'] );
259 if ( true !== $resource_validation ) {
260 return self::echo_or_return( $resource_validation, $is_echo );
261 }
262
263 // ---------------------------------------------------------------------
264 // == MU ==
265 // ---------------------------------------------------------------------
266 make_bk_action( 'check_multiuser_params_for_client_side', $params_arr['resource_id'] );
267
268 // ---------------------------------------------------------------------
269 // Normalize calendar_dates_start/end.
270 // ---------------------------------------------------------------------
271 $calendar_dates_range = WPBC_FE_Attr_Postprocessor::normalize_calendar_dates_range( $params_arr['calendar_dates_start'], $params_arr['calendar_dates_end'] );
272
273 $calendar_load_params = array(
274 'resource_id' => $params_arr['resource_id'],
275 'aggregate_resource_id_arr' => $aggregate_resource_id_arr,
276 'selected_dates_without_calendar' => '',
277 'calendar_number_of_months' => $params_arr['cal_count'],
278 'start_month_calendar' => $params_arr['start_month_calendar'],
279 'shortcode_options' => $params_arr['shortcode_param__options'],
280 'custom_form' => 'standard', // Because we show only 'AVAILABILITY CALENDAR' without the form, at all.
281 'calendar_dates_start' => $calendar_dates_range['start'],
282 'calendar_dates_end' => $calendar_dates_range['end'],
283 'calendar_request_overrides' => $params_arr['calendar_request_overrides'],
284 );
285 $start_script_code = wpbc__calendar__load( $calendar_load_params );
286
287
288 $my_result = '<div style="clear:both;height:10px;"></div>';
289 $my_result .= wpbc_pre_get_calendar_html( $params_arr['resource_id'], $params_arr['cal_count'], $params_arr['shortcode_param__options'] );
290 $my_result .= ' ' . $start_script_code;
291
292 // Keep legacy filter.
293 $my_result = apply_filters( 'wpdev_booking_calendar', $my_result, $params_arr['resource_id'] ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
294
295 $booking_form_is_using_bs_css = get_bk_option( 'booking_form_is_using_bs_css' );
296 $my_result = '<span ' . ( ( 'On' === $booking_form_is_using_bs_css ) ? 'class="wpdevelop"' : '' ) . '>' . $my_result . '</span>';
297
298 // == MU ==
299 make_bk_action( 'finish_check_multiuser_params_for_client_side', $params_arr['resource_id'] );
300
301 return self::echo_or_return( $my_result, $is_echo );
302 }
303
304 }
305
306
307 /**
308 * Try to get legacy wpdev_booking instance (for Phase #1 fallback calls).
309 *
310 * @return wpdev_booking|null
311 */
312 function wpbc_get_legacy_booking_instance() {
313
314 if ( ! function_exists( 'WPBC' ) ) {
315 return null;
316 }
317
318 $wpbc_instance = WPBC();
319 if ( ! $wpbc_instance ) {
320 return null;
321 }
322
323 if ( empty( $wpbc_instance->booking_obj ) && class_exists( 'wpdev_booking' ) ) {
324 // Lazy boot as a last resort (avoid doing this if you don’t want any boot during true WPBC ajax).
325 $wpbc_instance->booking_obj = new wpdev_booking();
326 }
327
328 return ( $wpbc_instance->booking_obj instanceof wpdev_booking ) ? $wpbc_instance->booking_obj : null;
329 }
330
331
332
333 //TODO: replace evrywhere wpbc_get_rendered_booking_form_html() to some simpler call.
334
335 /**
336 * Get HTML of Rendered Booking From - Legacy type of calling render.
337 *
338 * @param $resource_id
339 * @param $cal_count
340 * @param $is_echo
341 * @param $my_booking_form
342 * @param $my_selected_dates_without_calendar
343 * @param $start_month_calendar
344 * @param $shortcode_param__options
345 *
346 * @return string|null
347 */
348 function wpbc_get_rendered_booking_form_html( $resource_id = 1, $cal_count = 1, $is_echo = 1, $my_booking_form = 'standard', $my_selected_dates_without_calendar = '', $start_month_calendar = false, $shortcode_param__options = array() ) {
349
350 return WPBC_FE_Render::render_booking_form(
351 array(
352 'resource_id' => $resource_id,
353 'cal_count' => $cal_count,
354 'is_echo' => $is_echo,
355 'custom_booking_form' => $my_booking_form,
356 'selected_dates_without_calendar' => $my_selected_dates_without_calendar,
357 'start_month_calendar' => $start_month_calendar,
358 'shortcode_param__options' => $shortcode_param__options,
359 )
360 );
361 }
362
363 /**
364 * Get booking form rendered HTML content without echo.
365 *
366 * @param $resource_id
367 * @param $cal_count
368 * @param $my_booking_form
369 * @param $my_selected_dates_without_calendar
370 * @param $start_month_calendar
371 * @param $shortcode_param__options
372 *
373 * @return string|null
374 */
375 function wpbc_get_rendered_booking_form_html__noecho( $resource_id = 1, $cal_count = 1, $my_booking_form = 'standard', $my_selected_dates_without_calendar = '', $start_month_calendar = false, $shortcode_param__options = array() ) {
376
377 $my_result = WPBC_FE_Render::render_booking_form(
378 array(
379 'resource_id' => $resource_id,
380 'cal_count' => $cal_count,
381 'is_echo' => 0,
382 'custom_booking_form' => $my_booking_form,
383 'selected_dates_without_calendar' => $my_selected_dates_without_calendar,
384 'start_month_calendar' => $start_month_calendar,
385 'shortcode_param__options' => $shortcode_param__options,
386 )
387 );
388 return $my_result;
389 }
390
391 /**
392 * This hook exists in personal.php file for the [bookingselect ..]
393 */
394 add_bk_filter( 'wpdevbk_get_booking_form', 'wpbc_get_rendered_booking_form_html__noecho' );
395