/home/techb158/public_html/wp-content/plugins/wpforms-lite/src/SetupWizard
NameSizeModeActions
Service/-0755rm
AbstractStripeConnect.php60600666editdlrm
Auth.php36110666editdlrm
Bridge.php68210666editdlrm
FailedInstallsNotice.php75920666editdlrm
RestApi.php189440666editdlrm
Screen.php37450666editdlrm
SetupWizard.php137210666editdlrm
StripeConnect.php38310666editdlrm
Edit: /home/techb158/public_html/wp-content/plugins/wpforms-lite/src/SetupWizard/SetupWizard.php (13721B)
load_dependencies(); $this->hooks(); } /** * Load the wizard dependencies. * * Every dependency is resolved to its edition-specific implementation when * one exists (see {@see self::load_dependency()}). * * @since 2.0.0 */ private function load_dependencies(): void { $auth = $this->load_dependency( Auth::class ); $service = $this->load_dependency( StateManager::class ); $this->stripe_connect = $this->load_dependency( StripeConnect::class ); $this->bridge = $this->load_dependency( Bridge::class, [ $auth ] ); $this->rest_api = $this->load_dependency( RestApi::class, [ $auth, $service ] ); $this->failed_installs_notice = $this->load_dependency( FailedInstallsNotice::class ); $this->screen = $this->load_dependency( Screen::class, [ $this->bridge, $service ] ); $this->cross_plugin_onboarding = $this->load_dependency( CrossPluginOnboarding::class ); } /** * Instantiate a wizard class, preferring the edition-specific implementation. * * Pro tries `WPForms\Pro\{Class}`, Lite tries `WPForms\Lite\{Class}`, and * both fall back to the shared `WPForms\{Class}` when no override exists. * * @since 2.0.0 * * @param string $dependency Shared class name. * @param array $args Constructor arguments. * * @return object */ private function load_dependency( string $dependency, array $args = [] ): object { $edition = wpforms()->is_pro() ? 'Pro' : 'Lite'; $edition_class = 'WPForms\\' . $edition . '\\' . substr( $dependency, strlen( 'WPForms\\' ) ); $dependency = class_exists( $edition_class ) ? $edition_class : $dependency; return new $dependency( ...$args ); } /** * Register hooks. * * @since 2.0.0 */ private function hooks(): void { add_action( 'rest_api_init', [ $this->rest_api, 'register_routes' ] ); add_action( 'admin_init', [ $this, 'maybe_record_first_activation' ] ); add_action( 'admin_init', [ $this, 'maybe_launch' ], PHP_INT_MAX ); add_action( 'admin_notices', [ $this->failed_installs_notice, 'maybe_display' ] ); $this->stripe_connect->hooks(); $this->screen->hooks(); // Suppression is permanent, so it is scoped to the wizard's own install // call: users installing through the Setup Checklist or an Education // one-click link never entered our onboarding and keep their own. if ( RestApi::is_install_request() ) { $this->cross_plugin_onboarding->hooks(); } } /** * Maybe launch the wizard. * * Decides whether to render the POST bridge for the current admin request: * - First-time activation within the 1h launch window. * - Lite-to-Pro relaunch with preserved state. * - Manual launch via the `wpforms_setup_wizard` query argument. * * Auto-launch is suppressed when the user lacks `manage_options`, in WP-CLI, * in network admin, or in local environments (unless explicitly overridden). * Both launch paths are suppressed when the wizard is disabled via the * `wpforms_setup_wizard_disabled` option, the * `WPFORMS_SETUP_WIZARD_DISABLED` constant, or the * `wpforms_setup_wizard_setup_wizard_is_disabled` filter. * * @since 2.0.0 */ public function maybe_launch(): void { if ( wp_doing_ajax() || wpforms_is_rest() ) { return; } if ( self::is_disabled() ) { $this->strip_manual_launch_arg(); return; } if ( ! current_user_can( 'manage_options' ) ) { $this->strip_manual_launch_arg(); return; } $manual = $this->is_manual_launch_request(); if ( ! $manual && ! self::will_auto_launch() ) { return; } // Consume the one-shot first-run signal so auto-launch fires exactly once, // whether or not the launch below actually reaches the user. if ( ! $manual ) { delete_transient( self::TRANSIENT_FIRST_RUN ); } if ( $this->screen->launch() ) { $this->failed_installs_notice->clear(); } exit; } /** * Strip the manual launch query argument when the current user cannot launch the wizard. * * Acts as the CSRF mitigation for the URL-driven launch: an attacker who * tricks an underprivileged user into following the link gets redirected * to a clean URL without the parameter, so refreshing or sharing the page * no longer attempts to launch the wizard. * * @since 2.0.0 */ private function strip_manual_launch_arg(): void { if ( ! $this->is_manual_launch_request() ) { return; } if ( headers_sent() ) { return; } wp_safe_redirect( remove_query_arg( self::QUERY_ARG ) ); exit; } /** * Record the first activation on the first admin pageview of a fresh install. * * The plugin's `init`-hooked services are not loaded during the activation * request itself (the plugin is included inside `activate_plugin()` after * `init` has fired), so first-run is detected lazily here instead of from the * activation hook. A fresh install is one where the migrations base has not * recorded a previous core version — the same signal the Welcome page uses to * tell an initial install from an upgrade. `record_first_activation()` is a * one-shot, so this is a cheap no-op on every subsequent request. * * @since 2.0.0 */ public function maybe_record_first_activation(): void { // Already recorded on a previous request. if ( get_option( self::OPTION_INITIAL_VERSION ) !== false ) { return; } // Existing install upgrading, not a fresh activation. if ( get_option( MigrationsBase::PREVIOUS_CORE_VERSION_OPTION_NAME ) ) { return; } $this->record_first_activation(); } /** * Mark the plugin's first activation. * * Sets `wpforms_setup_wizard_initial_version` and the `first_run` transient * so the next admin pageview triggers the wizard. * * @since 2.0.0 * * @return bool True if this call recorded the first activation. */ private function record_first_activation(): bool { $version = defined( 'WPFORMS_VERSION' ) ? WPFORMS_VERSION : ''; if ( ! add_option( self::OPTION_INITIAL_VERSION, $version, '', false ) ) { return false; } set_transient( self::TRANSIENT_FIRST_RUN, 1, HOUR_IN_SECONDS ); return true; } /** * Whether the wizard should auto-launch on the current request. * * Side-effect-free predicate shared with the Welcome page so exactly one of * {wizard, Welcome fallback} acts on a fresh install. Static because every * input is global state (options, the first-run transient, the request * context) — it carries no instance state and must be callable from the * legacy Welcome class before the wizard renders. * * @since 2.0.0 * * @return bool */ public static function will_auto_launch(): bool { if ( self::is_disabled() ) { return false; } if ( get_option( self::OPTION_COMPLETED ) ) { return false; } if ( ! get_transient( self::TRANSIENT_FIRST_RUN ) ) { return false; } if ( self::is_excluded_context() || self::is_excluded_page() ) { return false; } return true; } /** * Whether the Setup Wizard is disabled entirely. * * A kill switch for hosts and agencies that provision WPForms * programmatically: when disabled, the whole first-run experience stands * down — the wizard never launches (neither the first-run auto-launch nor * the manual `wpforms_setup_wizard` query argument), and the Welcome page * suppresses its fallback activation redirect as well (see * `WPForms_Welcome::redirect()`). Public and static for the same reason as * `will_auto_launch()`: it carries no instance state and is consumed by * the Welcome page before the wizard renders. * * Three inputs serve different deployment shapes: the option persists a * decision made in a single provisioning request, the constant serves * wp-config-level control, and the filter is the runtime override that * can force either direction. * * @since 2.0.1 * * @return bool */ public static function is_disabled(): bool { $disabled = get_option( self::OPTION_DISABLED ) || ( defined( 'WPFORMS_SETUP_WIZARD_DISABLED' ) && WPFORMS_SETUP_WIZARD_DISABLED ); /** * Filter whether the Setup Wizard is disabled entirely. * * Returning true suppresses the first-run auto-launch, the manual * launch via the `wpforms_setup_wizard` query argument, and the * Welcome page fallback activation redirect. * * @since 2.0.1 * * @param bool $disabled Whether the wizard is disabled. Defaults to true * when the `wpforms_setup_wizard_disabled` option * or the `WPFORMS_SETUP_WIZARD_DISABLED` constant * is set, otherwise false. */ return (bool) apply_filters( 'wpforms_setup_wizard_setup_wizard_is_disabled', (bool) $disabled ); } /** * Whether the current request is a context the wizard must never auto-launch in. * * @since 2.0.0 * * @return bool */ private static function is_excluded_context(): bool { if ( is_network_admin() ) { return true; } if ( defined( 'WP_CLI' ) && WP_CLI ) { return true; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended return isset( $_GET['activate-multi'] ); } /** * Whether the current admin page must not be interrupted by the wizard. * * Mirrors the Welcome page exclusions: launching from the block editor breaks * the WPForms Gutenberg block, and the form builder is its own flow. * * @since 2.0.0 * * @return bool */ private static function is_excluded_page(): bool { global $pagenow; if ( in_array( $pagenow, [ 'edit.php', 'post.php', 'post-new.php', 'site-editor.php' ], true ) ) { return true; } return wpforms_is_admin_page( 'builder' ); } /** * Determine whether the manual launch query argument is present and valid. * * @since 2.0.0 * * @return bool */ private function is_manual_launch_request(): bool { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return isset( $_GET[ self::QUERY_ARG ] ); } /** * Get the URL that launches the wizard manually from any admin page. * * Shared with the Welcome page so its "Launch Setup Wizard" notice and the * wizard agree on the query argument without duplicating its name. * * @since 2.0.0 * * @return string */ public static function get_manual_launch_url(): string { return add_query_arg( self::QUERY_ARG, 1, admin_url( 'admin.php?page=wpforms-overview' ) ); } }