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

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

1,321 lines 52.2 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 'settings' => wpbc_availability_general__get_settings_response(),
93 'default_settings' => wpbc_availability_general__get_default_settings(),
94 'open_section' => wpbc_availability_general__get_open_section(),
95 'is_buffer_available' => class_exists( 'wpdev_bk_biz_m' ),
96 'is_available_limit_available' => class_exists( 'wpdev_bk_biz_m' ),
97 'i18n' => array(
98 'saving' => __( 'Saving', 'booking' ),
99 'saved' => __( 'General availability settings updated.', 'booking' ),
100 'reset_applied' => __( 'Default availability settings are ready for preview. Click Save Changes to apply them.', 'booking' ),
101 'save_failed' => __( 'Unable to save general availability settings.', 'booking' ),
102 'reset_confirm' => __( 'Reset controls to default values? Saved settings will not change until you click Save Changes.', 'booking' ),
103 'preview_failed' => __( 'Unable to refresh calendar preview.', 'booking' ),
104 'security_error' => __( 'Security check failed.', 'booking' ),
105 'loading' => __( 'Loading', 'booking' ),
106 'buffer_preview' => __( 'Buffer preview', 'booking' ),
107 'before_booking' => __( 'Before booking', 'booking' ),
108 'after_booking' => __( 'After booking', 'booking' ),
109 'no_buffer' => __( 'No booking buffer is selected.', 'booking' ),
110 ),
111 )
112 );
113 }
114 add_action( 'wpbc_enqueue_js_files', 'wpbc_availability_general_enqueue_js_files', 66 );
115
116 /**
117 * Print tooltip initializer for General Availability.
118 *
119 * @return void
120 */
121 function wpbc_availability_general_print_tooltip_js() {
122
123 if ( ! wpbc_availability_general__is_page() ) {
124 return;
125 }
126
127 if ( function_exists( 'wpbc_bs_javascript_tooltips' ) ) {
128 wpbc_bs_javascript_tooltips();
129 }
130 }
131 add_action( 'admin_footer', 'wpbc_availability_general_print_tooltip_js', 67 );
132
133 /**
134 * Get resource options.
135 *
136 * @return array
137 */
138 function wpbc_availability_general__get_resources() {
139
140 $resources = array();
141
142 if ( function_exists( 'wpbc_ajx_get_sorted_booking_resources_arr' ) && function_exists( 'wpbc_ajx_get_all_booking_resources_arr' ) ) {
143 $resource_rows = wpbc_ajx_get_sorted_booking_resources_arr( wpbc_ajx_get_all_booking_resources_arr() );
144 foreach ( $resource_rows as $resource ) {
145 $resources[] = array(
146 'id' => isset( $resource['booking_type_id'] ) ? (int) $resource['booking_type_id'] : 1,
147 'title' => isset( $resource['title'] ) ? $resource['title'] : __( 'Booking resource', 'booking' ),
148 );
149 }
150 }
151
152 if ( empty( $resources ) ) {
153 $resources[] = array(
154 'id' => function_exists( 'wpbc_get_default_resource' ) ? (int) wpbc_get_default_resource() : 1,
155 'title' => __( 'Booking resource', 'booking' ),
156 );
157 }
158
159 return $resources;
160 }
161
162 /**
163 * Get capability required to manage General Availability.
164 *
165 * @return string
166 */
167 function wpbc_availability_general__get_manage_cap() {
168
169 $min_user_role = get_bk_option( 'booking_user_role_settings' );
170 $capability = array(
171 'administrator' => 'activate_plugins',
172 'editor' => 'publish_pages',
173 'author' => 'publish_posts',
174 'contributor' => 'edit_posts',
175 'subscriber' => 'read',
176 );
177
178 return isset( $capability[ $min_user_role ] ) ? $capability[ $min_user_role ] : 'manage_options';
179 }
180
181 /**
182 * Get selected resource ID for preview.
183 *
184 * @return int
185 */
186 function wpbc_availability_general__get_preview_resource_id() {
187
188 $resources = wpbc_availability_general__get_resources();
189 $default_resource = isset( $resources[0]['id'] ) ? (int) $resources[0]['id'] : 1;
190
191 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
192 $resource_id = isset( $_REQUEST['resource_id'] ) ? absint( wp_unslash( $_REQUEST['resource_id'] ) ) : $default_resource;
193 $resource_ids = wp_list_pluck( $resources, 'id' );
194
195 return in_array( $resource_id, $resource_ids, true ) ? $resource_id : $default_resource;
196 }
197
198 /**
199 * Get selected month count for preview.
200 *
201 * @return int
202 */
203 function wpbc_availability_general__get_preview_months_count() {
204
205 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
206 $months = isset( $_REQUEST['months_count'] ) ? absint( wp_unslash( $_REQUEST['months_count'] ) ) : 6;
207
208 return in_array( $months, array( 1, 2, 3, 4, 6, 12 ), true ) ? $months : 6;
209 }
210
211 /**
212 * Get the General Availability section that should be opened on page load.
213 *
214 * @return string
215 */
216 function wpbc_availability_general__get_open_section() {
217
218 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
219 $open_section = isset( $_REQUEST['wpbc_ag_open'] ) ? sanitize_key( wp_unslash( $_REQUEST['wpbc_ag_open'] ) ) : '';
220
221 return in_array( $open_section, array( 'weekdays', 'from_today', 'buffer', 'working_time' ), true ) ? $open_section : '';
222 }
223
224 /**
225 * Validate preview resource ID.
226 *
227 * @param int $resource_id Resource ID.
228 *
229 * @return int
230 */
231 function wpbc_availability_general__sanitize_preview_resource_id( $resource_id ) {
232
233 $resources = wpbc_availability_general__get_resources();
234 $default_resource = isset( $resources[0]['id'] ) ? (int) $resources[0]['id'] : 1;
235 $resource_ids = wp_list_pluck( $resources, 'id' );
236
237 return in_array( (int) $resource_id, $resource_ids, true ) ? (int) $resource_id : $default_resource;
238 }
239
240 /**
241 * Validate preview months count.
242 *
243 * @param int $months_count Number of months.
244 *
245 * @return int
246 */
247 function wpbc_availability_general__sanitize_preview_months_count( $months_count ) {
248
249 $months_count = absint( $months_count );
250
251 return in_array( $months_count, array( 1, 2, 3, 4, 6, 12 ), true ) ? $months_count : 6;
252 }
253
254 /**
255 * Get unavailable-from-today select options.
256 *
257 * @return array
258 */
259 function wpbc_availability_general__get_unavailable_from_today_options() {
260
261 $options = array( '0' => ' - ' );
262
263 foreach ( range( 5, 55, 5 ) as $extra_num ) {
264 $options[ $extra_num . 'm' ] = $extra_num . ' ' . __( 'minutes', 'booking' );
265 }
266 $options['60m'] = '1 ' . __( 'hour', 'booking' );
267 foreach ( range( 65, 115, 5 ) as $extra_num ) {
268 $options[ $extra_num . 'm' ] = '1 ' . __( 'hour', 'booking' ) . ' ' . ( $extra_num - 60 ) . ' ' . __( 'minutes', 'booking' );
269 }
270 foreach ( range( 120, 1380, 60 ) as $extra_num ) {
271 $options[ $extra_num . 'm' ] = ( $extra_num / 60 ) . ' ' . __( 'hours', 'booking' );
272 }
273
274 $options['1'] = '1 ' . __( 'day', 'booking' );
275 for ( $ii = 2; $ii < 92; $ii++ ) {
276 $options[ (string) $ii ] = $ii . ' ' . __( 'days', 'booking' );
277 }
278
279 return $options;
280 }
281
282 /**
283 * Get available-from-today select options.
284 *
285 * @return array
286 */
287 function wpbc_availability_general__get_available_from_today_options() {
288
289 $options = array( '' => ' - ' );
290
291 foreach ( range( 1, 365 ) as $value ) {
292 $options[ (string) $value ] = (string) $value;
293 }
294
295 return $options;
296 }
297
298 /**
299 * Get minute buffer options.
300 *
301 * @return array
302 */
303 function wpbc_availability_general__get_buffer_minutes_options() {
304
305 $options = array( '' => ' - ' );
306
307 foreach ( range( 5, 55, 5 ) as $extra_num ) {
308 $options[ $extra_num . 'm' ] = $extra_num . ' ' . __( 'minutes', 'booking' );
309 }
310 $options['60m'] = '1 ' . __( 'hour', 'booking' );
311 foreach ( range( 65, 115, 5 ) as $extra_num ) {
312 $options[ $extra_num . 'm' ] = '1 ' . __( 'hour', 'booking' ) . ' ' . ( $extra_num - 60 ) . ' ' . __( 'minutes', 'booking' );
313 }
314 foreach ( range( 120, 1380, 60 ) as $extra_num ) {
315 $options[ $extra_num . 'm' ] = ( $extra_num / 60 ) . ' ' . __( 'hours', 'booking' );
316 }
317
318 return $options;
319 }
320
321 /**
322 * Get day buffer options.
323 *
324 * @return array
325 */
326 function wpbc_availability_general__get_buffer_days_options() {
327
328 $options = array( '' => ' - ' );
329
330 foreach ( range( 1, 30 ) as $extra_num ) {
331 $options[ $extra_num . 'd' ] = $extra_num . ' ' . __( 'day(s)', 'booking' );
332 }
333
334 return $options;
335 }
336
337 /**
338 * Get time options for future working-time controls.
339 *
340 * @param string $selected Selected value.
341 *
342 * @return array
343 */
344 function wpbc_availability_general__get_working_time_options( $selected = '' ) {
345
346 $options = array();
347
348 for ( $minutes = 0; $minutes <= 1440; $minutes += 30 ) {
349 $hours = (int) floor( $minutes / 60 );
350 $mins = $minutes % 60;
351 $value = sprintf( '%02d:%02d', $hours, $mins );
352 $label = ( 1440 === $minutes ) ? '24:00' : $value;
353
354 $options[ $value ] = $label;
355 }
356
357 if ( '' !== $selected && ! isset( $options[ $selected ] ) ) {
358 $options[ $selected ] = $selected;
359 }
360
361 return $options;
362 }
363
364 /**
365 * Render a select field.
366 *
367 * @param string $name Field name.
368 * @param array $options Options.
369 * @param string $selected Selected value.
370 * @param array $args Extra args.
371 *
372 * @return void
373 */
374 function wpbc_availability_general__render_select( $name, $options, $selected, $args = array() ) {
375
376 $args = wp_parse_args(
377 $args,
378 array(
379 'id' => $name,
380 'class' => 'wpbc_ag_field_control',
381 'disabled' => false,
382 )
383 );
384 ?>
385 <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'] ); ?>>
386 <?php foreach ( $options as $value => $label ) : ?>
387 <option value="<?php echo esc_attr( $value ); ?>" <?php selected( (string) $selected, (string) $value ); ?>><?php echo esc_html( $label ); ?></option>
388 <?php endforeach; ?>
389 </select>
390 <?php
391 }
392
393 /**
394 * Render Working Time weekday rows.
395 *
396 * @param string $prefix Field prefix.
397 * @param array $weekdays Weekday intervals.
398 *
399 * @return void
400 */
401 function wpbc_availability_general__render_working_time_weekdays( $prefix, $weekdays ) {
402
403 $days = array(
404 0 => _x( 'Sun', 'Short weekday name', 'booking' ),
405 1 => _x( 'Mon', 'Short weekday name', 'booking' ),
406 2 => _x( 'Tue', 'Short weekday name', 'booking' ),
407 3 => _x( 'Wed', 'Short weekday name', 'booking' ),
408 4 => _x( 'Thu', 'Short weekday name', 'booking' ),
409 5 => _x( 'Fri', 'Short weekday name', 'booking' ),
410 6 => _x( 'Sat', 'Short weekday name', 'booking' ),
411 );
412
413 $start_week_day = absint( get_bk_option( 'booking_start_day_weeek' ) );
414 if ( $start_week_day > 6 ) {
415 $start_week_day = 0;
416 }
417 $days_ordered = array_slice( $days, $start_week_day, null, true ) + array_slice( $days, 0, $start_week_day, true );
418 $time_options = wpbc_availability_general__get_working_time_options();
419 ?>
420 <div class="wpbc_ag_working_time_rows" data-wpbc-working-time-weekdays="<?php echo esc_attr( $prefix ); ?>">
421 <?php foreach ( $days_ordered as $day_num => $day_title ) : ?>
422 <?php
423 $interval = ! empty( $weekdays[ $day_num ][0] ) ? $weekdays[ $day_num ][0] : array( 'start_second' => 9 * HOUR_IN_SECONDS, 'end_second' => 18 * HOUR_IN_SECONDS );
424 $is_open = ! empty( $weekdays[ $day_num ] );
425 ?>
426 <div class="wpbc_ag_working_time_row">
427 <label class="wpbc_ag_switch wpbc_ag_working_time_day">
428 <input type="checkbox" name="<?php echo esc_attr( $prefix ); ?>_days[]" value="<?php echo esc_attr( $day_num ); ?>" <?php checked( $is_open ); ?> />
429 <span class="wpbc_ag_switch_control" aria-hidden="true"><span class="wpbc_ag_switch_knob"></span></span>
430 <span class="wpbc_ag_switch_label"><?php echo esc_html( $day_title ); ?></span>
431 </label>
432 <div class="wpbc_ag_working_time_times">
433 <?php
434 wpbc_availability_general__render_select(
435 $prefix . '_start[' . $day_num . ']',
436 $time_options,
437 wpbc_working_time__seconds_to_time( $interval['start_second'] ),
438 array(
439 'id' => $prefix . '_start_' . $day_num,
440 'class' => 'wpbc_ag_field_control wpbc_ag_working_time_start',
441 )
442 );
443 wpbc_availability_general__render_select(
444 $prefix . '_end[' . $day_num . ']',
445 $time_options,
446 wpbc_working_time__seconds_to_time( $interval['end_second'] ),
447 array(
448 'id' => $prefix . '_end_' . $day_num,
449 'class' => 'wpbc_ag_field_control wpbc_ag_working_time_end',
450 )
451 );
452 ?>
453 </div>
454 </div>
455 <?php endforeach; ?>
456 </div>
457 <?php
458 }
459
460 /**
461 * Get default General Availability settings.
462 *
463 * @return array
464 */
465 function wpbc_availability_general__get_default_settings() {
466
467 return array(
468 'weekdays' => array(),
469 'booking_unavailable_days_num_from_today' => '0',
470 'booking_available_days_num_from_today' => '',
471 'booking_unavailable_extra_in_out' => '',
472 'booking_unavailable_extra_minutes_in' => '',
473 'booking_unavailable_extra_minutes_out' => '',
474 'booking_unavailable_extra_days_in' => '',
475 'booking_unavailable_extra_days_out' => '',
476 'working_time' => wpbc_working_time__get_default_settings(),
477 );
478 }
479
480 /**
481 * Validate posted one-interval-per-weekday Working Time schedule.
482 *
483 * @param array $post_data Raw post data.
484 * @param string $prefix Field prefix.
485 *
486 * @return array
487 */
488 function wpbc_availability_general__validate_working_time_weekdays( $post_data, $prefix ) {
489
490 $weekdays = array();
491 $enabled_days = array();
492 $start_values = isset( $post_data[ $prefix . '_start' ] ) && is_array( $post_data[ $prefix . '_start' ] ) ? wp_unslash( $post_data[ $prefix . '_start' ] ) : array();
493 $end_values = isset( $post_data[ $prefix . '_end' ] ) && is_array( $post_data[ $prefix . '_end' ] ) ? wp_unslash( $post_data[ $prefix . '_end' ] ) : array();
494
495 if ( isset( $post_data[ $prefix . '_days' ] ) && is_array( $post_data[ $prefix . '_days' ] ) ) {
496 foreach ( $post_data[ $prefix . '_days' ] as $day_num ) {
497 $day_num = absint( $day_num );
498 if ( $day_num >= 0 && $day_num <= 6 ) {
499 $enabled_days[] = $day_num;
500 }
501 }
502 }
503
504 for ( $day = 0; $day <= 6; $day++ ) {
505 $weekdays[ $day ] = array();
506 if ( ! in_array( $day, $enabled_days, true ) ) {
507 continue;
508 }
509
510 $start = isset( $start_values[ $day ] ) ? wpbc_working_time__time_to_seconds( sanitize_text_field( $start_values[ $day ] ) ) : 0;
511 $end = isset( $end_values[ $day ] ) ? wpbc_working_time__time_to_seconds( sanitize_text_field( $end_values[ $day ] ) ) : 0;
512
513 if ( $start < $end ) {
514 $weekdays[ $day ][] = array(
515 'start_second' => $start,
516 'end_second' => $end,
517 );
518 }
519 }
520
521 return $weekdays;
522 }
523
524 /**
525 * Validate posted Working Time settings.
526 *
527 * @param array $post_data Raw post data.
528 *
529 * @return array
530 */
531 function wpbc_availability_general__validate_working_time_data( $post_data ) {
532
533 $current_settings = wpbc_working_time__get_settings();
534 $resource_id = isset( $post_data['booking_working_time_resource_id'] ) ? absint( wp_unslash( $post_data['booking_working_time_resource_id'] ) ) : 0;
535 $resource_mode = isset( $post_data['booking_working_time_resource_mode'] ) ? sanitize_key( wp_unslash( $post_data['booking_working_time_resource_mode'] ) ) : 'inherit';
536
537 if ( ! in_array( $resource_mode, array( 'inherit', 'custom', 'disabled' ), true ) ) {
538 $resource_mode = 'inherit';
539 }
540
541 $current_settings['enabled'] = ( isset( $post_data['booking_working_time_enabled'] ) && 'On' === sanitize_text_field( wp_unslash( $post_data['booking_working_time_enabled'] ) ) ) ? 'On' : 'Off';
542 $current_settings['default'] = array(
543 'weekdays' => wpbc_availability_general__validate_working_time_weekdays( $post_data, 'booking_working_time_default' ),
544 );
545
546 if ( $resource_id > 0 ) {
547 $current_settings['resources'][ $resource_id ] = array(
548 'mode' => $resource_mode,
549 'weekdays' => wpbc_availability_general__validate_working_time_weekdays( $post_data, 'booking_working_time_resource' ),
550 );
551 }
552
553 return wpbc_working_time__normalize_settings( $current_settings );
554 }
555
556 /**
557 * Validate posted settings.
558 *
559 * @param array $post_data Raw post data.
560 *
561 * @return array
562 */
563 function wpbc_availability_general__validate_data( $post_data ) {
564
565 $cleaned = wpbc_availability_general__get_default_settings();
566
567 if ( isset( $post_data['booking_unavailable_days'] ) && is_array( $post_data['booking_unavailable_days'] ) ) {
568 foreach ( $post_data['booking_unavailable_days'] as $day_num ) {
569 $day_num = absint( $day_num );
570 if ( $day_num >= 0 && $day_num <= 6 ) {
571 $cleaned['weekdays'][] = $day_num;
572 }
573 }
574 }
575
576 if ( isset( $post_data['booking_unavailable_days_num_from_today'] ) ) {
577 $value = sanitize_text_field( wp_unslash( $post_data['booking_unavailable_days_num_from_today'] ) );
578 if ( preg_match( '/^\d+m$/', $value ) || preg_match( '/^\d+$/', $value ) ) {
579 $cleaned['booking_unavailable_days_num_from_today'] = $value;
580 }
581 }
582
583 if ( isset( $post_data['booking_available_days_num_from_today'] ) ) {
584 $value = sanitize_text_field( wp_unslash( $post_data['booking_available_days_num_from_today'] ) );
585 $cleaned['booking_available_days_num_from_today'] = ( '' === $value ) ? '' : (string) absint( $value );
586 }
587
588 if ( isset( $post_data['booking_unavailable_extra_in_out'] ) ) {
589 $value = sanitize_text_field( wp_unslash( $post_data['booking_unavailable_extra_in_out'] ) );
590 $cleaned['booking_unavailable_extra_in_out'] = in_array( $value, array( '', 'm', 'd' ), true ) ? $value : '';
591 }
592
593 foreach ( array( 'booking_unavailable_extra_minutes_in', 'booking_unavailable_extra_minutes_out' ) as $key ) {
594 if ( isset( $post_data[ $key ] ) ) {
595 $value = sanitize_text_field( wp_unslash( $post_data[ $key ] ) );
596 $cleaned[ $key ] = preg_match( '/^\d+m$/', $value ) ? $value : '';
597 }
598 }
599
600 foreach ( array( 'booking_unavailable_extra_days_in', 'booking_unavailable_extra_days_out' ) as $key ) {
601 if ( isset( $post_data[ $key ] ) ) {
602 $value = sanitize_text_field( wp_unslash( $post_data[ $key ] ) );
603 $cleaned[ $key ] = preg_match( '/^\d+d$/', $value ) ? $value : '';
604 }
605 }
606
607 $cleaned['working_time'] = wpbc_availability_general__validate_working_time_data( $post_data );
608
609 return $cleaned;
610 }
611
612 /**
613 * Update settings.
614 *
615 * @param array $cleaned_data Cleaned settings.
616 *
617 * @return void
618 */
619 function wpbc_availability_general__update_settings( $cleaned_data ) {
620
621 for ( $i = 0; $i < 7; $i++ ) {
622 update_bk_option( 'booking_unavailable_day' . $i, in_array( $i, $cleaned_data['weekdays'], true ) ? 'On' : 'Off' );
623 }
624
625 update_bk_option( 'booking_unavailable_days_num_from_today', $cleaned_data['booking_unavailable_days_num_from_today'] );
626
627 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
628 update_bk_option( 'booking_available_days_num_from_today', $cleaned_data['booking_available_days_num_from_today'] );
629 update_bk_option( 'booking_unavailable_extra_in_out', $cleaned_data['booking_unavailable_extra_in_out'] );
630 update_bk_option( 'booking_unavailable_extra_minutes_in', $cleaned_data['booking_unavailable_extra_minutes_in'] );
631 update_bk_option( 'booking_unavailable_extra_minutes_out', $cleaned_data['booking_unavailable_extra_minutes_out'] );
632 update_bk_option( 'booking_unavailable_extra_days_in', $cleaned_data['booking_unavailable_extra_days_in'] );
633 update_bk_option( 'booking_unavailable_extra_days_out', $cleaned_data['booking_unavailable_extra_days_out'] );
634 }
635
636 wpbc_working_time__update_settings( $cleaned_data['working_time'] );
637 }
638
639 /**
640 * Get current settings prepared for JavaScript and AJAX responses.
641 *
642 * @return array
643 */
644 function wpbc_availability_general__get_settings_response() {
645
646 $hints = function_exists( 'wpbc_get_unavailable_from_today_hints_arr' ) ? wpbc_get_unavailable_from_today_hints_arr() : array();
647 $weekdays = array();
648
649 for ( $i = 0; $i < 7; $i++ ) {
650 if ( 'On' === get_bk_option( 'booking_unavailable_day' . $i ) ) {
651 $weekdays[] = $i;
652 }
653 }
654
655 return array(
656 'weekdays' => $weekdays,
657 'booking_unavailable_days_num_from_today' => get_bk_option( 'booking_unavailable_days_num_from_today' ),
658 'booking_available_days_num_from_today' => get_bk_option( 'booking_available_days_num_from_today' ),
659 'booking_unavailable_extra_in_out' => get_bk_option( 'booking_unavailable_extra_in_out' ),
660 'booking_unavailable_extra_minutes_in' => get_bk_option( 'booking_unavailable_extra_minutes_in' ),
661 'booking_unavailable_extra_minutes_out' => get_bk_option( 'booking_unavailable_extra_minutes_out' ),
662 'booking_unavailable_extra_days_in' => get_bk_option( 'booking_unavailable_extra_days_in' ),
663 'booking_unavailable_extra_days_out' => get_bk_option( 'booking_unavailable_extra_days_out' ),
664 'working_time' => wpbc_working_time__get_settings(),
665 'hints' => array(
666 'booking_unavailable_days_num_from_today__hint' => isset( $hints['booking_unavailable_days_num_from_today__hint'] ) ? $hints['booking_unavailable_days_num_from_today__hint'] : '',
667 'booking_available_days_num_from_today__hint' => isset( $hints['booking_available_days_num_from_today__hint'] ) ? $hints['booking_available_days_num_from_today__hint'] : '',
668 ),
669 );
670 }
671
672 /**
673 * Render booking resource calendar preview.
674 *
675 * @param int $resource_id Resource ID.
676 * @param int $months_count Number of months.
677 *
678 * @return void
679 */
680 function wpbc_availability_general__render_calendar_preview( $resource_id, $months_count ) {
681
682 $resource_id = wpbc_availability_general__sanitize_preview_resource_id( $resource_id );
683 $months_count = wpbc_availability_general__sanitize_preview_months_count( $months_count );
684 $months_in_row = min( 3, max( 1, $months_count ) );
685 $calendar_css_class_outer = 'wpbc_calendar_wraper';
686
687 if ( 'Off' !== get_bk_option( 'booking_change_over_days_triangles' ) ) {
688 $calendar_css_class_outer .= ' wpbc_change_over_triangle';
689 }
690 ?>
691 <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 ); ?>">
692 <div class="<?php echo esc_attr( $calendar_css_class_outer ); ?>">
693 <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 ); ?>">
694 <div id="calendar_booking<?php echo esc_attr( $resource_id ); ?>"><?php esc_html_e( 'Calendar is loading...', 'booking' ); ?></div>
695 </div>
696 </div>
697 <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>
698 <?php
699 if ( function_exists( 'wpbc__calendar__load' ) ) {
700 $start_script_code = wpbc__calendar__load(
701 array(
702 'resource_id' => $resource_id,
703 'aggregate_resource_id_arr' => array(),
704 'selected_dates_without_calendar' => '',
705 'calendar_number_of_months' => $months_count,
706 'start_month_calendar' => false,
707 'shortcode_options' => '',
708 'custom_form' => 'standard',
709 'skip_general_availability' => 1,
710 )
711 );
712 echo $start_script_code; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
713 }
714 ?>
715 </div>
716 <?php
717 }
718
719 /**
720 * Render select field with previous / next stepper buttons.
721 *
722 * @param string $name Field name.
723 * @param array $options Options.
724 * @param string $selected Selected value.
725 * @param array $args Extra args.
726 *
727 * @return void
728 */
729 function wpbc_availability_general__render_select_with_stepper( $name, $options, $selected, $args = array() ) {
730
731 $args = wp_parse_args(
732 $args,
733 array(
734 'id' => $name,
735 'disabled' => false,
736 )
737 );
738 ?>
739 <div class="wpbc_ag_stepper_control" data-wpbc-ag-stepper-wrap="<?php echo esc_attr( $name ); ?>">
740 <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'] ); ?>>
741 <i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_left"></i>
742 </button>
743 <?php
744 wpbc_availability_general__render_select(
745 $name,
746 $options,
747 $selected,
748 array(
749 'id' => $args['id'],
750 'disabled' => $args['disabled'],
751 )
752 );
753 ?>
754 <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'] ); ?>>
755 <i class="menu_icon icon-1x wpbc_icn_keyboard_arrow_right"></i>
756 </button>
757 </div>
758 <?php
759 }
760
761 /**
762 * Render select field with an attached range slider.
763 *
764 * @param string $name Field name.
765 * @param array $options Options.
766 * @param string $selected Selected value.
767 * @param array $args Extra args.
768 *
769 * @return void
770 */
771 function wpbc_availability_general__render_select_with_slider( $name, $options, $selected, $args = array() ) {
772
773 $args = wp_parse_args(
774 $args,
775 array(
776 'disabled' => false,
777 'slider_label' => __( 'Adjust value', 'booking' ),
778 )
779 );
780
781 $option_values = array_keys( $options );
782 $selected_index = 0;
783
784 foreach ( $option_values as $option_index => $option_value ) {
785 if ( (string) $selected === (string) $option_value ) {
786 $selected_index = (int) $option_index;
787 break;
788 }
789 }
790
791 wpbc_availability_general__render_select( $name, $options, $selected, $args );
792 ?>
793 <div class="wpbc_ag_range_control" data-wpbc-ag-range-wrap="<?php echo esc_attr( $name ); ?>">
794 <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'] ); ?> />
795 <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>
796 </div>
797 <?php
798 }
799
800 /**
801 * Show General Availability save button in top toolbar.
802 *
803 * @param string $page_tag Current page tag.
804 * @param string $active_page_tab Current tab.
805 * @param string $active_page_subtab Current subtab.
806 *
807 * @return void
808 */
809 function wpbc_availability_general__top_toolbar__show_save_button( $page_tag, $active_page_tab, $active_page_subtab ) {
810
811 if ( ( 'wpbc-availability' !== $page_tag ) || ( 'general_availability' !== $active_page_tab ) ) {
812 return;
813 }
814
815 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
816 return;
817 }
818 ?>
819 <div class="wpbc_ui_el__buttons_group wpbc_ag__top_toolbar_group">
820 <a href="javascript:void(0);"
821 class="button button-secondary wpbc_ag__top_btn_reset"
822 data-wpbc-ag-reset="1">
823 <i class="menu_icon icon-1x wpbc_icn_rotate_left"></i>
824 <span class="in-button-text">&nbsp;&nbsp;<?php esc_html_e( 'Reset', 'booking' ); ?></span>
825 </a>
826 <a href="javascript:void(0);"
827 class="button button-primary wpbc_ag__top_btn_save"
828 data-wpbc-ag-save="1"
829 data-wpbc-u-busy-text="<?php esc_attr_e( 'Saving', 'booking' ); ?>...">
830 <i class="menu_icon icon-1x wpbc-bi-check2-circle"></i>
831 <span class="in-button-text">&nbsp;&nbsp;<?php esc_html_e( 'Save Changes', 'booking' ); ?></span>
832 </a>
833 </div>
834 <?php
835 }
836 add_action( 'wpbc_ui_el__top_nav__content_end', 'wpbc_availability_general__top_toolbar__show_save_button', 20, 3 );
837
838 /**
839 * Block direct access for regular users in MultiUser context.
840 *
841 * @param bool $is_show_this_page Whether to show page.
842 * @param string $page_tag Current page.
843 * @param string $active_page_tab Active tab.
844 * @param string $active_page_subtab Active subtab.
845 *
846 * @return bool
847 */
848 function wpbc_availability_general__check_showing_page( $is_show_this_page, $page_tag, $active_page_tab, $active_page_subtab ) {
849
850 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() ) ) ) {
851 return false;
852 }
853
854 return $is_show_this_page;
855 }
856 add_filter( 'wpbc_before_showing_settings_page_is_show_page', 'wpbc_availability_general__check_showing_page', 20, 4 );
857
858 /**
859 * General Availability tab.
860 */
861 class WPBC_Page_Availability_General_Dedicated extends WPBC_Page_Structure {
862
863 /**
864 * Whether settings were saved during this request.
865 *
866 * @var bool
867 */
868 private $is_updated = false;
869
870 /**
871 * Menu slug.
872 *
873 * @return string
874 */
875 public function in_page() {
876
877 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
878 return (string) wp_rand( 100000, 1000000 );
879 }
880
881 return 'wpbc-availability';
882 }
883
884 /**
885 * Register tab.
886 *
887 * @return array
888 */
889 public function tabs() {
890
891 $tabs = array();
892
893 $tabs['general_availability'] = array(
894 'is_show_top_path' => true,
895 'right_vertical_sidebar__is_show' => true,
896 'right_vertical_sidebar__default_view_mode' => '',
897 'right_vertical_sidebar_compact__is_show' => true,
898 'left_navigation__default_view_mode' => '', // FixIn:11.7.1.1: 'compact',
899 'top_path_title' => __( 'Schedule & Rules', 'booking' ),
900 'title' => __( 'Schedule & Rules', 'booking' ),
901 'hint' => __( 'Define global front-end availability rules for all calendars, including unavailable weekdays, booking buffers, and availability limits.', 'booking' ),
902 'page_title' => __( 'Schedule & Rules', 'booking' ),
903 'link' => '',
904 'position' => '',
905 'css_classes' => 'wpbc_top_tab__general_availability',
906 'icon' => '',
907 'font_icon' => 'wpbc-bi-calendar2-day',
908 'font_icon_right' => '',
909 'default' => false,
910 'disabled' => false,
911 'hided' => false,
912 'subtabs' => array(),
913 'folder_style' => 'order:93;',
914 'is_show_top_navigation' => true,
915 );
916
917 return $tabs;
918 }
919
920 /**
921 * Save settings.
922 *
923 * @return void
924 */
925 public function maybe_update() {
926
927 $form_name = 'wpbc_availability_general_form';
928
929 // phpcs:ignore WordPress.Security.NonceVerification.Missing
930 if ( ! isset( $_POST[ 'is_form_submitted_' . $form_name ] ) ) {
931 return;
932 }
933
934 check_admin_referer( 'wpbc_settings_page_' . $form_name );
935
936 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
937 return;
938 }
939
940 $cleaned_data = wpbc_availability_general__validate_data( $_POST ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
941 wpbc_availability_general__update_settings( $cleaned_data );
942
943 $this->is_updated = true;
944 }
945
946 /**
947 * Right compact sidebar tabs.
948 *
949 * @return void
950 */
951 public function right_sidebar_compact_content() {
952
953 WPBC_UI_Sidebar_Panels::render_rightbar_tabs(
954 array(
955 array(
956 'id' => 'wpbc_tab_ag_settings',
957 'panel_id' => 'wpbc_ag__inspector_settings',
958 'title' => __( 'Settings', 'booking' ),
959 'icon' => 'wpbc_icn_tune',
960 'selected' => true,
961 ),
962 array(
963 'id' => 'wpbc_tab_ag_notes',
964 'panel_id' => 'wpbc_ag__inspector_notes',
965 'title' => __( 'Notes', 'booking' ),
966 'icon' => 'wpbc-bi-info-circle',
967 ),
968 ),
969 array(
970 'aria_label' => __( 'Schedule & Rules Panels', 'booking' ),
971 'context' => 'general_availability',
972 'class' => 'wpbc_ag_rightbar_tabs',
973 )
974 );
975 }
976
977 /**
978 * Right sidebar panels.
979 *
980 * @return void
981 */
982 public function right_sidebar_content() {
983 ?>
984 <div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_ag_rightbar_panels">
985 <?php
986 WPBC_UI_Sidebar_Panels::render_panel(
987 array(
988 'id' => 'wpbc_ag__inspector_settings',
989 'labelledby' => 'wpbc_tab_ag_settings',
990 'class' => 'wpbc_ag__inspector_settings',
991 ),
992 array( $this, 'right_panel_settings_content' )
993 );
994
995 WPBC_UI_Sidebar_Panels::render_panel(
996 array(
997 'id' => 'wpbc_ag__inspector_notes',
998 'labelledby' => 'wpbc_tab_ag_notes',
999 'class' => 'wpbc_ag__inspector_notes',
1000 'hidden' => true,
1001 ),
1002 array( $this, 'right_panel_notes_content' )
1003 );
1004 ?>
1005 </div>
1006 <?php
1007 }
1008
1009 /**
1010 * Settings panel content.
1011 *
1012 * @return void
1013 */
1014 public function right_panel_settings_content() {
1015
1016 $form_name = 'wpbc_availability_general_form';
1017 $hints = function_exists( 'wpbc_get_unavailable_from_today_hints_arr' ) ? wpbc_get_unavailable_from_today_hints_arr() : array();
1018 $buffer_type = (string) get_bk_option( 'booking_unavailable_extra_in_out' );
1019 $is_buffer_available = class_exists( 'wpdev_bk_biz_m' );
1020 $is_available_limit_available = class_exists( 'wpdev_bk_biz_m' );
1021 $unavailable_weekdays = array();
1022 $working_time_settings = wpbc_working_time__get_settings();
1023 $working_time_default_settings = wpbc_working_time__get_default_settings();
1024 $working_time_resource_id = wpbc_availability_general__get_preview_resource_id();
1025 $open_section = wpbc_availability_general__get_open_section();
1026 $working_time_resource = isset( $working_time_settings['resources'][ $working_time_resource_id ] )
1027 ? $working_time_settings['resources'][ $working_time_resource_id ]
1028 : array(
1029 'mode' => 'inherit',
1030 'weekdays' => $working_time_default_settings['default']['weekdays'],
1031 );
1032
1033 for ( $i = 0; $i < 7; $i++ ) {
1034 if ( 'On' === get_bk_option( 'booking_unavailable_day' . $i ) ) {
1035 $unavailable_weekdays[] = $i;
1036 }
1037 }
1038
1039 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Schedule & Rules', 'booking' ), __( 'Availability rules for all calendars.', 'booking' ) );
1040 ?>
1041 <form method="post" id="<?php echo esc_attr( $form_name ); ?>" class="wpbc_ag_settings_form" data-wpbc-ag-settings-form="1">
1042 <?php wp_nonce_field( 'wpbc_settings_page_' . $form_name ); ?>
1043 <input type="hidden" name="is_form_submitted_<?php echo esc_attr( $form_name ); ?>" value="1" />
1044 <div class="wpbc_bfb__inspector__body wpbc_ag_inspector_body">
1045 <?php
1046 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1047 array(
1048 'id' => 'wpbc_ag_weekdays_group',
1049 'group' => 'general-availability-weekdays',
1050 'title' => __( 'Unavailable Weekdays', 'booking' ),
1051 'open' => ( 'working_time' !== $open_section ),
1052 ),
1053 function () use ( $unavailable_weekdays ) {
1054 $days_ordered = array(
1055 1 => array(
1056 'short' => _x( 'Mo', 'Short weekday label', 'booking' ),
1057 'full' => __( 'Monday', 'booking' ),
1058 ),
1059 2 => array(
1060 'short' => _x( 'Tu', 'Short weekday label', 'booking' ),
1061 'full' => __( 'Tuesday', 'booking' ),
1062 ),
1063 3 => array(
1064 'short' => _x( 'We', 'Short weekday label', 'booking' ),
1065 'full' => __( 'Wednesday', 'booking' ),
1066 ),
1067 4 => array(
1068 'short' => _x( 'Th', 'Short weekday label', 'booking' ),
1069 'full' => __( 'Thursday', 'booking' ),
1070 ),
1071 5 => array(
1072 'short' => _x( 'Fr', 'Short weekday label', 'booking' ),
1073 'full' => __( 'Friday', 'booking' ),
1074 ),
1075 6 => array(
1076 'short' => _x( 'Sa', 'Short weekday label', 'booking' ),
1077 'full' => __( 'Saturday', 'booking' ),
1078 ),
1079 0 => array(
1080 'short' => _x( 'Su', 'Short weekday label', 'booking' ),
1081 'full' => __( 'Sunday', 'booking' ),
1082 ),
1083 );
1084 ?>
1085 <div class="wpbc_ag_weekday_grid">
1086 <?php foreach ( $days_ordered as $day_num => $day_labels ) : ?>
1087 <?php
1088 $unavailable_day_aria_label = sprintf(
1089 /* translators: %s: Full weekday name. */
1090 __( 'Set %s as unavailable', 'booking' ),
1091 $day_labels['full']
1092 );
1093 ?>
1094 <label class="wpbc_ag_switch wpbc_ag_weekday_switch">
1095 <input type="checkbox" name="booking_unavailable_days[]" value="<?php echo esc_attr( $day_num ); ?>" aria-label="<?php echo esc_attr( $unavailable_day_aria_label ); ?>" <?php checked( in_array( $day_num, $unavailable_weekdays, true ) ); ?> />
1096 <span class="wpbc_ag_switch_control" aria-hidden="true"><span class="wpbc_ag_switch_knob"></span></span>
1097 <span class="wpbc_ag_switch_label"><?php echo esc_html( $day_labels['short'] ); ?></span>
1098 </label>
1099 <?php endforeach; ?>
1100 </div>
1101 <p class="wpbc_ag_description"><?php esc_html_e( 'Selected weekdays will be unavailable in calendars and override other availability settings.', 'booking' ); ?></p>
1102 <?php
1103 }
1104 );
1105
1106 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1107 array(
1108 'id' => 'wpbc_ag_working_time_group',
1109 'group' => 'general-availability-working-time',
1110 'title' => __( 'Working Time', 'booking' ),
1111 'open' => ( 'working_time' === $open_section ),
1112 ),
1113 function () use ( $working_time_settings, $working_time_resource_id, $working_time_resource ) {
1114 ?>
1115 <div class="wpbc_ag_notice wpbc_ag_working_time_notice"><?php esc_html_e( 'Working Time restricts only time-based bookings, such as rangetime, start/end time, or start/duration time fields.', 'booking' ); ?></div>
1116 <input type="hidden" name="booking_working_time_resource_id" data-wpbc-working-time-resource-id="1" value="<?php echo esc_attr( $working_time_resource_id ); ?>" />
1117 <label class="wpbc_ag_switch wpbc_ag_switch_card">
1118 <input type="checkbox" name="booking_working_time_enabled" value="On" <?php checked( $working_time_settings['enabled'], 'On' ); ?> />
1119 <span class="wpbc_ag_switch_control" aria-hidden="true"><span class="wpbc_ag_switch_knob"></span></span>
1120 <span class="wpbc_ag_switch_label"><?php esc_html_e( 'Restrict time-based bookings to working time', 'booking' ); ?></span>
1121 </label>
1122
1123 <div class="wpbc_ag_working_time_block">
1124 <div class="wpbc_ag_scope_title"><?php esc_html_e( 'Default working time', 'booking' ); ?></div>
1125 <p class="wpbc_ag_description"><?php esc_html_e( 'Used by all booking resources unless a resource override is configured below.', 'booking' ); ?></p>
1126 <?php wpbc_availability_general__render_working_time_weekdays( 'booking_working_time_default', $working_time_settings['default']['weekdays'] ); ?>
1127 </div>
1128
1129 <div class="wpbc_ag_working_time_block wpbc_ag_working_time_resource_block" data-wpbc-working-time-resource-block="1">
1130 <div class="wpbc_ag_scope_title"><?php esc_html_e( 'Selected resource override', 'booking' ); ?></div>
1131 <p class="wpbc_ag_description"><?php esc_html_e( 'This override follows the booking resource selected in the page toolbar.', 'booking' ); ?></p>
1132 <div class="wpbc_ag_radio_stack wpbc_ag_working_time_mode">
1133 <label><input type="radio" name="booking_working_time_resource_mode" value="inherit" <?php checked( $working_time_resource['mode'], 'inherit' ); ?> /> <?php esc_html_e( 'Inherit default working time', 'booking' ); ?></label>
1134 <label><input type="radio" name="booking_working_time_resource_mode" value="custom" <?php checked( $working_time_resource['mode'], 'custom' ); ?> /> <?php esc_html_e( 'Use custom working time', 'booking' ); ?></label>
1135 <label><input type="radio" name="booking_working_time_resource_mode" value="disabled" <?php checked( $working_time_resource['mode'], 'disabled' ); ?> /> <?php esc_html_e( 'Do not restrict this resource by working time', 'booking' ); ?></label>
1136 </div>
1137 <div class="wpbc_ag_working_time_custom" data-wpbc-working-time-resource-custom="1">
1138 <?php wpbc_availability_general__render_working_time_weekdays( 'booking_working_time_resource', $working_time_resource['weekdays'] ); ?>
1139 </div>
1140 </div>
1141 <?php
1142 }
1143 );
1144
1145 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1146 array(
1147 'id' => 'wpbc_ag_today_group',
1148 'group' => 'general-availability-from-today',
1149 'title' => __( 'Availability From Today', 'booking' ),
1150 'open' => false,
1151 ),
1152 function () use ( $hints, $is_available_limit_available ) {
1153 ?>
1154 <div class="wpbc_ag_field_row">
1155 <label class="wpbc_ag_field_label" for="booking_unavailable_days_num_from_today"><?php esc_html_e( 'Unavailable time from current time', 'booking' ); ?></label>
1156 <?php
1157 wpbc_availability_general__render_select_with_slider(
1158 'booking_unavailable_days_num_from_today',
1159 wpbc_availability_general__get_unavailable_from_today_options(),
1160 get_bk_option( 'booking_unavailable_days_num_from_today' ),
1161 array( 'slider_label' => __( 'Adjust unavailable time from current time', 'booking' ) )
1162 );
1163 ?>
1164 <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>
1165 </div>
1166 <div class="wpbc_ag_field_row">
1167 <label class="wpbc_ag_field_label" for="booking_available_days_num_from_today"><?php esc_html_e( 'Limit available days from today', 'booking' ); ?></label>
1168 <?php if ( ! $is_available_limit_available ) : ?>
1169 <div class="wpbc_ag_upgrade_required">
1170 <a class="wpbc_pro_label" href="<?php echo esc_url( 'https://wpbookingcalendar.com/features/' ); ?>" target="_blank">Pro | BM+</a>
1171 <span><?php esc_html_e( 'Limit available days from today is available only in Booking Calendar Business Medium or higher versions.', 'booking' ); ?></span>
1172 </div>
1173 <?php endif; ?>
1174 <div class="<?php echo $is_available_limit_available ? '' : 'wpbc_ag_is_locked'; ?>">
1175 <?php
1176 wpbc_availability_general__render_select_with_slider(
1177 'booking_available_days_num_from_today',
1178 wpbc_availability_general__get_available_from_today_options(),
1179 get_bk_option( 'booking_available_days_num_from_today' ),
1180 array(
1181 'slider_label' => __( 'Adjust available days limit', 'booking' ),
1182 'disabled' => ! $is_available_limit_available,
1183 )
1184 );
1185 ?>
1186 </div>
1187 <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>
1188 </div>
1189 <?php
1190 }
1191 );
1192
1193 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1194 array(
1195 'id' => 'wpbc_ag_buffer_group',
1196 'group' => 'general-availability-buffer',
1197 'title' => __( 'Booking Buffer', 'booking' ),
1198 'open' => false,
1199 ),
1200 function () use ( $buffer_type, $is_buffer_available ) {
1201 ?>
1202 <?php if ( ! $is_buffer_available ) : ?>
1203 <div class="wpbc_ag_upgrade_required">
1204 <a class="wpbc_pro_label" href="<?php echo esc_url( 'https://wpbookingcalendar.com/features/' ); ?>" target="_blank">Pro | BM+</a>
1205 <span><?php esc_html_e( 'Booking buffer is available only in Booking Calendar Business Medium or higher versions.', 'booking' ); ?></span>
1206 </div>
1207 <?php endif; ?>
1208 <div class="wpbc_ag_radio_stack <?php echo $is_buffer_available ? '' : 'wpbc_ag_is_locked'; ?>">
1209 <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>
1210 <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>
1211 <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>
1212 </div>
1213 <div class="wpbc_ag_buffer_fields" data-buffer-panel="m">
1214 <div class="wpbc_ag_field_row">
1215 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_minutes_in"><?php esc_html_e( 'Before booking', 'booking' ); ?></label>
1216 <?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 ) ); ?>
1217 </div>
1218 <div class="wpbc_ag_field_row">
1219 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_minutes_out"><?php esc_html_e( 'After booking', 'booking' ); ?></label>
1220 <?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 ) ); ?>
1221 </div>
1222 </div>
1223 <div class="wpbc_ag_buffer_fields" data-buffer-panel="d">
1224 <div class="wpbc_ag_field_row">
1225 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_days_in"><?php esc_html_e( 'Before booking', 'booking' ); ?></label>
1226 <?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 ) ); ?>
1227 </div>
1228 <div class="wpbc_ag_field_row">
1229 <label class="wpbc_ag_field_label" for="booking_unavailable_extra_days_out"><?php esc_html_e( 'After booking', 'booking' ); ?></label>
1230 <?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 ) ); ?>
1231 </div>
1232 </div>
1233 <?php
1234 }
1235 );
1236 ?>
1237 </div>
1238 </form>
1239 <?php
1240 }
1241
1242 /**
1243 * Notes panel content.
1244 *
1245 * @return void
1246 */
1247 public function right_panel_notes_content() {
1248
1249 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Notes', 'booking' ), __( 'How these rules are applied.', 'booking' ) );
1250 ?>
1251 <div class="wpbc_bfb__inspector__body wpbc_ag_inspector_body" style="padding:10px;">
1252 <div class="wpbc_ag_notice">
1253 <strong><?php esc_html_e( 'Note', 'booking' ); ?>!</strong>
1254 <?php esc_html_e( 'These options do not apply in the admin panel. These options apply only on the front-end side.', 'booking' ); ?>
1255 </div>
1256 <div class="wpbc_ag_scope_card">
1257 <div class="wpbc_ag_scope_title"><?php esc_html_e( 'Scope', 'booking' ); ?></div>
1258 <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>
1259 </div>
1260 </div>
1261 <?php
1262 }
1263
1264 /**
1265 * Show page content.
1266 *
1267 * @return void|false
1268 */
1269 public function content() {
1270
1271 do_action( 'wpbc_hook_settings_page_header', 'page_booking_availability_general' );
1272
1273 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_availability_general__get_manage_cap() ) ) {
1274 return false;
1275 }
1276
1277 if ( function_exists( 'wpbc_js_for_bookings_page' ) ) {
1278 wpbc_js_for_bookings_page();
1279 }
1280
1281 $resource_id = wpbc_availability_general__get_preview_resource_id();
1282 $months_count = wpbc_availability_general__get_preview_months_count();
1283 $resources = wpbc_availability_general__get_resources();
1284 ?>
1285 <div class="wpbc_ag_page wpdevelop" data-wpbc-ag-page="1" data-wpbc-ag-resource-id="<?php echo esc_attr( $resource_id ); ?>">
1286 <form method="get" class="wpbc_ag_toolbar wpbc_ts_toolbar wpbc_ag_preview_controls" data-wpbc-ag-preview-toolbar="1">
1287 <input type="hidden" name="page" value="wpbc-availability" />
1288 <input type="hidden" name="tab" value="general_availability" />
1289 <div class="wpbc_ts_control wpbc_ag_control_resource">
1290 <label for="wpbc_ag_resource_id"><?php esc_html_e( 'Booking resource', 'booking' ); ?></label>
1291 <select id="wpbc_ag_resource_id" name="resource_id">
1292 <?php foreach ( $resources as $resource ) : ?>
1293 <option value="<?php echo esc_attr( $resource['id'] ); ?>" <?php selected( $resource_id, (int) $resource['id'] ); ?>><?php echo esc_html( $resource['title'] ); ?></option>
1294 <?php endforeach; ?>
1295 </select>
1296 </div>
1297 <div class="wpbc_ts_control wpbc_ag_control_months">
1298 <label for="wpbc_ag_months_count"><?php esc_html_e( 'Months', 'booking' ); ?></label>
1299 <select id="wpbc_ag_months_count" name="months_count">
1300 <?php foreach ( array( 1, 2, 3, 4, 6, 12 ) as $month_option ) : ?>
1301 <option value="<?php echo esc_attr( $month_option ); ?>" <?php selected( $months_count, $month_option ); ?>><?php echo esc_html( $month_option ); ?></option>
1302 <?php endforeach; ?>
1303 </select>
1304 </div>
1305 </form>
1306 <?php wpbc_availability_general__render_calendar_preview( $resource_id, $months_count ); ?>
1307 <div class="wpbc_ag_calendar_notes" data-wpbc-ag-calendar-notes="1">
1308 <div class="wpbc_ts_hint wpbc_ag_hint_bar">
1309 <span class="wpbc_icn_info_outline"></span>
1310 <?php esc_html_e( 'Preview how the current general availability rules affect a front-end calendar.', 'booking' ); ?>
1311 </div>
1312 </div>
1313 </div>
1314 <?php
1315
1316 do_action( 'wpbc_hook_settings_page_footer', 'page_booking_availability_general' );
1317 }
1318
1319 }
1320 add_action( 'wpbc_menu_created', array( new WPBC_Page_Availability_General_Dedicated(), '__construct' ) );
1321