PluginProbe
Booking Calendar / 11.0
Booking Calendar v11.0
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 / page-availability-general / availability_general__page.php

availability_general__page.php in Booking Calendar 11.0, at includes/page-availability-general/availability_general__page.php

1,110 lines 42.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * General availability admin page.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Check whether the General Availability page is active.
14 *
15 * @return bool
16 */
17 function wpbc_availability_general__is_page() {
18
19 if ( ! is_admin() ) {
20 return false;
21 }
22
23 if ( ! function_exists( 'wpbc_is_availability_page' ) || ! wpbc_is_availability_page() ) {
24 return false;
25 }
26
27 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
28 $active_tab = isset( $_REQUEST['tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) : '';
29
30 return ( 'general_availability' === $active_tab );
31 }
32
33 /**
34 * Enqueue CSS for General Availability.
35 *
36 * @param string $where_to_load Where assets are loaded.
37 *
38 * @return void
39 */
40 function wpbc_availability_general_enqueue_css_files( $where_to_load ) {
41
42 if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) {
43 return;
44 }
45
46 if ( ! wpbc_availability_general__is_page() ) {
47 return;
48 }
49
50 wp_enqueue_style(
51 'wpbc-availability-general-page',
52 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/availability_general_page.css',
53 array( 'wpbc-calendar', 'wpbc-all-admin' ),
54 WP_BK_VERSION_NUM
55 );
56 }
57 add_action( 'wpbc_enqueue_css_files', 'wpbc_availability_general_enqueue_css_files', 66 );
58
59 /**
60 * Enqueue JS for General Availability.
61 *
62 * @param string $where_to_load Where assets are loaded.
63 *
64 * @return void
65 */
66 function wpbc_availability_general_enqueue_js_files( $where_to_load ) {
67
68 if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) {
69 return;
70 }
71
72 if ( ! wpbc_availability_general__is_page() ) {
73 return;
74 }
75
76 wp_enqueue_script(
77 'wpbc-availability-general-page',
78 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/availability_general_page.js',
79 array( 'jquery', 'wpbc_all' ),
80 WP_BK_VERSION_NUM,
81 array( 'in_footer' => WPBC_JS_IN_FOOTER )
82 );
83
84 wp_localize_script(
85 'wpbc-availability-general-page',
86 'wpbc_availability_general_page',
87 array(
88 'ajax_url' => admin_url( 'admin-ajax.php' ),
89 'nonce' => wp_create_nonce( 'wpbc_availability_general_ajax_nonce' ),
90 'action' => 'WPBC_AJX_AVAILABILITY_GENERAL_SAVE',
91 'preview_action' => 'WPBC_AJX_AVAILABILITY_GENERAL_PREVIEW',
92 'default_settings' => wpbc_availability_general__get_default_settings(),
93 'is_buffer_available' => class_exists( 'wpdev_bk_biz_m' ),
94 'is_available_limit_available' => class_exists( 'wpdev_bk_biz_m' ),
95 'i18n' => array(
96 'saving' => __( 'Saving', 'booking' ),
97 'saved' => __( 'General availability settings updated.', 'booking' ),
98 'reset_applied' => __( 'Default availability settings are ready for preview. Click Save Changes to apply them.', 'booking' ),
99 'save_failed' => __( 'Unable to save general availability settings.', 'booking' ),
100 'reset_confirm' => __( 'Reset controls to default values? Saved settings will not change until you click Save Changes.', 'booking' ),
101 'preview_failed' => __( 'Unable to refresh calendar preview.', 'booking' ),
102 'security_error' => __( 'Security check failed.', 'booking' ),
103 'loading' => __( 'Loading', 'booking' ),
104 'buffer_preview' => __( 'Buffer preview', 'booking' ),
105 'before_booking' => __( 'Before booking', 'booking' ),
106 'after_booking' => __( 'After booking', 'booking' ),
107 'no_buffer' => __( 'No booking buffer is selected.', 'booking' ),
108 ),
109 )
110 );
111 }
112 add_action( 'wpbc_enqueue_js_files', 'wpbc_availability_general_enqueue_js_files', 66 );
113
114 /**
115 * Print tooltip initializer for General Availability.
116 *
117 * @return void
118 */
119 function wpbc_availability_general_print_tooltip_js() {
120
121 if ( ! wpbc_availability_general__is_page() ) {
122 return;
123 }
124
125 if ( function_exists( 'wpbc_bs_javascript_tooltips' ) ) {
126 wpbc_bs_javascript_tooltips();
127 }
128 }
129 add_action( 'admin_footer', 'wpbc_availability_general_print_tooltip_js', 67 );
130
131 /**
132 * Get resource options.
133 *
134 * @return array
135 */
136 function wpbc_availability_general__get_resources() {
137
138 $resources = array();
139
140 if ( function_exists( 'wpbc_ajx_get_sorted_booking_resources_arr' ) && function_exists( 'wpbc_ajx_get_all_booking_resources_arr' ) ) {
141 $resource_rows = wpbc_ajx_get_sorted_booking_resources_arr( wpbc_ajx_get_all_booking_resources_arr() );
142 foreach ( $resource_rows as $resource ) {
143 $resources[] = array(
144 'id' => isset( $resource['booking_type_id'] ) ? (int) $resource['booking_type_id'] : 1,
145 'title' => isset( $resource['title'] ) ? $resource['title'] : __( 'Booking resource', 'booking' ),
146 );
147 }
148 }
149
150 if ( empty( $resources ) ) {
151 $resources[] = array(
152 'id' => function_exists( 'wpbc_get_default_resource' ) ? (int) wpbc_get_default_resource() : 1,
153 'title' => __( 'Booking resource', 'booking' ),
154 );
155 }
156
157 return $resources;
158 }
159
160 /**
161 * Get capability required to manage General Availability.
162 *
163 * @return string
164 */
165 function wpbc_availability_general__get_manage_cap() {
166
167 $min_user_role = get_bk_option( 'booking_user_role_settings' );
168 $capability = array(
169 'administrator' => 'activate_plugins',
170 'editor' => 'publish_pages',
171 'author' => 'publish_posts',
172 'contributor' => 'edit_posts',
173 'subscriber' => 'read',
174 );
175
176 return isset( $capability[ $min_user_role ] ) ? $capability[ $min_user_role ] : 'manage_options';
177 }
178
179 /**
180 * Get selected resource ID for preview.
181 *
182 * @return int
183 */
184 function wpbc_availability_general__get_preview_resource_id() {
185
186 $resources = wpbc_availability_general__get_resources();
187 $default_resource = isset( $resources[0]['id'] ) ? (int) $resources[0]['id'] : 1;
188
189 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
190 $resource_id = isset( $_REQUEST['resource_id'] ) ? absint( wp_unslash( $_REQUEST['resource_id'] ) ) : $default_resource;
191 $resource_ids = wp_list_pluck( $resources, 'id' );
192
193 return in_array( $resource_id, $resource_ids, true ) ? $resource_id : $default_resource;
194 }
195
196 /**
197 * Get selected month count for preview.
198 *
199 * @return int
200 */
201 function wpbc_availability_general__get_preview_months_count() {
202
203 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
204 $months = isset( $_REQUEST['months_count'] ) ? absint( wp_unslash( $_REQUEST['months_count'] ) ) : 6;
205
206 return in_array( $months, array( 1, 2, 3, 4, 6, 12 ), true ) ? $months : 6;
207 }
208
209 /**
210 * Validate preview resource ID.
211 *
212 * @param int $resource_id Resource ID.
213 *
214 * @return int
215 */
216 function wpbc_availability_general__sanitize_preview_resource_id( $resource_id ) {
217
218 $resources = wpbc_availability_general__get_resources();
219 $default_resource = isset( $resources[0]['id'] ) ? (int) $resources[0]['id'] : 1;
220 $resource_ids = wp_list_pluck( $resources, 'id' );
221
222 return in_array( (int) $resource_id, $resource_ids, true ) ? (int) $resource_id : $default_resource;
223 }
224
225 /**
226 * Validate preview months count.
227 *
228 * @param int $months_count Number of months.
229 *
230 * @return int
231 */
232 function wpbc_availability_general__sanitize_preview_months_count( $months_count ) {
233
234 $months_count = absint( $months_count );
235
236 return in_array( $months_count, array( 1, 2, 3, 4, 6, 12 ), true ) ? $months_count : 6;
237 }
238
239 /**
240 * Get unavailable-from-today select options.
241 *
242 * @return array
243 */
244 function wpbc_availability_general__get_unavailable_from_today_options() {
245
246 $options = array( '0' => ' - ' );
247
248 foreach ( range( 5, 55, 5 ) as $extra_num ) {
249 $options[ $extra_num . 'm' ] = $extra_num . ' ' . __( 'minutes', 'booking' );
250 }
251 $options['60m'] = '1 ' . __( 'hour', 'booking' );
252 foreach ( range( 65, 115, 5 ) as $extra_num ) {
253 $options[ $extra_num . 'm' ] = '1 ' . __( 'hour', 'booking' ) . ' ' . ( $extra_num - 60 ) . ' ' . __( 'minutes', 'booking' );
254 }
255 foreach ( range( 120, 1380, 60 ) as $extra_num ) {
256 $options[ $extra_num . 'm' ] = ( $extra_num / 60 ) . ' ' . __( 'hours', 'booking' );
257 }
258
259 $options['1'] = '1 ' . __( 'day', 'booking' );
260 for ( $ii = 2; $ii < 92; $ii++ ) {
261 $options[ (string) $ii ] = $ii . ' ' . __( 'days', 'booking' );
262 }
263
264 return $options;
265 }
266
267 /**
268 * Get available-from-today select options.
269 *
270 * @return array
271 */
272 function wpbc_availability_general__get_available_from_today_options() {
273
274 $options = array( '' => ' - ' );
275
276 foreach ( range( 1, 365 ) as $value ) {
277 $options[ (string) $value ] = (string) $value;
278 }
279
280 return $options;
281 }
282
283 /**
284 * Get minute buffer options.
285 *
286 * @return array
287 */
288 function wpbc_availability_general__get_buffer_minutes_options() {
289
290 $options = array( '' => ' - ' );
291
292 foreach ( range( 5, 55, 5 ) as $extra_num ) {
293 $options[ $extra_num . 'm' ] = $extra_num . ' ' . __( 'minutes', 'booking' );
294 }
295 $options['60m'] = '1 ' . __( 'hour', 'booking' );
296 foreach ( range( 65, 115, 5 ) as $extra_num ) {
297 $options[ $extra_num . 'm' ] = '1 ' . __( 'hour', 'booking' ) . ' ' . ( $extra_num - 60 ) . ' ' . __( 'minutes', 'booking' );
298 }
299 foreach ( range( 120, 1380, 60 ) as $extra_num ) {
300 $options[ $extra_num . 'm' ] = ( $extra_num / 60 ) . ' ' . __( 'hours', 'booking' );
301 }
302
303 return $options;
304 }
305
306 /**
307 * Get day buffer options.
308 *
309 * @return array
310 */
311 function wpbc_availability_general__get_buffer_days_options() {
312
313 $options = array( '' => ' - ' );
314
315 foreach ( range( 1, 30 ) as $extra_num ) {
316 $options[ $extra_num . 'd' ] = $extra_num . ' ' . __( 'day(s)', 'booking' );
317 }
318
319 return $options;
320 }
321
322 /**
323 * Get time options for future working-time controls.
324 *
325 * @param string $selected Selected value.
326 *
327 * @return array
328 */
329 function wpbc_availability_general__get_working_time_options( $selected = '' ) {
330
331 $options = array();
332
333 for ( $minutes = 0; $minutes <= 1440; $minutes += 30 ) {
334 $hours = (int) floor( $minutes / 60 );
335 $mins = $minutes % 60;
336 $value = sprintf( '%02d:%02d', $hours, $mins );
337 $label = ( 1440 === $minutes ) ? '24:00' : $value;
338
339 $options[ $value ] = $label;
340 }
341
342 if ( '' !== $selected && ! isset( $options[ $selected ] ) ) {
343 $options[ $selected ] = $selected;
344 }
345
346 return $options;
347 }
348
349 /**
350 * Render a select field.
351 *
352 * @param string $name Field name.
353 * @param array $options Options.
354 * @param string $selected Selected value.
355 * @param array $args Extra args.
356 *
357 * @return void
358 */
359 function wpbc_availability_general__render_select( $name, $options, $selected, $args = array() ) {
360
361 $args = wp_parse_args(
362 $args,
363 array(
364 'id' => $name,
365 'class' => 'wpbc_ag_field_control',
366 'disabled' => false,
367 )
368 );
369 ?>
370 <select id="<?php echo esc_attr( $args['id'] ); ?>" name="<?php echo esc_attr( $name ); ?>" class="<?php echo esc_attr( $args['class'] ); ?>" <?php disabled( $args['disabled'] ); ?>>
371 <?php foreach ( $options as $value => $label ) : ?>
372 <option value="<?php echo esc_attr( $value ); ?>" <?php selected( (string) $selected, (string) $value ); ?>><?php echo esc_html( $label ); ?></option>
373 <?php endforeach; ?>
374 </select>
375 <?php
376 }
377
378 /**
379 * Get default General Availability settings.
380 *
381 * @return array
382 */
383 function wpbc_availability_general__get_default_settings() {
384
385 return array(
386 'weekdays' => array(),
387 'booking_unavailable_days_num_from_today' => '0',
388 'booking_available_days_num_from_today' => '',
389 'booking_unavailable_extra_in_out' => '',
390 'booking_unavailable_extra_minutes_in' => '',
391 'booking_unavailable_extra_minutes_out' => '',
392 'booking_unavailable_extra_days_in' => '',
393 'booking_unavailable_extra_days_out' => '',
394 );
395 }
396
397 /**
398 * Validate posted settings.
399 *
400 * @param array $post_data Raw post data.
401 *
402 * @return array
403 */
404 function wpbc_availability_general__validate_data( $post_data ) {
405
406 $cleaned = wpbc_availability_general__get_default_settings();
407
408 if ( isset( $post_data['booking_unavailable_days'] ) && is_array( $post_data['booking_unavailable_days'] ) ) {
409 foreach ( $post_data['booking_unavailable_days'] as $day_num ) {
410 $day_num = absint( $day_num );
411 if ( $day_num >= 0 && $day_num <= 6 ) {
412 $cleaned['weekdays'][] = $day_num;
413 }
414 }
415 }
416
417 if ( isset( $post_data['booking_unavailable_days_num_from_today'] ) ) {
418 $value = sanitize_text_field( wp_unslash( $post_data['booking_unavailable_days_num_from_today'] ) );
419 if ( preg_match( '/^\d+m$/', $value ) || preg_match( '/^\d+$/', $value ) ) {
420 $cleaned['booking_unavailable_days_num_from_today'] = $value;
421 }
422 }
423
424 if ( isset( $post_data['booking_available_days_num_from_today'] ) ) {
425 $value = sanitize_text_field( wp_unslash( $post_data['booking_available_days_num_from_today'] ) );
426 $cleaned['booking_available_days_num_from_today'] = ( '' === $value ) ? '' : (string) absint( $value );
427 }
428
429 if ( isset( $post_data['booking_unavailable_extra_in_out'] ) ) {
430 $value = sanitize_text_field( wp_unslash( $post_data['booking_unavailable_extra_in_out'] ) );
431 $cleaned['booking_unavailable_extra_in_out'] = in_array( $value, array( '', 'm', 'd' ), true ) ? $value : '';
432 }
433
434 foreach ( array( 'booking_unavailable_extra_minutes_in', 'booking_unavailable_extra_minutes_out' ) as $key ) {
435 if ( isset( $post_data[ $key ] ) ) {
436 $value = sanitize_text_field( wp_unslash( $post_data[ $key ] ) );
437 $cleaned[ $key ] = preg_match( '/^\d+m$/', $value ) ? $value : '';
438 }
439 }
440
441 foreach ( array( 'booking_unavailable_extra_days_in', 'booking_unavailable_extra_days_out' ) as $key ) {
442 if ( isset( $post_data[ $key ] ) ) {
443 $value = sanitize_text_field( wp_unslash( $post_data[ $key ] ) );
444 $cleaned[ $key ] = preg_match( '/^\d+d$/', $value ) ? $value : '';
445 }
446 }
447
448 return $cleaned;
449 }
450
451 /**
452 * Update settings.
453 *
454 * @param array $cleaned_data Cleaned settings.
455 *
456 * @return void
457 */
458 function wpbc_availability_general__update_settings( $cleaned_data ) {
459
460 for ( $i = 0; $i < 7; $i++ ) {
461 update_bk_option( 'booking_unavailable_day' . $i, in_array( $i, $cleaned_data['weekdays'], true ) ? 'On' : 'Off' );
462 }
463
464 update_bk_option( 'booking_unavailable_days_num_from_today', $cleaned_data['booking_unavailable_days_num_from_today'] );
465
466 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
467 update_bk_option( 'booking_available_days_num_from_today', $cleaned_data['booking_available_days_num_from_today'] );
468 update_bk_option( 'booking_unavailable_extra_in_out', $cleaned_data['booking_unavailable_extra_in_out'] );
469 update_bk_option( 'booking_unavailable_extra_minutes_in', $cleaned_data['booking_unavailable_extra_minutes_in'] );
470 update_bk_option( 'booking_unavailable_extra_minutes_out', $cleaned_data['booking_unavailable_extra_minutes_out'] );
471 update_bk_option( 'booking_unavailable_extra_days_in', $cleaned_data['booking_unavailable_extra_days_in'] );
472 update_bk_option( 'booking_unavailable_extra_days_out', $cleaned_data['booking_unavailable_extra_days_out'] );
473 }
474 }
475
476 /**
477 * Get current settings prepared for JavaScript and AJAX responses.
478 *
479 * @return array
480 */
481 function wpbc_availability_general__get_settings_response() {
482
483 $hints = function_exists( 'wpbc_get_unavailable_from_today_hints_arr' ) ? wpbc_get_unavailable_from_today_hints_arr() : array();
484 $weekdays = array();
485
486 for ( $i = 0; $i < 7; $i++ ) {
487 if ( 'On' === get_bk_option( 'booking_unavailable_day' . $i ) ) {
488 $weekdays[] = $i;
489 }
490 }
491
492 return array(
493 'weekdays' => $weekdays,
494 'booking_unavailable_days_num_from_today' => get_bk_option( 'booking_unavailable_days_num_from_today' ),
495 'booking_available_days_num_from_today' => get_bk_option( 'booking_available_days_num_from_today' ),
496 'booking_unavailable_extra_in_out' => get_bk_option( 'booking_unavailable_extra_in_out' ),
497 'booking_unavailable_extra_minutes_in' => get_bk_option( 'booking_unavailable_extra_minutes_in' ),
498 'booking_unavailable_extra_minutes_out' => get_bk_option( 'booking_unavailable_extra_minutes_out' ),
499 'booking_unavailable_extra_days_in' => get_bk_option( 'booking_unavailable_extra_days_in' ),
500 'booking_unavailable_extra_days_out' => get_bk_option( 'booking_unavailable_extra_days_out' ),
501 'hints' => array(
502 'booking_unavailable_days_num_from_today__hint' => isset( $hints['booking_unavailable_days_num_from_today__hint'] ) ? $hints['booking_unavailable_days_num_from_today__hint'] : '',
503 'booking_available_days_num_from_today__hint' => isset( $hints['booking_available_days_num_from_today__hint'] ) ? $hints['booking_available_days_num_from_today__hint'] : '',
504 ),
505 );
506 }
507
508 /**
509 * Render booking resource calendar preview.
510 *
511 * @param int $resource_id Resource ID.
512 * @param int $months_count Number of months.
513 *
514 * @return void
515 */
516 function wpbc_availability_general__render_calendar_preview( $resource_id, $months_count ) {
517
518 $resource_id = wpbc_availability_general__sanitize_preview_resource_id( $resource_id );
519 $months_count = wpbc_availability_general__sanitize_preview_months_count( $months_count );
520 $months_in_row = min( 3, max( 1, $months_count ) );
521 $calendar_css_class_outer = 'wpbc_calendar_wraper';
522
523 if ( 'Off' !== get_bk_option( 'booking_change_over_days_triangles' ) ) {
524 $calendar_css_class_outer .= ' wpbc_change_over_triangle';
525 }
526 ?>
527 <div class="wpbc_ag_calendar_panel" data-wpbc-ag-calendar-panel="1" data-resource-id="<?php echo esc_attr( $resource_id ); ?>" data-months-count="<?php echo esc_attr( $months_count ); ?>">
528 <div class="<?php echo esc_attr( $calendar_css_class_outer ); ?>">
529 <div class="bk_calendar_frame months_num_in_row_<?php echo esc_attr( $months_in_row ); ?> cal_month_num_<?php echo esc_attr( $months_count ); ?>">
530 <div id="calendar_booking<?php echo esc_attr( $resource_id ); ?>"><?php esc_html_e( 'Calendar is loading...', 'booking' ); ?></div>
531 </div>
532 </div>
533 <textarea rows="3" cols="50" id="date_booking<?php echo esc_attr( $resource_id ); ?>" name="date_booking<?php echo esc_attr( $resource_id ); ?>" autocomplete="off" hidden></textarea>
534 <?php
535 if ( function_exists( 'wpbc__calendar__load' ) ) {
536 $start_script_code = wpbc__calendar__load(
537 array(
538 'resource_id' => $resource_id,
539 'aggregate_resource_id_arr' => array(),
540 'selected_dates_without_calendar' => '',
541 'calendar_number_of_months' => $months_count,
542 'start_month_calendar' => false,
543 'shortcode_options' => '',
544 'custom_form' => 'standard',
545 'skip_general_availability' => 1,
546 )
547 );
548 echo $start_script_code; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
549 }
550 ?>
551 </div>
552 <?php
553 }
554
555 /**
556 * Render select field with previous / next stepper buttons.
557 *
558 * @param string $name Field name.
559 * @param array $options Options.
560 * @param string $selected Selected value.
561 * @param array $args Extra args.
562 *
563 * @return void
564 */
565 function wpbc_availability_general__render_select_with_stepper( $name, $options, $selected, $args = array() ) {
566
567 $args = wp_parse_args(
568 $args,
569 array(
570 'id' => $name,
571 'disabled' => false,
572 )
573 );
574 ?>
575 <div class="wpbc_ag_stepper_control" data-wpbc-ag-stepper-wrap="<?php echo esc_attr( $name ); ?>">
576 <button type="button" class="button button-secondary wpbc_button_no_background wpbc_ag_stepper_button" data-wpbc-ag-stepper="<?php echo esc_attr( $name ); ?>" data-step="-1" aria-label="<?php esc_attr_e( 'Decrease value', 'booking' ); ?>" <?php disabled( $args['disabled'] ); ?>>
577 <i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_left"></i>
578 </button>
579 <?php
580 wpbc_availability_general__render_select(
581 $name,
582 $options,
583 $selected,
584 array(
585 'id' => $args['id'],
586 'disabled' => $args['disabled'],
587 )
588 );
589 ?>
590 <button type="button" class="button button-secondary wpbc_button_no_background wpbc_ag_stepper_button" data-wpbc-ag-stepper="<?php echo esc_attr( $name ); ?>" data-step="1" aria-label="<?php esc_attr_e( 'Increase value', 'booking' ); ?>" <?php disabled( $args['disabled'] ); ?>>
591 <i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_right"></i>
592 </button>
593 </div>
594 <?php
595 }
596
597 /**
598 * Render select field with an attached range slider.
599 *
600 * @param string $name Field name.
601 * @param array $options Options.
602 * @param string $selected Selected value.
603 * @param array $args Extra args.
604 *
605 * @return void
606 */
607 function wpbc_availability_general__render_select_with_slider( $name, $options, $selected, $args = array() ) {
608
609 $args = wp_parse_args(
610 $args,
611 array(
612 'disabled' => false,
613 'slider_label' => __( 'Adjust value', 'booking' ),
614 )
615 );
616
617 $option_values = array_keys( $options );
618 $selected_index = 0;
619
620 foreach ( $option_values as $option_index => $option_value ) {
621 if ( (string) $selected === (string) $option_value ) {
622 $selected_index = (int) $option_index;
623 break;
624 }
625 }
626
627 wpbc_availability_general__render_select( $name, $options, $selected, $args );
628 ?>
629 <div class="wpbc_ag_range_control" data-wpbc-ag-range-wrap="<?php echo esc_attr( $name ); ?>">
630 <input type="range" min="0" max="<?php echo esc_attr( max( 0, count( $options ) - 1 ) ); ?>" step="1" value="<?php echo esc_attr( $selected_index ); ?>" data-wpbc-ag-range-for="<?php echo esc_attr( $name ); ?>" aria-label="<?php echo esc_attr( $args['slider_label'] ); ?>" <?php disabled( $args['disabled'] ); ?> />
631 <span class="wpbc_ag_range_value" data-wpbc-ag-range-value-for="<?php echo esc_attr( $name ); ?>"><?php echo esc_html( isset( $options[ $option_values[ $selected_index ] ] ) ? $options[ $option_values[ $selected_index ] ] : '' ); ?></span>
632 </div>
633 <?php
634 }
635
636 /**
637 * Show General Availability save button in top toolbar.
638 *
639 * @param string $page_tag Current page tag.
640 * @param string $active_page_tab Current tab.
641 * @param string $active_page_subtab Current subtab.
642 *
643 * @return void
644 */
645 function wpbc_availability_general__top_toolbar__show_save_button( $page_tag, $active_page_tab, $active_page_subtab ) {
646
647 if ( ( 'wpbc-availability' !== $page_tag ) || ( 'general_availability' !== $active_page_tab ) ) {
648 return;
649 }
650
651 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
652 return;
653 }
654 ?>
655 <div class="wpbc_ui_el__buttons_group wpbc_ag__top_toolbar_group">
656 <a href="javascript:void(0);"
657 class="button button-secondary wpbc_ag__top_btn_reset"
658 data-wpbc-ag-reset="1">
659 <i class="menu_icon icon-1x wpbc_icn_rotate_left"></i>
660 <span class="in-button-text">&nbsp;&nbsp;<?php esc_html_e( 'Reset', 'booking' ); ?></span>
661 </a>
662 <a href="javascript:void(0);"
663 class="button button-primary wpbc_ag__top_btn_save"
664 data-wpbc-ag-save="1"
665 data-wpbc-u-busy-text="<?php esc_attr_e( 'Saving', 'booking' ); ?>...">
666 <i class="menu_icon icon-1x wpbc-bi-check2-circle"></i>
667 <span class="in-button-text">&nbsp;&nbsp;<?php esc_html_e( 'Save Changes', 'booking' ); ?></span>
668 </a>
669 </div>
670 <?php
671 }
672 add_action( 'wpbc_ui_el__top_nav__content_end', 'wpbc_availability_general__top_toolbar__show_save_button', 20, 3 );
673
674 /**
675 * Block direct access for regular users in MultiUser context.
676 *
677 * @param bool $is_show_this_page Whether to show page.
678 * @param string $page_tag Current page.
679 * @param string $active_page_tab Active tab.
680 * @param string $active_page_subtab Active subtab.
681 *
682 * @return bool
683 */
684 function wpbc_availability_general__check_showing_page( $is_show_this_page, $page_tag, $active_page_tab, $active_page_subtab ) {
685
686 if ( ( 'wpbc-availability' === $page_tag ) && ( 'general_availability' === $active_page_tab ) && ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) ) {
687 return false;
688 }
689
690 return $is_show_this_page;
691 }
692 add_filter( 'wpbc_before_showing_settings_page_is_show_page', 'wpbc_availability_general__check_showing_page', 20, 4 );
693
694 /**
695 * General Availability tab.
696 */
697 class WPBC_Page_Availability_General_Dedicated extends WPBC_Page_Structure {
698
699 /**
700 * Whether settings were saved during this request.
701 *
702 * @var bool
703 */
704 private $is_updated = false;
705
706 /**
707 * Menu slug.
708 *
709 * @return string
710 */
711 public function in_page() {
712
713 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
714 return (string) wp_rand( 100000, 1000000 );
715 }
716
717 return 'wpbc-availability';
718 }
719
720 /**
721 * Register tab.
722 *
723 * @return array
724 */
725 public function tabs() {
726
727 $tabs = array();
728
729 $tabs['general_availability'] = array(
730 'is_show_top_path' => false,
731 'right_vertical_sidebar__is_show' => true,
732 'right_vertical_sidebar__default_view_mode' => '',
733 'right_vertical_sidebar_compact__is_show' => true,
734 'left_navigation__default_view_mode' => 'compact',
735 'title' => __( 'General Availability', 'booking' ) .
736 '<span class="wpbc_new_label" style="margin-left: auto;">' . esc_html__( 'New', 'booking' ) . '</span>',
737 'hint' => __( 'Define global front-end availability rules for all calendars, including unavailable weekdays, booking buffers, and availability limits.', 'booking' ),
738 'page_title' => __( 'General Availability', 'booking' ),
739 'link' => '',
740 'position' => '',
741 'css_classes' => 'wpbc_top_tab__general_availability',
742 'icon' => '',
743 'font_icon' => 'wpbc-bi-calendar2-day',
744 'font_icon_right' => '',
745 'default' => false,
746 'disabled' => false,
747 'hided' => false,
748 'subtabs' => array(),
749 'folder_style' => 'order:93;',
750 );
751
752 return $tabs;
753 }
754
755 /**
756 * Save settings.
757 *
758 * @return void
759 */
760 public function maybe_update() {
761
762 $form_name = 'wpbc_availability_general_form';
763
764 // phpcs:ignore WordPress.Security.NonceVerification.Missing
765 if ( ! isset( $_POST[ 'is_form_submitted_' . $form_name ] ) ) {
766 return;
767 }
768
769 check_admin_referer( 'wpbc_settings_page_' . $form_name );
770
771 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
772 return;
773 }
774
775 $cleaned_data = wpbc_availability_general__validate_data( $_POST ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
776 wpbc_availability_general__update_settings( $cleaned_data );
777
778 $this->is_updated = true;
779 }
780
781 /**
782 * Right compact sidebar tabs.
783 *
784 * @return void
785 */
786 public function right_sidebar_compact_content() {
787
788 WPBC_UI_Sidebar_Panels::render_rightbar_tabs(
789 array(
790 array(
791 'id' => 'wpbc_tab_ag_settings',
792 'panel_id' => 'wpbc_ag__inspector_settings',
793 'title' => __( 'Settings', 'booking' ),
794 'icon' => 'wpbc_icn_tune',
795 'selected' => true,
796 ),
797 array(
798 'id' => 'wpbc_tab_ag_notes',
799 'panel_id' => 'wpbc_ag__inspector_notes',
800 'title' => __( 'Notes', 'booking' ),
801 'icon' => 'wpbc-bi-info-circle',
802 ),
803 ),
804 array(
805 'aria_label' => __( 'General Availability Panels', 'booking' ),
806 'context' => 'general_availability',
807 'class' => 'wpbc_ag_rightbar_tabs',
808 )
809 );
810 }
811
812 /**
813 * Right sidebar panels.
814 *
815 * @return void
816 */
817 public function right_sidebar_content() {
818 ?>
819 <div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_ag_rightbar_panels">
820 <?php
821 WPBC_UI_Sidebar_Panels::render_panel(
822 array(
823 'id' => 'wpbc_ag__inspector_settings',
824 'labelledby' => 'wpbc_tab_ag_settings',
825 'class' => 'wpbc_ag__inspector_settings',
826 ),
827 array( $this, 'right_panel_settings_content' )
828 );
829
830 WPBC_UI_Sidebar_Panels::render_panel(
831 array(
832 'id' => 'wpbc_ag__inspector_notes',
833 'labelledby' => 'wpbc_tab_ag_notes',
834 'class' => 'wpbc_ag__inspector_notes',
835 'hidden' => true,
836 ),
837 array( $this, 'right_panel_notes_content' )
838 );
839 ?>
840 </div>
841 <?php
842 }
843
844 /**
845 * Settings panel content.
846 *
847 * @return void
848 */
849 public function right_panel_settings_content() {
850
851 $form_name = 'wpbc_availability_general_form';
852 $hints = function_exists( 'wpbc_get_unavailable_from_today_hints_arr' ) ? wpbc_get_unavailable_from_today_hints_arr() : array();
853 $buffer_type = (string) get_bk_option( 'booking_unavailable_extra_in_out' );
854 $is_buffer_available = class_exists( 'wpdev_bk_biz_m' );
855 $is_available_limit_available = class_exists( 'wpdev_bk_biz_m' );
856 $unavailable_weekdays = array();
857
858 for ( $i = 0; $i < 7; $i++ ) {
859 if ( 'On' === get_bk_option( 'booking_unavailable_day' . $i ) ) {
860 $unavailable_weekdays[] = $i;
861 }
862 }
863
864 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'General Availability', 'booking' ), __( 'Global front-end availability rules for all calendars.', 'booking' ) );
865 ?>
866 <form method="post" id="<?php echo esc_attr( $form_name ); ?>" class="wpbc_ag_settings_form" data-wpbc-ag-settings-form="1">
867 <?php wp_nonce_field( 'wpbc_settings_page_' . $form_name ); ?>
868 <input type="hidden" name="is_form_submitted_<?php echo esc_attr( $form_name ); ?>" value="1" />
869 <div class="wpbc_bfb__inspector__body wpbc_ag_inspector_body">
870 <?php
871 WPBC_UI_Sidebar_Panels::render_collapsible_group(
872 array(
873 'id' => 'wpbc_ag_weekdays_group',
874 'group' => 'general-availability-weekdays',
875 'title' => __( 'Unavailable Weekdays', 'booking' ),
876 'open' => true,
877 ),
878 function () use ( $unavailable_weekdays ) {
879 $days = array(
880 0 => __( 'Sunday', 'booking' ),
881 1 => __( 'Monday', 'booking' ),
882 2 => __( 'Tuesday', 'booking' ),
883 3 => __( 'Wednesday', 'booking' ),
884 4 => __( 'Thursday', 'booking' ),
885 5 => __( 'Friday', 'booking' ),
886 6 => __( 'Saturday', 'booking' ),
887 );
888 $start_week_day = absint( get_bk_option( 'booking_start_day_weeek' ) );
889 if ( $start_week_day > 6 ) {
890 $start_week_day = 0;
891 }
892 $days_ordered = array_slice( $days, $start_week_day, null, true ) + array_slice( $days, 0, $start_week_day, true );
893 ?>
894 <div class="wpbc_ag_weekday_grid">
895 <?php foreach ( $days_ordered as $day_num => $day_title ) : ?>
896 <label class="wpbc_ag_switch">
897 <input type="checkbox" name="booking_unavailable_days[]" value="<?php echo esc_attr( $day_num ); ?>" <?php checked( in_array( $day_num, $unavailable_weekdays, true ) ); ?> />
898 <span class="wpbc_ag_switch_control" aria-hidden="true"><span class="wpbc_ag_switch_knob"></span></span>
899 <span class="wpbc_ag_switch_label"><?php echo esc_html( $day_title ); ?></span>
900 </label>
901 <?php endforeach; ?>
902 </div>
903 <p class="wpbc_ag_description"><?php esc_html_e( 'Selected weekdays will be unavailable in calendars and override other availability settings.', 'booking' ); ?></p>
904 <?php
905 }
906 );
907
908 WPBC_UI_Sidebar_Panels::render_collapsible_group(
909 array(
910 'id' => 'wpbc_ag_today_group',
911 'group' => 'general-availability-from-today',
912 'title' => __( 'Availability From Today', 'booking' ),
913 'open' => true,
914 ),
915 function () use ( $hints, $is_available_limit_available ) {
916 ?>
917 <div class="wpbc_ag_field_row">
918 <label class="wpbc_ag_field_label" for="booking_unavailable_days_num_from_today"><?php esc_html_e( 'Unavailable time from current time', 'booking' ); ?></label>
919 <?php
920 wpbc_availability_general__render_select_with_slider(
921 'booking_unavailable_days_num_from_today',
922 wpbc_availability_general__get_unavailable_from_today_options(),
923 get_bk_option( 'booking_unavailable_days_num_from_today' ),
924 array( 'slider_label' => __( 'Adjust unavailable time from current time', 'booking' ) )
925 );
926 ?>
927 <code class="wpbc_ag_hint" data-wpbc-ag-hint="booking_unavailable_days_num_from_today"><span class="wpbc_ag_hint_unavailable"><?php esc_html_e( 'Unavailable', 'booking' ); ?></span><?php echo wp_kses_post( isset( $hints['booking_unavailable_days_num_from_today__hint'] ) ? $hints['booking_unavailable_days_num_from_today__hint'] : '' ); ?></code>
928 </div>
929 <div class="wpbc_ag_field_row">
930 <label class="wpbc_ag_field_label" for="booking_available_days_num_from_today"><?php esc_html_e( 'Limit available days from today', 'booking' ); ?></label>
931 <?php if ( ! $is_available_limit_available ) : ?>
932 <div class="wpbc_ag_upgrade_required">
933 <a class="wpbc_pro_label" href="<?php echo esc_url( 'https://wpbookingcalendar.com/features/' ); ?>" target="_blank">Pro | BM+</a>
934 <span><?php esc_html_e( 'Limit available days from today is available only in Booking Calendar Business Medium or higher versions.', 'booking' ); ?></span>
935 </div>
936 <?php endif; ?>
937 <div class="<?php echo $is_available_limit_available ? '' : 'wpbc_ag_is_locked'; ?>">
938 <?php
939 wpbc_availability_general__render_select_with_slider(
940 'booking_available_days_num_from_today',
941 wpbc_availability_general__get_available_from_today_options(),
942 get_bk_option( 'booking_available_days_num_from_today' ),
943 array(
944 'slider_label' => __( 'Adjust available days limit', 'booking' ),
945 'disabled' => ! $is_available_limit_available,
946 )
947 );
948 ?>
949 </div>
950 <code class="wpbc_ag_hint" data-wpbc-ag-hint="booking_available_days_num_from_today"><span class="wpbc_ag_hint_available"><?php esc_html_e( 'Available', 'booking' ); ?></span><?php echo wp_kses_post( isset( $hints['booking_available_days_num_from_today__hint'] ) ? $hints['booking_available_days_num_from_today__hint'] : '' ); ?></code>
951 </div>
952 <?php
953 }
954 );
955
956 WPBC_UI_Sidebar_Panels::render_collapsible_group(
957 array(
958 'id' => 'wpbc_ag_buffer_group',
959 'group' => 'general-availability-buffer',
960 'title' => __( 'Booking Buffer', 'booking' ),
961 'open' => true,
962 ),
963 function () use ( $buffer_type, $is_buffer_available ) {
964 ?>
965 <?php if ( ! $is_buffer_available ) : ?>
966 <div class="wpbc_ag_upgrade_required">
967 <a class="wpbc_pro_label" href="<?php echo esc_url( 'https://wpbookingcalendar.com/features/' ); ?>" target="_blank">Pro | BM+</a>
968 <span><?php esc_html_e( 'Booking buffer is available only in Booking Calendar Business Medium or higher versions.', 'booking' ); ?></span>
969 </div>
970 <?php endif; ?>
971 <div class="wpbc_ag_radio_stack <?php echo $is_buffer_available ? '' : 'wpbc_ag_is_locked'; ?>">
972 <label><input type="radio" name="booking_unavailable_extra_in_out" value="" <?php checked( $buffer_type, '' ); ?> <?php disabled( ! $is_buffer_available ); ?> /> <?php echo esc_html( ucfirst( __( 'None', 'booking' ) ) ); ?></label>
973 <label><input type="radio" name="booking_unavailable_extra_in_out" value="m" <?php checked( $buffer_type, 'm' ); ?> <?php disabled( ! $is_buffer_available ); ?> /> <?php echo esc_html( ucfirst( __( 'minutes', 'booking' ) ) . ' / ' . ucfirst( __( 'hours', 'booking' ) ) ); ?></label>
974 <label><input type="radio" name="booking_unavailable_extra_in_out" value="d" <?php checked( $buffer_type, 'd' ); ?> <?php disabled( ! $is_buffer_available ); ?> /> <?php echo esc_html( ucfirst( __( 'day(s)', 'booking' ) ) ); ?></label>
975 </div>
976 <div class="wpbc_ag_buffer_fields" data-buffer-panel="m">
977 <div class="wpbc_ag_field_row">
978 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_minutes_in"><?php esc_html_e( 'Before booking', 'booking' ); ?></label>
979 <?php wpbc_availability_general__render_select_with_stepper( 'booking_unavailable_extra_minutes_in', wpbc_availability_general__get_buffer_minutes_options(), get_bk_option( 'booking_unavailable_extra_minutes_in' ), array( 'disabled' => ! $is_buffer_available ) ); ?>
980 </div>
981 <div class="wpbc_ag_field_row">
982 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_minutes_out"><?php esc_html_e( 'After booking', 'booking' ); ?></label>
983 <?php wpbc_availability_general__render_select_with_stepper( 'booking_unavailable_extra_minutes_out', wpbc_availability_general__get_buffer_minutes_options(), get_bk_option( 'booking_unavailable_extra_minutes_out' ), array( 'disabled' => ! $is_buffer_available ) ); ?>
984 </div>
985 </div>
986 <div class="wpbc_ag_buffer_fields" data-buffer-panel="d">
987 <div class="wpbc_ag_field_row">
988 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_days_in"><?php esc_html_e( 'Before booking', 'booking' ); ?></label>
989 <?php wpbc_availability_general__render_select_with_stepper( 'booking_unavailable_extra_days_in', wpbc_availability_general__get_buffer_days_options(), get_bk_option( 'booking_unavailable_extra_days_in' ), array( 'disabled' => ! $is_buffer_available ) ); ?>
990 </div>
991 <div class="wpbc_ag_field_row">
992 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_days_out"><?php esc_html_e( 'After booking', 'booking' ); ?></label>
993 <?php wpbc_availability_general__render_select_with_stepper( 'booking_unavailable_extra_days_out', wpbc_availability_general__get_buffer_days_options(), get_bk_option( 'booking_unavailable_extra_days_out' ), array( 'disabled' => ! $is_buffer_available ) ); ?>
994 </div>
995 </div>
996 <?php
997 }
998 );
999 /* //TODO: implement it later.
1000 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1001 array(
1002 'id' => 'wpbc_ag_working_time_group',
1003 'group' => 'general-availability-working-time',
1004 'title' => __( 'Working Time', 'booking' ),
1005 ),
1006 function () {
1007 ?>
1008 <div class="wpbc_ag_future_notice"><?php esc_html_e( 'Prepared for the future rule: time outside the working interval will become unavailable for booking resources.', 'booking' ); ?></div>
1009 <label class="wpbc_ag_toggle wpbc_ag_toggle_full">
1010 <input type="checkbox" disabled="disabled" />
1011 <span><?php esc_html_e( 'Enable working time rule', 'booking' ); ?></span>
1012 </label>
1013 <div class="wpbc_ag_field_row">
1014 <label class="wpbc_ag_field_label" for="wpbc_ag_working_time_start"><?php esc_html_e( 'Start time', 'booking' ); ?></label>
1015 <?php wpbc_availability_general__render_select( 'wpbc_ag_working_time_start', wpbc_availability_general__get_working_time_options(), '09:00', array( 'disabled' => true ) ); ?>
1016 </div>
1017 <div class="wpbc_ag_field_row">
1018 <label class="wpbc_ag_field_label" for="wpbc_ag_working_time_end"><?php esc_html_e( 'End time', 'booking' ); ?></label>
1019 <?php wpbc_availability_general__render_select( 'wpbc_ag_working_time_end', wpbc_availability_general__get_working_time_options(), '18:00', array( 'disabled' => true ) ); ?>
1020 </div>
1021 <?php
1022 }
1023 );
1024 */
1025 ?>
1026 </div>
1027 </form>
1028 <?php
1029 }
1030
1031 /**
1032 * Notes panel content.
1033 *
1034 * @return void
1035 */
1036 public function right_panel_notes_content() {
1037
1038 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Notes', 'booking' ), __( 'How these rules are applied.', 'booking' ) );
1039 ?>
1040 <div class="wpbc_bfb__inspector__body wpbc_ag_inspector_body" style="padding:10px;">
1041 <div class="wpbc_ag_notice">
1042 <strong><?php esc_html_e( 'Note', 'booking' ); ?>!</strong>
1043 <?php esc_html_e( 'These options do not apply in the admin panel. These options apply only on the front-end side.', 'booking' ); ?>
1044 </div>
1045 <div class="wpbc_ag_scope_card">
1046 <div class="wpbc_ag_scope_title"><?php esc_html_e( 'Scope', 'booking' ); ?></div>
1047 <p><?php esc_html_e( 'The calendar on this page previews one selected booking resource. The settings in the palette are general availability settings and affect front-end calendars globally.', 'booking' ); ?></p>
1048 </div>
1049 </div>
1050 <?php
1051 }
1052
1053 /**
1054 * Show page content.
1055 *
1056 * @return void|false
1057 */
1058 public function content() {
1059
1060 do_action( 'wpbc_hook_settings_page_header', 'page_booking_availability_general' );
1061
1062 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
1063 return false;
1064 }
1065
1066 if ( function_exists( 'wpbc_js_for_bookings_page' ) ) {
1067 wpbc_js_for_bookings_page();
1068 }
1069
1070 $resource_id = wpbc_availability_general__get_preview_resource_id();
1071 $months_count = wpbc_availability_general__get_preview_months_count();
1072 $resources = wpbc_availability_general__get_resources();
1073 ?>
1074 <div class="wpbc_ag_page wpdevelop" data-wpbc-ag-page="1" data-wpbc-ag-resource-id="<?php echo esc_attr( $resource_id ); ?>">
1075 <form method="get" class="wpbc_ag_toolbar wpbc_ts_toolbar wpbc_ag_preview_controls" data-wpbc-ag-preview-toolbar="1">
1076 <input type="hidden" name="page" value="wpbc-availability" />
1077 <input type="hidden" name="tab" value="general_availability" />
1078 <div class="wpbc_ts_control wpbc_ag_control_resource">
1079 <label for="wpbc_ag_resource_id"><?php esc_html_e( 'Booking resource', 'booking' ); ?></label>
1080 <select id="wpbc_ag_resource_id" name="resource_id">
1081 <?php foreach ( $resources as $resource ) : ?>
1082 <option value="<?php echo esc_attr( $resource['id'] ); ?>" <?php selected( $resource_id, (int) $resource['id'] ); ?>><?php echo esc_html( $resource['title'] ); ?></option>
1083 <?php endforeach; ?>
1084 </select>
1085 </div>
1086 <div class="wpbc_ts_control wpbc_ag_control_months">
1087 <label for="wpbc_ag_months_count"><?php esc_html_e( 'Months', 'booking' ); ?></label>
1088 <select id="wpbc_ag_months_count" name="months_count">
1089 <?php foreach ( array( 1, 2, 3, 4, 6, 12 ) as $month_option ) : ?>
1090 <option value="<?php echo esc_attr( $month_option ); ?>" <?php selected( $months_count, $month_option ); ?>><?php echo esc_html( $month_option ); ?></option>
1091 <?php endforeach; ?>
1092 </select>
1093 </div>
1094 </form>
1095 <?php wpbc_availability_general__render_calendar_preview( $resource_id, $months_count ); ?>
1096 <div class="wpbc_ag_calendar_notes" data-wpbc-ag-calendar-notes="1">
1097 <div class="wpbc_ts_hint wpbc_ag_hint_bar">
1098 <span class="wpbc_icn_info_outline"></span>
1099 <?php esc_html_e( 'Preview how the current general availability rules affect a front-end calendar.', 'booking' ); ?>
1100 </div>
1101 </div>
1102 </div>
1103 <?php
1104
1105 do_action( 'wpbc_hook_settings_page_footer', 'page_booking_availability_general' );
1106 }
1107
1108 }
1109 add_action( 'wpbc_menu_created', array( new WPBC_Page_Availability_General_Dedicated(), '__construct' ) );
1110