' . esc_html__( 'Settings', 'sr-anywhere' ) . '' ); return $links; } /** * The page's address. * * @return string */ public static function url() { return admin_url( 'options-general.php?page=' . self::SLUG ); } /** * Loads the SR Anywhere look on this page only (decision 0015). * * @param string $hook The admin page's hook. */ public static function assets( $hook ) { if ( 'settings_page_' . self::SLUG !== $hook ) { return; } Block::register_styles(); wp_enqueue_style( 'sranywhere-admin' ); wp_enqueue_script( 'sranywhere-admin', SRANYWHERE_URL . 'assets/admin.js', array(), SRANYWHERE_VERSION, array( 'in_footer' => true ) ); } /** * Prints the page. */ public static function page() { if ( ! current_user_can( 'manage_options' ) ) { return; } $connection = Connection::get(); $state = $connection ? $connection->state() : Connection::DISCONNECTED; $notice = get_transient( self::notice_key() ); delete_transient( self::notice_key() ); ?>


connected_by(); $links = array(); if ( ! is_wp_error( $account ) && isset( $account['links'] ) && is_array( $account['links'] ) ) { $links = array_filter( $account['links'], array( Config::class, 'is_portal_url' ) ); } ?>

site() ) ); ?>

align="full"', 'offset="header"' ); ?>

__( 'The saved connection cannot be read any more (the site\'s security keys changed). Connect again.', 'sr-anywhere' ), Connection::LEFT_ACCOUNT => __( 'SR Anywhere ended this connection: it was removed there, or the person who made it left the account. Connect again.', 'sr-anywhere' ), Connection::EXPIRED => __( 'The connection expired. Connect again.', 'sr-anywhere' ), ); return $messages[ $state ] ?? ''; } /** * "Copy diagnostics" (decision 0013): what the site runs and the connection's state, for SR Anywhere's Help. Shown as * it is copied, so the person sees what they send. */ private static function diagnostics_card() { $text = Health::diagnostics(); ?>

' . esc_html__( 'Tools → Site Health', 'sr-anywhere' ) . '' ); ?>

site() ) ); ?>

  1. ' . esc_html__( 'Settings → Connections → WordPress', 'sr-anywhere' ) . '' ); ?>
= 100 ? 'full' : ( $share >= 70 ? 'high' : '' ); ?>
style="--sra-p:%">
__( 'Live site', 'sr-anywhere' ), 'staging' => __( 'Staging', 'sr-anywhere' ), 'development' => __( 'Development', 'sr-anywhere' ), 'local' => __( 'Local', 'sr-anywhere' ), ); return $labels[ $type ] ?? $labels['production']; } /** * Connects with the pasted key. */ public static function handle_connect() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'sr-anywhere' ), 403 ); } check_admin_referer( 'sranywhere_connect' ); $token = isset( $_POST['sranywhere_token'] ) ? sanitize_text_field( wp_unslash( $_POST['sranywhere_token'] ) ) : ''; $result = Connection::connect_with_key( $token ); if ( is_wp_error( $result ) ) { self::notice( 'error', $result->get_error_message() ); } else { self::notice( 'success', __( 'Connected. You can now place your modules with the SR Anywhere block.', 'sr-anywhere' ) ); } wp_safe_redirect( self::url() ); exit; } /** * Starts the connection by OAuth (Dirk, OAuth.php): sends the administrator to SR Anywhere's consent page. */ public static function handle_oauth_start() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'sr-anywhere' ), 403 ); } check_admin_referer( 'sranywhere_oauth_start' ); $url = OAuth::start_url(); if ( is_wp_error( $url ) ) { self::notice( 'error', $url->get_error_message() ); wp_safe_redirect( self::url() ); exit; } wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- the service's own consent page, built from the fixed API host (Config). exit; } /** * Disconnects. Placed modules keep printing (decision 0002). */ public static function handle_disconnect() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'sr-anywhere' ), 403 ); } check_admin_referer( 'sranywhere_disconnect' ); $connection = Connection::get(); $by_key = ! $connection || ! $connection->is_oauth(); Connection::disconnect(); self::notice( 'success', $by_key ? __( 'Disconnected. Your placed modules stay on your pages. To end the key in SR Anywhere as well, remove it there in Settings → Connections.', 'sr-anywhere' ) : __( 'Disconnected, here and in SR Anywhere. Your placed modules stay on your pages.', 'sr-anywhere' ) ); wp_safe_redirect( self::url() ); exit; } /** * Confirms that a copied-looking site is the same site, moved. */ public static function handle_move() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'sr-anywhere' ), 403 ); } check_admin_referer( 'sranywhere_move' ); Connection::confirm_moved_site(); wp_safe_redirect( self::url() ); exit; } /** * Whether the classic Slider Revolution plugin is active (plan §9). * * @return bool */ public static function classic_active() { return defined( 'RS_REVISION' ) || class_exists( 'RevSliderFront', false ); } /** * Whether the active classic plugin is older than the core that starts modules added after its init * (`SR7.F.addModule`, the core's answer of 2026-10-07; findings §14). Its modules and ours may then not both start on * one page. * * @return bool */ public static function classic_outdated() { if ( ! self::classic_active() ) { return false; } return ! defined( 'RS_REVISION' ) || version_compare( (string) RS_REVISION, self::CLASSIC_FIXED, '<' ); } /** * Keeps a notice for the next view of the page, for this user only. * * @param string $type `success` or `error`. * @param string $text The text. */ private static function notice( $type, $text ) { set_transient( self::notice_key(), array( 'type' => $type, 'text' => $text, ), MINUTE_IN_SECONDS ); } /** * The notice's transient for the current user. * * @return string */ private static function notice_key() { return 'sranywhere_notice_' . get_current_user_id(); } }