id, array( 'toplevel_page_abtestkit-dashboard', 'abtestkit-dashboard_page_abtestkit-dashboard', 'abtestkit-dashboard_page_abtestkit-email-updates', 'admin_page_abtestkit-pt-wizard', 'admin_page_abtestkit-test-performance', ), true ); } /** * Determine whether the empty dashboard already provides enough connection actions. * * @return bool */ function abtestkit_hosted_email_updates_banner_is_redundant() : bool { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; if ( ! $screen ) { return false; } if ( ! in_array( (string) $screen->id, array( 'toplevel_page_abtestkit-dashboard', 'abtestkit-dashboard_page_abtestkit-dashboard', ), true ) ) { return false; } $tests = get_option( 'abtestkit_page_tests', array() ); return ! is_array( $tests ) || empty( $tests ); } /** * Show the required connected-account callout on abtestkit admin screens. * * @return void */ function abtestkit_hosted_render_email_updates_banner() : void { if ( ! is_admin() || ! current_user_can( 'manage_options' ) || ! abtestkit_hosted_email_updates_banner_is_target_screen() ) { return; } if ( abtestkit_connected_platform_can_create_or_launch() ) { return; } if ( abtestkit_hosted_email_updates_banner_is_redundant() ) { return; } echo '
'; } add_action( 'admin_notices', 'abtestkit_hosted_render_email_updates_banner', 20 ); /** * Permanently dismiss the Email updates banner for administrators. * * @return void */ function abtestkit_hosted_dismiss_email_updates_banner() : void { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to change this setting.', 'abtestkit' ) ); } check_admin_referer( 'abtestkit_hosted_dismiss_email_updates_banner' ); update_option( ABTESTKIT_HOSTED_EMAIL_UPDATES_BANNER_OPTION, array( 'dismissed' => 1 ), false ); wp_safe_redirect( abtestkit_admin_get_safe_return_url() ); exit; } add_action( 'admin_post_abtestkit_hosted_dismiss_email_updates_banner', 'abtestkit_hosted_dismiss_email_updates_banner' ); /** * Generate one URL-safe 256-bit value. * * @return string|WP_Error */ function abtestkit_hosted_random_credential() { try { return rtrim( strtr( base64_encode( random_bytes( 32 ) ), '+/', '-_' ), '=' ); } catch ( Exception $error ) { return new WP_Error( 'abtestkit_hosted_random_failed' ); } } /** * Validate the shared 43-character credential shape. * * @param mixed $value Candidate value. * @return string|WP_Error */ function abtestkit_hosted_validate_credential( $value ) { if ( ! is_string( $value ) || 43 !== strlen( $value ) || 1 !== preg_match( '/^[A-Za-z0-9_-]{43}$/D', $value ) ) { return new WP_Error( 'abtestkit_hosted_invalid_credential' ); } return $value; } /** * Canonicalise an HTTPS origin with no path, query or credentials. * * @param mixed $value Candidate origin. * @return string|WP_Error */ function abtestkit_hosted_canonical_origin( $value ) { if ( ! is_string( $value ) || '' === $value || strlen( $value ) > 255 ) { return new WP_Error( 'abtestkit_hosted_invalid_origin' ); } $parts = wp_parse_url( $value ); if ( ! is_array( $parts ) || 'https' !== strtolower( (string) ( $parts['scheme'] ?? '' ) ) || empty( $parts['host'] ) || isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['query'] ) || isset( $parts['fragment'] ) || ( isset( $parts['path'] ) && ! in_array( $parts['path'], array( '', '/' ), true ) ) ) { return new WP_Error( 'abtestkit_hosted_invalid_origin' ); } $host = strtolower( rtrim( (string) $parts['host'], '.' ) ); if ( '' === $host || 1 !== preg_match( '/^[a-z0-9.-]+$/D', $host ) ) { return new WP_Error( 'abtestkit_hosted_invalid_origin' ); } $port = isset( $parts['port'] ) ? (int) $parts['port'] : 0; if ( isset( $parts['port'] ) && ( $port < 1 || $port > 65535 ) ) { return new WP_Error( 'abtestkit_hosted_invalid_origin' ); } return 'https://' . $host . ( $port > 0 && 443 !== $port ? ':' . $port : '' ); } /** * Return this WordPress installation's HTTPS origin. * * @return string|WP_Error */ function abtestkit_hosted_site_origin() { $home = home_url( '/' ); $parts = wp_parse_url( $home ); if ( ! is_array( $parts ) || empty( $parts['host'] ) ) { return new WP_Error( 'abtestkit_hosted_invalid_origin' ); } $candidate = (string) ( $parts['scheme'] ?? '' ) . '://' . (string) $parts['host']; if ( isset( $parts['port'] ) && 443 !== (int) $parts['port'] ) { $candidate .= ':' . (int) $parts['port']; } /** * Filter the exact site origin used by the hosted connection protocol. * * Intended for controlled compatibility environments. Production values * must remain an HTTPS origin with no path or query. * * @param string $candidate Candidate origin. */ return abtestkit_hosted_canonical_origin( apply_filters( 'abtestkit_hosted_site_origin', $candidate ) ); } /** * Return the fixed service account page URL. * * @return string|WP_Error */ function abtestkit_hosted_service_account_url() { $url = apply_filters( 'abtestkit_hosted_service_account_url', 'https://www.abtestkit.io/abtestkit-account/' ); if ( ! is_string( $url ) || strlen( $url ) > 500 ) { return new WP_Error( 'abtestkit_hosted_invalid_service_url' ); } $parts = wp_parse_url( $url ); if ( ! is_array( $parts ) || 'https' !== strtolower( (string) ( $parts['scheme'] ?? '' ) ) || empty( $parts['host'] ) || isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['query'] ) || isset( $parts['fragment'] ) || '/abtestkit-account/' !== (string) ( $parts['path'] ?? '' ) ) { return new WP_Error( 'abtestkit_hosted_invalid_service_url' ); } $origin = abtestkit_hosted_canonical_origin( (string) $parts['scheme'] . '://' . (string) $parts['host'] . ( isset( $parts['port'] ) ? ':' . (int) $parts['port'] : '' ) ); if ( is_wp_error( $origin ) ) { return new WP_Error( 'abtestkit_hosted_invalid_service_url' ); } return $url; } /** * Return the fixed service REST base URL. * * @return string|WP_Error */ function abtestkit_hosted_service_api_base_url() { $url = apply_filters( 'abtestkit_hosted_service_api_base_url', 'https://www.abtestkit.io/wp-json/abtestkit-service/v1' ); if ( ! is_string( $url ) || strlen( $url ) > 500 ) { return new WP_Error( 'abtestkit_hosted_invalid_service_url' ); } $parts = wp_parse_url( $url ); if ( ! is_array( $parts ) || 'https' !== strtolower( (string) ( $parts['scheme'] ?? '' ) ) || empty( $parts['host'] ) || isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['query'] ) || isset( $parts['fragment'] ) || '/wp-json/abtestkit-service/v1' !== untrailingslashit( (string) ( $parts['path'] ?? '' ) ) ) { return new WP_Error( 'abtestkit_hosted_invalid_service_url' ); } $origin = abtestkit_hosted_canonical_origin( (string) $parts['scheme'] . '://' . (string) $parts['host'] . ( isset( $parts['port'] ) ? ':' . (int) $parts['port'] : '' ) ); if ( is_wp_error( $origin ) ) { return new WP_Error( 'abtestkit_hosted_invalid_service_url' ); } return untrailingslashit( $url ); } /** * Return and validate the fixed local callback URL. * * @param string $origin Expected site origin. * @return string|WP_Error */ function abtestkit_hosted_callback_url( $origin ) { $url = admin_url( 'admin.php?page=' . ABTESTKIT_HOSTED_CONNECTION_PAGE_SLUG ); $url = apply_filters( 'abtestkit_hosted_callback_url', $url ); if ( ! is_string( $url ) || strlen( $url ) > 500 ) { return new WP_Error( 'abtestkit_hosted_invalid_callback' ); } $parts = wp_parse_url( $url ); if ( ! is_array( $parts ) || isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['fragment'] ) ) { return new WP_Error( 'abtestkit_hosted_invalid_callback' ); } $callback_origin = abtestkit_hosted_canonical_origin( (string) $parts['scheme'] . '://' . (string) $parts['host'] . ( isset( $parts['port'] ) ? ':' . (int) $parts['port'] : '' ) ); if ( is_wp_error( $callback_origin ) || ! hash_equals( (string) $origin, $callback_origin ) ) { return new WP_Error( 'abtestkit_hosted_invalid_callback' ); } if ( empty( $parts['path'] ) || 1 !== preg_match( '#/wp-admin/admin\.php$#D', (string) $parts['path'] ) ) { return new WP_Error( 'abtestkit_hosted_invalid_callback' ); } $query = array(); parse_str( (string) ( $parts['query'] ?? '' ), $query ); if ( array( 'page' => ABTESTKIT_HOSTED_CONNECTION_PAGE_SLUG ) !== $query ) { return new WP_Error( 'abtestkit_hosted_invalid_callback' ); } return $url; } /** * Return one supported WordPress environment. * * @return string */ function abtestkit_hosted_environment() : string { $environment = function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production'; return in_array( $environment, array( 'production', 'staging', 'development', 'local' ), true ) ? $environment : 'production'; } /** * Store one exact option with autoload disabled. * * @param string $name Option name. * @param array' . esc_html__( 'abtestkit account', 'abtestkit' ) . '
'; if ( abtestkit_connected_platform_can_create_or_launch() ) { echo '' . esc_html__( 'This site can create and launch tests. Email preferences remain available in your account.', 'abtestkit' ) . '
' . esc_html__( 'This older connection has not accepted the current Terms, Privacy Policy and Data Processing Agreement. Remove it, then reconnect this site to create or launch tests. Existing running tests keep working.', 'abtestkit' ) . '
' . esc_html__( 'You normally won’t need these controls. Use them if the connection has a problem or you no longer want this account connected to the site.', 'abtestkit' ) . '
'; echo '' . esc_html__( 'The stored connection is invalid. Disconnect it locally before starting again.', 'abtestkit' ) . '
' . esc_html__( 'That one-time response cannot be reused. Return to the Account page to check the current connection or start a new request.', 'abtestkit' ) . '
'; echo '' . esc_html__( 'Check connection status', 'abtestkit' ) . '
' . esc_html__( 'Your email is verified. abtestkit is securely connecting this site.', 'abtestkit' ) . '
'; echo '' . esc_html( $retry_stopped ? __( 'Automatic recovery paused after several unsuccessful attempts. You can try again or cancel this request. Your existing tests are unaffected.', 'abtestkit' ) : __( 'abtestkit is securely checking for the completed account approval and will finish this connection automatically.', 'abtestkit' ) ) . '
'; if ( $retry_stopped ) { echo ''; } echo '' . esc_html__( 'For your WordPress tests', 'abtestkit' ) . '
'; echo '' . esc_html__( 'Connect this site to create or launch tests. If you do not have an account yet, you can create one during setup.', 'abtestkit' ) . '
' . esc_html__( 'Connect your site to your abtestkit account to receive experiment updates, view connected-site information, and access new account features as they become available.', 'abtestkit' ) . '
' . esc_html__( 'Know when a test has a result worth acting on.', 'abtestkit' ) . '
' . esc_html__( 'Stay ahead of tracking and test-health changes.', 'abtestkit' ) . '
' . esc_html__( 'Pick the updates you want after you connect.', 'abtestkit' ) . '
' . esc_html__( 'The connected service receives bounded experiment lifecycle and aggregate result data, basic platform context, and installed/active state and versions for Elementor, Woodmart, and cache plugins that abtestkit directly integrates with. It does not receive a general plugin list, page content, selectors, custom code, or customer and order identity.', 'abtestkit' ) . '
' . esc_html__( 'Connect this site to your account in a new tab.', 'abtestkit' ) . '
' . esc_html__( 'This site must use HTTPS before it can connect.', 'abtestkit' ) . '
'; } } echo ''; } else { echo ''; } } echo ''; }