Add Booking experience.
*
* The admin page calls this without args, so legacy $_GET driven behavior stays intact.
* Future embedded contexts can pass explicit args, which are always preferred over $_GET.
*/
class WPBC_Add_Booking_Component {
/**
* Check if current user can access the Add Booking workflow.
*
* @return bool
*/
public static function current_user_can_add_booking() {
$user_role = get_bk_option( 'booking_user_role_addbooking' );
$cap = 'read';
if ( class_exists( 'WPBC_Admin_Menus' ) && isset( WPBC_Admin_Menus::$capability[ $user_role ] ) ) {
$cap = WPBC_Admin_Menus::$capability[ $user_role ];
} elseif ( class_exists( 'WPBC_Admin_Menus' ) && isset( WPBC_Admin_Menus::$capability['subscriber'] ) ) {
$cap = WPBC_Admin_Menus::$capability['subscriber'];
}
return current_user_can( $cap );
}
/**
* Render the component and echo by default.
*
* @param array $args Component options.
*
* @return string|void
*/
public static function render( $args = array() ) {
$args = self::normalize_args( $args );
$is_echo = ( ! empty( $args['is_echo'] ) );
ob_start();
?> $args['_is_explicit_resource_id'] ? $args['resource_id'] : null,
'booking_form' => $args['_is_explicit_booking_form'] ? $args['custom_booking_form'] : null,
)
);
}
?>
$args['resource_id'],
'cal_count' => $args['cal_count'],
'is_echo' => 1,
'custom_booking_form' => $args['custom_booking_form'],
'selected_dates_without_calendar' => $args['selected_dates_without_calendar'],
'start_month_calendar' => $args['start_month_calendar'],
'shortcode_param__options' => $args['shortcode_param__options'],
'calendar_dates_start' => $args['calendar_dates_start'],
'calendar_dates_end' => $args['calendar_dates_end'],
'booking_hash' => $args['booking_hash'],
)
);
?>
null,
'booking_type' => null,
'booking_form' => null,
'custom_booking_form' => null,
'calendar_options' => null,
'cal_count' => null,
'calendar_months_count' => null,
'shortcode_param__options' => null,
'selected_dates_without_calendar' => null,
'start_month_calendar' => false,
'calendar_dates_start' => '',
'calendar_dates_end' => '',
'booking_hash' => '',
'allow_past' => null,
'selected_dates' => '',
'selected_date' => '',
'selected_time' => '',
'time_override_enabled' => 0,
'time_override_source' => '',
'time_override_start' => '',
'time_override_end' => '',
'is_toolbar_visible' => true,
'is_booking_page_js' => true,
'is_booking_page_popover' => true,
'is_show_before_content_spacer' => true,
'is_show_footer_email_toggle' => true,
'content_css_class' => 'add_booking_page_content',
'content_style' => 'width:100%;margin-bottom:100px;',
'is_echo' => 1,
);
$args = wp_parse_args( $args, $defaults );
$args['_is_explicit_resource_id'] = ( ( null !== $args['resource_id'] ) && ( absint( $args['resource_id'] ) > 0 ) )
|| ( ( null !== $args['booking_type'] ) && ( absint( $args['booking_type'] ) > 0 ) );
$args['_is_explicit_booking_form'] = ( ( null !== $args['custom_booking_form'] ) && ( '' !== (string) $args['custom_booking_form'] ) )
|| ( ( null !== $args['booking_form'] ) && ( '' !== (string) $args['booking_form'] ) );
$resource_id = self::get_explicit_or_get_resource_id( $args );
$form_name = self::get_explicit_or_get_booking_form( $args, $resource_id );
$calendar_params = self::get_calendar_params( $args );
$args['resource_id'] = $resource_id;
$args['custom_booking_form'] = $form_name;
$args['cal_count'] = $calendar_params['months_number'];
$args['shortcode_param__options'] = $calendar_params['shortcode_param__options'];
$args['selected_dates_without_calendar'] = ( null !== $args['selected_dates_without_calendar'] ) ? (string) $args['selected_dates_without_calendar'] : '';
$args['calendar_dates_start'] = (string) $args['calendar_dates_start'];
$args['calendar_dates_end'] = (string) $args['calendar_dates_end'];
$args['booking_hash'] = ( '' !== (string) $args['booking_hash'] ) ? sanitize_text_field( wp_unslash( (string) $args['booking_hash'] ) ) : ( isset( $_GET['booking_hash'] ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['allow_past'] = ( null !== $args['allow_past'] ) ? ( ! empty( $args['allow_past'] ) ? 1 : 0 ) : ( isset( $_GET['allow_past'] ) ? 1 : 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['selected_dates'] = sanitize_text_field( wp_unslash( (string) $args['selected_dates'] ) );
$args['selected_date'] = sanitize_text_field( wp_unslash( (string) $args['selected_date'] ) );
$args['selected_time'] = sanitize_text_field( wp_unslash( (string) $args['selected_time'] ) );
$args['time_override_enabled'] = ! empty( $args['time_override_enabled'] ) ? 1 : 0;
$args['time_override_source'] = sanitize_key( wp_unslash( (string) $args['time_override_source'] ) );
$args['time_override_start'] = sanitize_text_field( wp_unslash( (string) $args['time_override_start'] ) );
$args['time_override_end'] = sanitize_text_field( wp_unslash( (string) $args['time_override_end'] ) );
return $args;
}
/**
* Print per-render context that legacy front-end JavaScript reads from the global _wpbc object.
*
* @param array $args Component options.
*
* @return void
*/
private static function print_context_js( $args ) {
$booking_hash = isset( $args['booking_hash'] ) ? (string) $args['booking_hash'] : '';
$allow_past_date_arr = self::get_allow_past_min_date_arr( $args );
$context = array(
'resource_id' => absint( $args['resource_id'] ),
'selected_dates_without_calendar' => (string) $args['selected_dates_without_calendar'],
'selected_dates' => (string) $args['selected_dates'],
'selected_date' => (string) $args['selected_date'],
'selected_time' => (string) $args['selected_time'],
'time_override_enabled' => absint( $args['time_override_enabled'] ),
'time_override_source' => (string) $args['time_override_source'],
'time_override_start' => (string) $args['time_override_start'],
'time_override_end' => (string) $args['time_override_end'],
'allow_past' => ! empty( $args['allow_past'] ) ? 1 : 0,
);
?>
0 ) ) {
return absint( $args['resource_id'] );
}
if ( ( null !== $args['booking_type'] ) && ( absint( $args['booking_type'] ) > 0 ) ) {
return absint( $args['booking_type'] );
}
if ( isset( $_GET['booking_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return intval( $_GET['booking_type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
return 1;
}
/**
* Resolve default booking form for specific booking resource.
*
* @param int $resource_id Booking resource ID.
* @param string $default_form Fallback form name.
*
* @return string
*/
public static function get_default_booking_form_for_resource( $resource_id, $default_form = 'standard' ) {
$resource_id = absint( $resource_id );
$default_form = ( '' !== (string) $default_form ) ? (string) $default_form : 'standard';
if ( $resource_id <= 0 ) {
return sanitize_text_field( wp_unslash( $default_form ) );
}
$default_custom_form_name = '';
if ( function_exists( 'apply_bk_filter' ) ) {
$default_custom_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', '', $resource_id );
}
if (
( '' === (string) $default_custom_form_name )
&& class_exists( 'WPBC_FE_Custom_Form_Helper' )
&& method_exists( 'WPBC_FE_Custom_Form_Helper', 'get_default_custom_form__for__booking_resource' )
) {
$default_custom_form_name = WPBC_FE_Custom_Form_Helper::get_default_custom_form__for__booking_resource( $resource_id );
}
$default_custom_form_name = sanitize_text_field( wp_unslash( (string) $default_custom_form_name ) );
return ( '' !== $default_custom_form_name ) ? $default_custom_form_name : sanitize_text_field( wp_unslash( $default_form ) );
}
/**
* Resolve booking form: explicit component args first, then legacy $_GET, then resource default.
*
* @param array $args Component options.
* @param int $resource_id Booking resource ID.
*
* @return string
*/
private static function get_explicit_or_get_booking_form( $args, $resource_id = 0 ) {
if ( ( null !== $args['custom_booking_form'] ) && ( '' !== (string) $args['custom_booking_form'] ) ) {
return sanitize_text_field( wp_unslash( (string) $args['custom_booking_form'] ) );
}
if ( ( null !== $args['booking_form'] ) && ( '' !== (string) $args['booking_form'] ) ) {
return sanitize_text_field( wp_unslash( (string) $args['booking_form'] ) );
}
if ( WPBC_GET_Request::has_non_empty_get( 'booking_form' ) ) {
return WPBC_GET_Request::get_sanitized( 'booking_form' );
}
return self::get_default_booking_form_for_resource( $resource_id, 'standard' );
}
/**
* Resolve calendar settings for the component.
*
* @param array $args Component options.
*
* @return array
*/
private static function get_calendar_params( $args ) {
if ( null !== $args['calendar_options'] && is_array( $args['calendar_options'] ) ) {
$calendar_options = self::format_calendar_options( $args['calendar_options'] );
} else {
$calendar_options = self::get_saved_user_calendar_options();
}
if ( null !== $args['calendar_months_count'] ) {
$calendar_options['months_number'] = absint( $args['calendar_months_count'] );
}
if ( null !== $args['cal_count'] ) {
$calendar_options['months_number'] = absint( $args['cal_count'] );
}
if ( empty( $calendar_options['months_number'] ) ) {
$calendar_options['months_number'] = 1;
}
if ( null !== $args['shortcode_param__options'] ) {
$shortcode_param__options = (string) $args['shortcode_param__options'];
} else {
$shortcode_param__options = '{calendar' . $calendar_options['options_param'] . '}';
}
return array(
'months_number' => absint( $calendar_options['months_number'] ),
'shortcode_param__options' => $shortcode_param__options,
);
}
/**
* Get Calendar Options of specific User.
*
* @return array Number of months and calendar options parameter.
*/
public static function get_saved_user_calendar_options() {
$user_calendar_options = get_user_option( 'booking_custom_' . 'add_booking_calendar_options', wpbc_get_current_user_id() );
if ( false === $user_calendar_options ) {
$user_calendar_options = array();
} else {
$user_calendar_options = maybe_unserialize( $user_calendar_options );
}
return self::format_calendar_options( $user_calendar_options );
}
/**
* Convert calendar option values to the shortcode option string used by the renderer.
*
* @param array $user_calendar_options Raw calendar options.
*
* @return array
*/
private static function format_calendar_options( $user_calendar_options ) {
$defaults = array(
'calendar_months_count' => 1,
'calendar_months_num_in_1_row' => 0,
'calendar_width' => '',
'calendar_widthunits' => 'px',
'calendar_cell_height' => '',
'calendar_cell_heightunits' => 'px',
);
$user_calendar_options = wp_parse_args( (array) $user_calendar_options, $defaults );
if ( ! empty( $user_calendar_options['calendar_months_count'] ) ) {
$selected_calendar_months_count = intval( $user_calendar_options['calendar_months_count'] );
} else {
$selected_calendar_months_count = 1;
}
if ( ! empty( $user_calendar_options['calendar_months_num_in_1_row'] ) ) {
$option_months_num_in_row = ' months_num_in_row=' . intval( $user_calendar_options['calendar_months_num_in_1_row'] );
} else {
$option_months_num_in_row = '';
}
if ( ! empty( $user_calendar_options['calendar_width'] ) ) {
$unit_value = ( esc_attr( $user_calendar_options['calendar_widthunits'] ) == 'percent' ) ? '%' : esc_attr( $user_calendar_options['calendar_widthunits'] );
$option_width = ' width=' . intval( $user_calendar_options['calendar_width'] ) . $unit_value;
$option_width .= ' strong_width=' . intval( $user_calendar_options['calendar_width'] ) . $unit_value; // FixIn: 9.3.1.6.
} else {
$option_width = '';
}
if ( ! empty( $user_calendar_options['calendar_cell_height'] ) ) {
$unit_value = ( esc_attr( $user_calendar_options['calendar_cell_heightunits'] ) == 'percent' ) ? '%' : esc_attr( $user_calendar_options['calendar_cell_heightunits'] );
$option_cell_height = ' cell_height=' . intval( $user_calendar_options['calendar_cell_height'] ) . $unit_value;
} else {
$option_cell_height = '';
}
return array(
'months_number' => $selected_calendar_months_count,
'options_param' => $option_months_num_in_row . $option_width . $option_cell_height,
);
}
}