WPBC_JS_IN_FOOTER ) ); wp_localize_script( 'wpbc-availability-general-page', 'wpbc_availability_general_page', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'wpbc_availability_general_ajax_nonce' ), 'action' => 'WPBC_AJX_AVAILABILITY_GENERAL_SAVE', 'preview_action' => 'WPBC_AJX_AVAILABILITY_GENERAL_PREVIEW', 'default_settings' => wpbc_availability_general__get_default_settings(), 'is_buffer_available' => class_exists( 'wpdev_bk_biz_m' ), 'is_available_limit_available' => class_exists( 'wpdev_bk_biz_m' ), 'i18n' => array( 'saving' => __( 'Saving', 'booking' ), 'saved' => __( 'General availability settings updated.', 'booking' ), 'reset_applied' => __( 'Default availability settings are ready for preview. Click Save Changes to apply them.', 'booking' ), 'save_failed' => __( 'Unable to save general availability settings.', 'booking' ), 'reset_confirm' => __( 'Reset controls to default values? Saved settings will not change until you click Save Changes.', 'booking' ), 'preview_failed' => __( 'Unable to refresh calendar preview.', 'booking' ), 'security_error' => __( 'Security check failed.', 'booking' ), 'loading' => __( 'Loading', 'booking' ), 'buffer_preview' => __( 'Buffer preview', 'booking' ), 'before_booking' => __( 'Before booking', 'booking' ), 'after_booking' => __( 'After booking', 'booking' ), 'no_buffer' => __( 'No booking buffer is selected.', 'booking' ), ), ) ); } add_action( 'wpbc_enqueue_js_files', 'wpbc_availability_general_enqueue_js_files', 66 ); /** * Print tooltip initializer for General Availability. * * @return void */ function wpbc_availability_general_print_tooltip_js() { if ( ! wpbc_availability_general__is_page() ) { return; } if ( function_exists( 'wpbc_bs_javascript_tooltips' ) ) { wpbc_bs_javascript_tooltips(); } } add_action( 'admin_footer', 'wpbc_availability_general_print_tooltip_js', 67 ); /** * Get resource options. * * @return array */ function wpbc_availability_general__get_resources() { $resources = array(); if ( function_exists( 'wpbc_ajx_get_sorted_booking_resources_arr' ) && function_exists( 'wpbc_ajx_get_all_booking_resources_arr' ) ) { $resource_rows = wpbc_ajx_get_sorted_booking_resources_arr( wpbc_ajx_get_all_booking_resources_arr() ); foreach ( $resource_rows as $resource ) { $resources[] = array( 'id' => isset( $resource['booking_type_id'] ) ? (int) $resource['booking_type_id'] : 1, 'title' => isset( $resource['title'] ) ? $resource['title'] : __( 'Booking resource', 'booking' ), ); } } if ( empty( $resources ) ) { $resources[] = array( 'id' => function_exists( 'wpbc_get_default_resource' ) ? (int) wpbc_get_default_resource() : 1, 'title' => __( 'Booking resource', 'booking' ), ); } return $resources; } /** * Get capability required to manage General Availability. * * @return string */ function wpbc_availability_general__get_manage_cap() { $min_user_role = get_bk_option( 'booking_user_role_settings' ); $capability = array( 'administrator' => 'activate_plugins', 'editor' => 'publish_pages', 'author' => 'publish_posts', 'contributor' => 'edit_posts', 'subscriber' => 'read', ); return isset( $capability[ $min_user_role ] ) ? $capability[ $min_user_role ] : 'manage_options'; } /** * Get selected resource ID for preview. * * @return int */ function wpbc_availability_general__get_preview_resource_id() { $resources = wpbc_availability_general__get_resources(); $default_resource = isset( $resources[0]['id'] ) ? (int) $resources[0]['id'] : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $resource_id = isset( $_REQUEST['resource_id'] ) ? absint( wp_unslash( $_REQUEST['resource_id'] ) ) : $default_resource; $resource_ids = wp_list_pluck( $resources, 'id' ); return in_array( $resource_id, $resource_ids, true ) ? $resource_id : $default_resource; } /** * Get selected month count for preview. * * @return int */ function wpbc_availability_general__get_preview_months_count() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $months = isset( $_REQUEST['months_count'] ) ? absint( wp_unslash( $_REQUEST['months_count'] ) ) : 6; return in_array( $months, array( 1, 2, 3, 4, 6, 12 ), true ) ? $months : 6; } /** * Validate preview resource ID. * * @param int $resource_id Resource ID. * * @return int */ function wpbc_availability_general__sanitize_preview_resource_id( $resource_id ) { $resources = wpbc_availability_general__get_resources(); $default_resource = isset( $resources[0]['id'] ) ? (int) $resources[0]['id'] : 1; $resource_ids = wp_list_pluck( $resources, 'id' ); return in_array( (int) $resource_id, $resource_ids, true ) ? (int) $resource_id : $default_resource; } /** * Validate preview months count. * * @param int $months_count Number of months. * * @return int */ function wpbc_availability_general__sanitize_preview_months_count( $months_count ) { $months_count = absint( $months_count ); return in_array( $months_count, array( 1, 2, 3, 4, 6, 12 ), true ) ? $months_count : 6; } /** * Get unavailable-from-today select options. * * @return array */ function wpbc_availability_general__get_unavailable_from_today_options() { $options = array( '0' => ' - ' ); foreach ( range( 5, 55, 5 ) as $extra_num ) { $options[ $extra_num . 'm' ] = $extra_num . ' ' . __( 'minutes', 'booking' ); } $options['60m'] = '1 ' . __( 'hour', 'booking' ); foreach ( range( 65, 115, 5 ) as $extra_num ) { $options[ $extra_num . 'm' ] = '1 ' . __( 'hour', 'booking' ) . ' ' . ( $extra_num - 60 ) . ' ' . __( 'minutes', 'booking' ); } foreach ( range( 120, 1380, 60 ) as $extra_num ) { $options[ $extra_num . 'm' ] = ( $extra_num / 60 ) . ' ' . __( 'hours', 'booking' ); } $options['1'] = '1 ' . __( 'day', 'booking' ); for ( $ii = 2; $ii < 92; $ii++ ) { $options[ (string) $ii ] = $ii . ' ' . __( 'days', 'booking' ); } return $options; } /** * Get available-from-today select options. * * @return array */ function wpbc_availability_general__get_available_from_today_options() { $options = array( '' => ' - ' ); foreach ( range( 1, 365 ) as $value ) { $options[ (string) $value ] = (string) $value; } return $options; } /** * Get minute buffer options. * * @return array */ function wpbc_availability_general__get_buffer_minutes_options() { $options = array( '' => ' - ' ); foreach ( range( 5, 55, 5 ) as $extra_num ) { $options[ $extra_num . 'm' ] = $extra_num . ' ' . __( 'minutes', 'booking' ); } $options['60m'] = '1 ' . __( 'hour', 'booking' ); foreach ( range( 65, 115, 5 ) as $extra_num ) { $options[ $extra_num . 'm' ] = '1 ' . __( 'hour', 'booking' ) . ' ' . ( $extra_num - 60 ) . ' ' . __( 'minutes', 'booking' ); } foreach ( range( 120, 1380, 60 ) as $extra_num ) { $options[ $extra_num . 'm' ] = ( $extra_num / 60 ) . ' ' . __( 'hours', 'booking' ); } return $options; } /** * Get day buffer options. * * @return array */ function wpbc_availability_general__get_buffer_days_options() { $options = array( '' => ' - ' ); foreach ( range( 1, 30 ) as $extra_num ) { $options[ $extra_num . 'd' ] = $extra_num . ' ' . __( 'day(s)', 'booking' ); } return $options; } /** * Get time options for future working-time controls. * * @param string $selected Selected value. * * @return array */ function wpbc_availability_general__get_working_time_options( $selected = '' ) { $options = array(); for ( $minutes = 0; $minutes <= 1440; $minutes += 30 ) { $hours = (int) floor( $minutes / 60 ); $mins = $minutes % 60; $value = sprintf( '%02d:%02d', $hours, $mins ); $label = ( 1440 === $minutes ) ? '24:00' : $value; $options[ $value ] = $label; } if ( '' !== $selected && ! isset( $options[ $selected ] ) ) { $options[ $selected ] = $selected; } return $options; } /** * Render a select field. * * @param string $name Field name. * @param array $options Options. * @param string $selected Selected value. * @param array $args Extra args. * * @return void */ function wpbc_availability_general__render_select( $name, $options, $selected, $args = array() ) { $args = wp_parse_args( $args, array( 'id' => $name, 'class' => 'wpbc_ag_field_control', 'disabled' => false, ) ); ?> array(), 'booking_unavailable_days_num_from_today' => '0', 'booking_available_days_num_from_today' => '', 'booking_unavailable_extra_in_out' => '', 'booking_unavailable_extra_minutes_in' => '', 'booking_unavailable_extra_minutes_out' => '', 'booking_unavailable_extra_days_in' => '', 'booking_unavailable_extra_days_out' => '', ); } /** * Validate posted settings. * * @param array $post_data Raw post data. * * @return array */ function wpbc_availability_general__validate_data( $post_data ) { $cleaned = wpbc_availability_general__get_default_settings(); if ( isset( $post_data['booking_unavailable_days'] ) && is_array( $post_data['booking_unavailable_days'] ) ) { foreach ( $post_data['booking_unavailable_days'] as $day_num ) { $day_num = absint( $day_num ); if ( $day_num >= 0 && $day_num <= 6 ) { $cleaned['weekdays'][] = $day_num; } } } if ( isset( $post_data['booking_unavailable_days_num_from_today'] ) ) { $value = sanitize_text_field( wp_unslash( $post_data['booking_unavailable_days_num_from_today'] ) ); if ( preg_match( '/^\d+m$/', $value ) || preg_match( '/^\d+$/', $value ) ) { $cleaned['booking_unavailable_days_num_from_today'] = $value; } } if ( isset( $post_data['booking_available_days_num_from_today'] ) ) { $value = sanitize_text_field( wp_unslash( $post_data['booking_available_days_num_from_today'] ) ); $cleaned['booking_available_days_num_from_today'] = ( '' === $value ) ? '' : (string) absint( $value ); } if ( isset( $post_data['booking_unavailable_extra_in_out'] ) ) { $value = sanitize_text_field( wp_unslash( $post_data['booking_unavailable_extra_in_out'] ) ); $cleaned['booking_unavailable_extra_in_out'] = in_array( $value, array( '', 'm', 'd' ), true ) ? $value : ''; } foreach ( array( 'booking_unavailable_extra_minutes_in', 'booking_unavailable_extra_minutes_out' ) as $key ) { if ( isset( $post_data[ $key ] ) ) { $value = sanitize_text_field( wp_unslash( $post_data[ $key ] ) ); $cleaned[ $key ] = preg_match( '/^\d+m$/', $value ) ? $value : ''; } } foreach ( array( 'booking_unavailable_extra_days_in', 'booking_unavailable_extra_days_out' ) as $key ) { if ( isset( $post_data[ $key ] ) ) { $value = sanitize_text_field( wp_unslash( $post_data[ $key ] ) ); $cleaned[ $key ] = preg_match( '/^\d+d$/', $value ) ? $value : ''; } } return $cleaned; } /** * Update settings. * * @param array $cleaned_data Cleaned settings. * * @return void */ function wpbc_availability_general__update_settings( $cleaned_data ) { for ( $i = 0; $i < 7; $i++ ) { update_bk_option( 'booking_unavailable_day' . $i, in_array( $i, $cleaned_data['weekdays'], true ) ? 'On' : 'Off' ); } update_bk_option( 'booking_unavailable_days_num_from_today', $cleaned_data['booking_unavailable_days_num_from_today'] ); if ( class_exists( 'wpdev_bk_biz_m' ) ) { update_bk_option( 'booking_available_days_num_from_today', $cleaned_data['booking_available_days_num_from_today'] ); update_bk_option( 'booking_unavailable_extra_in_out', $cleaned_data['booking_unavailable_extra_in_out'] ); update_bk_option( 'booking_unavailable_extra_minutes_in', $cleaned_data['booking_unavailable_extra_minutes_in'] ); update_bk_option( 'booking_unavailable_extra_minutes_out', $cleaned_data['booking_unavailable_extra_minutes_out'] ); update_bk_option( 'booking_unavailable_extra_days_in', $cleaned_data['booking_unavailable_extra_days_in'] ); update_bk_option( 'booking_unavailable_extra_days_out', $cleaned_data['booking_unavailable_extra_days_out'] ); } } /** * Get current settings prepared for JavaScript and AJAX responses. * * @return array */ function wpbc_availability_general__get_settings_response() { $hints = function_exists( 'wpbc_get_unavailable_from_today_hints_arr' ) ? wpbc_get_unavailable_from_today_hints_arr() : array(); $weekdays = array(); for ( $i = 0; $i < 7; $i++ ) { if ( 'On' === get_bk_option( 'booking_unavailable_day' . $i ) ) { $weekdays[] = $i; } } return array( 'weekdays' => $weekdays, 'booking_unavailable_days_num_from_today' => get_bk_option( 'booking_unavailable_days_num_from_today' ), 'booking_available_days_num_from_today' => get_bk_option( 'booking_available_days_num_from_today' ), 'booking_unavailable_extra_in_out' => get_bk_option( 'booking_unavailable_extra_in_out' ), 'booking_unavailable_extra_minutes_in' => get_bk_option( 'booking_unavailable_extra_minutes_in' ), 'booking_unavailable_extra_minutes_out' => get_bk_option( 'booking_unavailable_extra_minutes_out' ), 'booking_unavailable_extra_days_in' => get_bk_option( 'booking_unavailable_extra_days_in' ), 'booking_unavailable_extra_days_out' => get_bk_option( 'booking_unavailable_extra_days_out' ), 'hints' => array( 'booking_unavailable_days_num_from_today__hint' => isset( $hints['booking_unavailable_days_num_from_today__hint'] ) ? $hints['booking_unavailable_days_num_from_today__hint'] : '', 'booking_available_days_num_from_today__hint' => isset( $hints['booking_available_days_num_from_today__hint'] ) ? $hints['booking_available_days_num_from_today__hint'] : '', ), ); } /** * Render booking resource calendar preview. * * @param int $resource_id Resource ID. * @param int $months_count Number of months. * * @return void */ function wpbc_availability_general__render_calendar_preview( $resource_id, $months_count ) { $resource_id = wpbc_availability_general__sanitize_preview_resource_id( $resource_id ); $months_count = wpbc_availability_general__sanitize_preview_months_count( $months_count ); $months_in_row = min( 3, max( 1, $months_count ) ); $calendar_css_class_outer = 'wpbc_calendar_wraper'; if ( 'Off' !== get_bk_option( 'booking_change_over_days_triangles' ) ) { $calendar_css_class_outer .= ' wpbc_change_over_triangle'; } ?>