load(); if ( 'completed' !== $checkpoint['status'] ) { self::redirect_to_setup_page(); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by authorize_request(). $expected_revision = isset( $_POST['expected_revision'] ) && is_scalar( $_POST['expected_revision'] ) ? absint( wp_unslash( $_POST['expected_revision'] ) ) : -1; $result = $draft_store->navigate_to_step( $target_step_id, $checkpoint['current_step'], $expected_revision ); if ( is_wp_error( $result ) ) { self::redirect_with_notice( self::is_stale_error( $result ) ? 'stale' : 'error' ); } self::redirect_to_setup_page(); } /** * Start a fresh wizard navigation pass without rolling back live settings. * * @return void */ public static function restart() { self::authorize_request(); $draft_store = self::create_draft_store(); $checkpoint = $draft_store->load(); if ( 'completed' !== $checkpoint['status'] ) { self::redirect_to_setup_page(); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by authorize_request(). $expected_revision = isset( $_POST['expected_revision'] ) && is_scalar( $_POST['expected_revision'] ) ? absint( wp_unslash( $_POST['expected_revision'] ) ) : -1; $result = $draft_store->restart( $expected_revision ); if ( is_wp_error( $result ) ) { self::redirect_with_notice( self::is_stale_error( $result ) ? 'stale' : 'error' ); } self::redirect_to_setup_page(); } /** * Enforce login capability and the shared overview nonce. * * @return void */ private static function authorize_request() { if ( ! WPBC_Setup_Wizard_Access::current_user_can_access() ) { wp_die( esc_html__( 'You are not allowed to change this Setup Wizard.', 'booking' ), esc_html__( 'Access denied', 'booking' ), array( 'response' => 403 ) ); } $request_method = isset( $_SERVER['REQUEST_METHOD'] ) && is_scalar( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) ) : ''; if ( 'POST' !== $request_method ) { wp_die( esc_html__( 'This Setup Wizard action requires a form submission.', 'booking' ), esc_html__( 'Invalid request method', 'booking' ), array( 'response' => 405 ) ); } check_admin_referer( self::NONCE_ACTION, self::NONCE_NAME ); } /** * Create the owner/site-scoped checkpoint store used by overview actions. * * @return WPBC_Setup_Wizard_Draft_Store Checkpoint store. */ private static function create_draft_store() { $module_registry = new WPBC_Setup_Wizard_Step_Module_Registry(); $step_registry = new WPBC_Setup_Wizard_Step_Registry( $module_registry ); $step_data = new WPBC_Setup_Wizard_Step_Data( $module_registry ); return new WPBC_Setup_Wizard_Draft_Store( $step_registry, new WPBC_Setup_Wizard_Draft_Validator( $step_data ) ); } /** * Determine whether an operation failed because the client checkpoint was stale. * * @param WP_Error $error Setup Wizard operation error. * * @return bool True for a stale revision or stale step error. */ private static function is_stale_error( WP_Error $error ) { return 0 === strpos( (string) $error->get_error_code(), 'wpbc_setup_wizard_stale_' ); } /** * Redirect to the canonical Setup Wizard menu URL and stop execution. * * @return void */ private static function redirect_to_setup_page() { wp_safe_redirect( wpbc_get_setup_wizard_page_url() ); exit; } /** * Redirect a bounded error code to the completed overview. * * @param string $notice_code Allow-listed presentation notice code. * * @return void */ private static function redirect_with_notice( $notice_code ) { $notice_code = in_array( $notice_code, array( 'stale', 'error' ), true ) ? $notice_code : 'error'; wp_safe_redirect( add_query_arg( 'wpbc_setup_overview_notice', $notice_code, wpbc_get_setup_wizard_page_url() ) ); exit; } }