array( 'validate' => 'digit_or_csd', 'default' => array( '1' ) ) * , ... ) */ function wpbc_setup_wizard_page__request_rules_structure() { return array( 'do_action' => array( 'validate' => array( 'none', 'save_and_continue', 'make_reset', 'skip_wizard', 'save_and_continue__welcome', 'save_and_continue__general_info', 'save_and_continue__date_time_formats', 'save_and_continue__bookings_types', 'redirect_to_setup_step' ), 'default' => 'none' ), 'current_step' => array( 'validate' => 's', 'default' => '' ), 'resource_id' => array( 'validate' => 'd', 'default' => wpbc_get_default_resource() ), 'ui_clicked_element_id' => array( 'validate' => 's', 'default' => '' ) // 'calendar__booking_start_day_weeek' => array( 'validate' => array( '0', '1', '2', '3', '4', '5', '6' ), 'default' => get_bk_option( 'booking_start_day_weeek' ) ) ); } /** * Get default params * * @return array array ( 'ui_wh_modification_date_radio' => 0 * , ... ) */ function wpbc_setup_wizard_page__get__request_values__default(){ $request_rules_structure = wpbc_setup_wizard_page__request_rules_structure(); $default_params_arr = array(); $structure_type = 'default'; foreach ( $request_rules_structure as $key => $value ) { $default_params_arr[ $key ] = $value[ $structure_type ]; } return $default_params_arr; } // ===================================================================================================================== // == Get sanitised Request parameters for Ajax == // ===================================================================================================================== /** * Get sanitised request parameters. | 01. -> Firstly check if user saved request params in user_meta DB. * | 02. -> Otherwise check $_REQUEST. * | 03. -> Otherwise Get default. * * @return array|false */ function wpbc_setup_wizard_page__get_cleaned_params__saved_request_default(){ // User Specific Experience with Setup -> saved to user meta_table. // E.g. next time user open the page with saved own settings $user_request = new WPBC_AJX__REQUEST( array( 'db_option_name' => 'booking_setup_wizard_page_request_params', 'user_id' => wpbc_get_current_user_id(), 'request_rules_structure' => wpbc_setup_wizard_page__request_rules_structure() ) ); // ----------------------------------------------------------------------------------------------------------------- // Get saved from DB // ----------------------------------------------------------------------------------------------------------------- $escaped_request_params_arr = $user_request->get_sanitized__saved__user_request_params(); // ----------------------------------------------------------------------------------------------------------------- // Get $_REQUEST or Default :: This request was not saved before, then get sanitized direct parameters , such as: $_REQUEST['resource_id'] // ----------------------------------------------------------------------------------------------------------------- if ( false === $escaped_request_params_arr ) { $request_prefix = false; $escaped_request_params_arr = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); } // ----------------------------------------------------------------------------------------------------------------- // == O V E R R I D E - DB params by the params from REQUEST! == // ----------------------------------------------------------------------------------------------------------------- $request_key = 'current_step'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing if ( isset( $_REQUEST[ $request_key ] ) ) { // Get SANITIZED REQUEST parameters together with default values $request_prefix = false; $url_request_params_arr = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // Direct: $_REQUEST['resource_id'] // Now get only SANITIZED values that exist in REQUEST // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing $url_request_params_only_arr = array_intersect_key( $url_request_params_arr, $_REQUEST ); // And now override our DB $escaped_request_params_arr by SANITIZED $_REQUEST values $escaped_request_params_arr = wp_parse_args( $url_request_params_only_arr, $escaped_request_params_arr ); } // --------------------------------------------------------------------------------------------------------- // //MU // if ( class_exists( 'wpdev_bk_multiuser' ) ) { // // // Check if this MU user activated or super-admin, otherwise show warning // if ( ! wpbc_is_mu_user_can_be_here('activated_user') ) // return false; // // // Check if this MU user owner of this resource or super-admin, otherwise show warning // if ( ! wpbc_is_mu_user_can_be_here( 'resource_owner', $escaped_request_params_arr['resource_id'] ) ) { // $default_values = $user_request->get_request_rules__default(); // $escaped_request_params_arr['resource_id'] = $default_values['resource_id']; // } // } return $escaped_request_params_arr; } // ===================================================================================================================== // == A J A X == // ===================================================================================================================== class WPBC_AJX__Setup_Wizard__Ajax_Request { /** * Define HOOKs for start loading Ajax */ public function define_ajax_hook(){ // Ajax Handlers. Note. "locale_for_ajax" rechecked in wpbc-ajax.php add_action( 'wp_ajax_' . 'WPBC_AJX_SETUP_WIZARD_PAGE', array( $this, 'ajax_' . 'WPBC_AJX_SETUP_WIZARD_PAGE' ) ); // Admin & Client (logged in usres) add_action( 'wp_ajax_' . 'WPBC_AJX_SETUP_WIZARD_MARK_STEP_SAVED', array( $this, 'ajax_' . 'WPBC_AJX_SETUP_WIZARD_MARK_STEP_SAVED' ) ); // Ajax Handlers for actions // add_action( 'wp_ajax_nopriv_' . 'WPBC_AJX_BOOKING_LISTING', array( $this, 'ajax_' . 'WPBC_AJX_BOOKING_LISTING' ) ); // Client (not logged in) } /** * Ajax - mark an external setup step as saved after an existing settings page saves successfully. * * @return void */ public function ajax_WPBC_AJX_SETUP_WIZARD_MARK_STEP_SAVED() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( ! wp_verify_nonce( $nonce, 'wpbc_setup_wizard_mark_step_saved' ) ) { wp_send_json_error( array( 'message' => __( 'Security check failed.', 'booking' ) ) ); } $step_name = isset( $_POST['wpbc_setup_step'] ) ? sanitize_key( wp_unslash( $_POST['wpbc_setup_step'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $setup_steps = new WPBC_SETUP_WIZARD_STEPS(); $steps_arr = $setup_steps->get_steps_arr(); if ( empty( $step_name ) && function_exists( 'wpbc_setup_wizard__detect_step_from_admin_url' ) ) { $referer_step = wpbc_setup_wizard__detect_step_from_admin_url( wp_get_referer() ); if ( ! empty( $referer_step ) && isset( $steps_arr[ $referer_step ] ) ) { $step_name = $referer_step; } } if ( empty( $step_name ) || ! isset( $steps_arr[ $step_name ] ) ) { wp_send_json_error( array( 'message' => __( 'Unknown setup step.', 'booking' ) ) ); } $setup_steps->db__set_step_as_saved( $step_name, true ); $setup_steps->db__save_current_step_name( $step_name ); wp_send_json_success( array( 'step' => $step_name ) ); } /** * Ajax - Get Listing Data and Response to JS script */ public function ajax_WPBC_AJX_SETUP_WIZARD_PAGE() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing if ( ! isset( $_POST['all_ajx_params'] ) || empty( $_POST['all_ajx_params'] ) ) { exit; } // ------------------------------------------------------------------------------------------------------------- // == Security == -> in Ajax Post: 'nonce': wpbc_ajx_booking_listing.get_secure_param( 'nonce' ) // ------------------------------------------------------------------------------------------------------------- $action_name = 'wpbc_setup_wizard_page_ajx' . '_wpbcnonce'; $nonce_post_key = 'nonce'; $result_check = check_ajax_referer( $action_name, $nonce_post_key ); $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing // ------------------------------------------------------------------------------------------------------------- // == Request == -> $_REQUEST['all_ajx_params']['page_num'], $_REQUEST['all_ajx_params']['page_items_count'], ... // ------------------------------------------------------------------------------------------------------------- $user_request = new WPBC_AJX__REQUEST( array( 'db_option_name' => 'booking_setup_wizard_page_request_params', 'user_id' => $user_id, 'request_rules_structure' => wpbc_setup_wizard_page__request_rules_structure() ) ); //-------------------------------------------------------------------------------------------------------------- // If in Ajax: all_ajx_params: _wpbc_settings.get_all_..() -> Use prefix "all_ajx_params" THEN Sanitize required REQUEST params //-------------------------------------------------------------------------------------------------------------- $request_prefix = 'all_ajx_params'; $cleaned_request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['all_ajx_params']['resource_id'] //-------------------------------------------------------------------------------------------------------------- $cleaned_data = array(); $setup_steps = new WPBC_SETUP_WIZARD_STEPS(); $data_arr = array(); $data_arr['ajx_after_action_message'] = ''; $data_arr['ajx_after_action_result'] = 1; // Message Type: ? '1' => 'success' : 'error' //-------------------------------------------------------------------------------------------------------------- // Steps //-------------------------------------------------------------------------------------------------------------- $data_arr['current_step'] = ( ! empty( $cleaned_request_params['current_step'] ) ? $cleaned_request_params['current_step'] : $setup_steps->get_active_step_name() ); // e.g. 'general_info' or 'date_availability' $data_arr['steps'] = $setup_steps->get_steps_arr(); if ( ! isset( $data_arr['steps'][ $data_arr['current_step'] ] ) ) { $data_arr['current_step'] = $setup_steps->get_active_step_name(); } // ------------------------------------------------------------------------------------------------------------- // Get Wizard history // ------------------------------------------------------------------------------------------------------------- $booking_wizard_data_arr = get_bk_option( 'booking_wizard_data' ); $booking_wizard_data_arr = ( empty( $booking_wizard_data_arr ) ) ? array() : $booking_wizard_data_arr; // ============================================================================================================= // == Do Action == // ============================================================================================================= switch ( $cleaned_request_params['do_action'] ) { // --------------------------------------------------------------------------------------------------------- // == RESET == // --------------------------------------------------------------------------------------------------------- case 'make_reset': $is_reseted = $user_request->user_request_params__db_delete(); // Delete from DB wpbc_setup_wizard__set_full_screen_mode_for_current_user( false ); $cleaned_request_params['do_action'] = $is_reseted ? 'reset_done' : 'reset_error'; $cleaned_request_params = wpbc_setup_wizard_page__get__request_values__default(); $data_arr['ajx_after_action_message'] = __( 'Start Setup from Beginning', 'booking' ); $data_arr['current_step'] = 'welcome'; update_bk_option( 'booking_wizard_data', array() ); $setup_steps->db__set_all_steps_as( false ); // Clear All Steps Mark as Undone break; case 'skip_wizard': $data_arr['current_step'] = 'welcome'; // $data_arr['redirect_url'] = wpbc_get_settings_url(); $data_arr['redirect_url'] = wpbc_get_bookings_url(); wpbc_setup_wizard__set_full_screen_mode_for_current_user( false ); $setup_steps->db__set_all_steps_as( true ); // Mark All Steps as Done break; case 'save_and_continue__welcome': $setup_steps->db__set_step_as_completed( 'welcome' ); break; case 'save_and_continue__general_info': // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing if ( isset( $_POST['all_ajx_params']['step_data'] ) && ( ! empty( $_POST['all_ajx_params']['step_data'] ) ) ) { $cleaned_data = wpbc_template__general_info__action_validate_data( $_POST['all_ajx_params']['step_data'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( 'On' === $cleaned_data['wpbc_swp_accept_send'] ) { //wpbc_setup_feedback__send_email( $cleaned_data ); // FixIn: 10.7.1.3. update_bk_option( 'booking_feedback__send_email', $cleaned_data ); } else { delete_bk_option( 'booking_feedback__send_email' ); } wpbc_setup__update__general_info( $cleaned_data ); } $setup_steps->db__set_step_as_completed( 'general_info' ); break; case 'save_and_continue__date_time_formats': // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing if ( isset( $_POST['all_ajx_params']['step_data'] ) && ( ! empty( $_POST['all_ajx_params']['step_data'] ) ) ) { $cleaned_data = wpbc_template__date_time_formats__action_validate_data( $_POST['all_ajx_params']['step_data'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized wpbc_setup__update__date_time_formats( $cleaned_data ); } $setup_steps->db__set_step_as_completed( 'date_time_formats' ); break; case 'save_and_continue__bookings_types': // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing if ( isset( $_POST['all_ajx_params']['step_data'] ) && ( ! empty( $_POST['all_ajx_params']['step_data'] ) ) ) { $cleaned_data = wpbc_template__bookings_types__action_validate_data( $_POST['all_ajx_params']['step_data'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized // Legacy update booking form and dates selection, as some other options (recurrent time).... wpbc_setup__update__bookings_types( $cleaned_data ); $booking_wizard_data_arr['save_and_continue__bookings_types'] = $cleaned_data; update_bk_option( 'booking_wizard_data', $booking_wizard_data_arr ); $setup_steps = new WPBC_SETUP_WIZARD_STEPS(); // FixIn: 10.7.1.3. // FixIn: 10.15.1.1. $cleaned_data_booking_feedback_arr = get_bk_option( 'booking_feedback__send_email' ); if (! empty($cleaned_data_booking_feedback_arr)){ if ( 'On' === $cleaned_data_booking_feedback_arr['wpbc_swp_accept_send'] ) { $cleaned_data_booking_feedback_arr = array_merge( $cleaned_data_booking_feedback_arr , array( 'type' => 'Type: ' . $cleaned_data ['wpbc_swp_booking_types'] ) ); if ( 'time_slots_appointments' === $cleaned_data ['wpbc_swp_booking_types'] ) { $cleaned_data_booking_feedback_arr = array_merge( $cleaned_data_booking_feedback_arr, array( 'appointments_type' => 'Appointment: ' . $cleaned_data ['wpbc_swp_booking_appointments_type'] ) ); } wpbc_setup_feedback__send_email( $cleaned_data_booking_feedback_arr ); update_bk_option( 'booking_feedback__after_send', $cleaned_data_booking_feedback_arr ); delete_bk_option( 'booking_feedback__send_email' ); } } } $setup_steps->db__set_step_as_completed( 'bookings_types' ); if ( ! empty( $cleaned_data ) ) { wpbc_setup_wizard__set_full_screen_mode_for_current_user( true ); $data_arr['current_step'] = wpbc_setup_wizard__get_first_profile_step(); $current_steps_arr = $setup_steps->get_steps_arr(); $setup_steps->db__reset_steps_from( $data_arr['current_step'] ); if ( isset( $current_steps_arr[ $data_arr['current_step'] ] ) && 'manual_save_required' === $setup_steps->get_step_save_behavior( $data_arr['current_step'] ) ) { $setup_steps->db__set_step_as_saved( $data_arr['current_step'], false ); } $data_arr['redirect_url'] = $setup_steps->get_step_target_url( $data_arr['current_step'] ); $data_arr['steps'] = $current_steps_arr; $cleaned_request_params['do_action'] = 'redirect_to_setup_step'; } break; default: // Default } //-------------------------------------------------------------------------------------------------------------- // Other //-------------------------------------------------------------------------------------------------------------- $data_arr['steps_is_done'] = $setup_steps->db__get_steps_is_done(); $data_arr['left_navigation'] = wpbc_setup_wizard_page__get_left_navigation_menu_arr(); $data_arr['plugin_menu__setup_progress'] = $setup_steps->get_plugin_menu_title__setup_progress( $data_arr['current_step'] ); // External setup steps are now configured on their existing admin pages, so the setup-page AJAX response does // not need to embed their duplicated calendars or forms. $data_arr['ui'] = array(); $data_arr['calendar_force_load'] = ''; // ------------------------------------------------------------------------------------------------------------- // Save Wizard history // ------------------------------------------------------------------------------------------------------------- // Save to DB $booking_wizard_data_arr[ $cleaned_request_params['do_action'] ] = $cleaned_data; update_bk_option( 'booking_wizard_data', $booking_wizard_data_arr ); // Ajax Transfer $data_arr['booking_wizard_data'] = $booking_wizard_data_arr; // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- // Save Status of Wizard for specific user // ------------------------------------------------------------------------------------------------------------- if ( 'make_reset' !== $cleaned_request_params['do_action'] ) { $cleaned_request_params['current_step'] = $data_arr['current_step']; $request_params_to_save = $cleaned_request_params; // Do not safe such elements unset( $request_params_to_save['ui_clicked_element_id'] ); unset( $request_params_to_save['do_action'] ); unset( $request_params_to_save['calendar_force_load'] ); unset( $request_params_to_save['plugin_menu__setup_progress'] ); $is_success_update = $user_request->user_request_params__db_save( $request_params_to_save ); // Save to DB // - $cleaned_request_params - serialized here automatically } if ( ! empty( $data_arr['calendar_force_load'] ) ) { $data_arr['calendar_force_load'] = wpbc_clean_calendar_loading_scripts( $data_arr['calendar_force_load'] ); } // ------------------------------------------------------------------------------------------------------------- // Send JSON. It will make "wp_json_encode" - so pass only array, and This function call wp_die( '', '', array( 'response' => null, ) ) Pass JS OBJ: response_data in "jQuery.post( " function on success. // ------------------------------------------------------------------------------------------------------------- wp_send_json( array( 'ajx_data' => $data_arr, // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 'ajx_all_ajx_params' => $_REQUEST[ $request_prefix ], // $_REQUEST[ 'all_ajx_params' ] 'ajx_cleaned_params' => $cleaned_request_params ) ); } } /** * Just for loading CSS and JavaScript files */ if ( true ) { $wpbc_setup_wizard_page_loading = new WPBC_AJX__Setup_Wizard__Ajax_Request; $wpbc_setup_wizard_page_loading->define_ajax_hook(); }