settings_capability = $settings_capability; } /** * Register hooks to add the connected services page to the settings tabs * and handle license-related notices. * * @since 1.xx.x * * @return void */ public function add_page() { // Add Connected Services tab to settings page. add_filter( 'edac_filter_settings_tab_items', [ $this, 'add_connected_services_tab' ] ); // Render Connected Services tab content when active. add_action( 'edac_settings_tab_content', [ $this, 'maybe_render_tab_content' ] ); // Inject degraded-state messaging above the Pro license form when Pro renders the license tab. add_action( 'edacp_license_page_before_form', [ $this, 'render_pro_license_degraded_notice' ] ); // Register admin notice display with higher priority than default. add_action( 'in_admin_header', [ $this, 'register_admin_notices' ], 1001 ); } /** * Add Connected Services tab to settings tabs array. * * @since 1.xx.x * * @param array $tabs Array of registered settings tabs. * * @return array Modified tabs array with Connected Services tab added. */ public function add_connected_services_tab( $tabs ) { // Free plugin no longer owns the Pro License tab. return $tabs; } /** * Conditionally render the tab content if the current tab is 'connected-services'. * * @since 1.xx.x * * @param string $settings_tab The current active settings tab. * * @return void */ public function maybe_render_tab_content( $settings_tab ) { if ( 'connected-services' === $settings_tab ) { $this->render_page(); } } /** * Register the admin notices function to display license-related messages. * * @since 1.xx.x * * @return void */ public function register_admin_notices() { add_action( 'admin_notices', [ $this, 'admin_notices' ] ); } /** * Render the connected services settings page content. * * @since 1.xx.x * * @return void */ public function render_page() { $license_context = $this->get_license_context(); $is_pro = $license_context['is_pro']; $status = $license_context['status']; $license = get_option( 'edacp_license_key' ); $is_connected = $license_context['is_connected']; $is_registered = $license_context['is_registered']; $degraded_context = $this->get_degraded_notice_context( $license_context ); $degraded_notice = $this->get_degraded_notice_message( $license_context ); $dashboard_link = 'my.equalizedigital.com'; $create_account_link = '' . esc_html__( 'create a free account', 'accessibility-checker' ) . ''; ?>

render_degraded_connected_state( $dashboard_link ); ?>

' . esc_html__( 'Renew your license', 'accessibility-checker' ) . ''; printf( /* translators: %s: renew license link */ wp_kses_post( __( 'Your license has expired and this site is still connected. %s to restore full access, or disconnect the site above.', 'accessibility-checker' ) ), wp_kses_post( $renew_link ) ); ?>

get_license_context(); $degraded_notice = $this->get_degraded_notice_message( $license_context ); if ( empty( $degraded_notice ) ) { return; } ?>

$has_pro_plugin, 'is_pro' => $is_pro, 'status' => $status, 'is_connected' => $is_connected, 'is_registered' => $is_registered, 'fallback_active' => $fallback_active, ]; } /** * Resolve which error option and settings tab should be used for notices. * * @return array{error:string,tab:string} */ private function get_error_context(): array { $license_context = $this->get_license_context(); return self::resolve_error_context( $license_context['is_pro'] ); } /** * Resolve notice context from effective license authority. * * @param bool $is_pro Whether Pro is currently authoritative. * @return array{error:string,tab:string} */ private static function resolve_error_context( bool $is_pro ): array { return [ 'error' => (string) get_option( $is_pro ? 'edacp_license_error' : 'edac_license_error', '' ), 'tab' => $is_pro ? 'license' : 'accessibility-reports', ]; } /** * Resolve whether to show a Pro-to-Free degraded-state notice. * * @param bool $has_pro_plugin Whether Pro plugin is installed. * @param bool $is_pro Whether Pro is currently authoritative. * @param string $pro_status Current Pro status option. * @param string $effective_status Effective authority status. * @param bool $is_connected Whether UI currently considers site connected. * @param bool $fallback_active Whether Pro has degraded to fallback mode. * @return array{show:bool,mode:string} */ private static function resolve_degraded_notice_context( bool $has_pro_plugin, bool $is_pro, string $pro_status, string $effective_status, bool $is_connected, bool $fallback_active = false ): array { // Show degraded notice when: // - Pro plugin exists AND // - Pro is not currently active as authority AND // - Pro status is set but not valid AND // - Either: Free is valid OR Pro fallback mode is active. $show = $has_pro_plugin && ! $is_pro && '' !== $pro_status && 'valid' !== $pro_status && ( 'valid' === $effective_status || $fallback_active ); if ( ! $show ) { return [ 'show' => false, 'mode' => '', ]; } return [ 'show' => true, 'mode' => $is_connected ? 'connected' : 'reconnect', ]; } /** * Get degraded-state notice message when Pro is invalid and Free is active. * * @param array{has_pro_plugin:bool,is_pro:bool,status:string,is_connected:bool} $license_context Effective license context. * @return string|null */ private function get_degraded_notice_message( array $license_context ): ?string { $notice_context = $this->get_degraded_notice_context( $license_context ); if ( ! $notice_context['show'] ) { return null; } if ( 'connected' === $notice_context['mode'] ) { return __( 'Your Pro license is no longer valid. Email reports remain connected as Free email reports. Renew your Pro license to restore Pro-only features.', 'accessibility-checker' ); } return __( 'Your Pro license is no longer valid. This site is using a valid Free license, but email reports are not currently connected. Connect this site from the Free License section to resume Free email reports.', 'accessibility-checker' ); } /** * Display admin notices when the license added is invalid or expired. * * @since 1.xx.x * * @return void */ public function admin_notices() { $error_context = $this->get_error_context(); $error = $error_context['error']; $license_url = admin_url( 'admin.php?page=accessibility_checker_settings&tab=' . $error_context['tab'] ); $message = null; if ( $error ) { $message = $this->get_error_message( $error, $license_url ); } if ( isset( $message ) ) { printf( '

%s

', wp_kses_post( $message ) ); } } /** * Get appropriate error message based on the license error code. * * @since 1.xx.x * * @param string $error_code The license error code. * @param string $license_url URL to the license settings page. * * @return string The formatted error message. */ private function get_error_message( $error_code, $license_url ) { switch ( $error_code ) { case 'expired': $renew_link = '' . esc_html__( 'Please renew your license', 'accessibility-checker' ) . ''; return sprintf( /* translators: %1$s: item name, %2$s: item name, %3$s: renew license link */ __( 'Your %1$s license has expired. %3$s to continue accessing additional features and services for %2$s.', 'accessibility-checker' ), Connector::PRODUCT_NAME, Connector::PRODUCT_NAME, wp_kses_post( $renew_link ) ); case 'disabled': case 'revoked': return sprintf( /* translators: %s: item name */ __( 'Your %s license key has been disabled. Please contact our support team if you believe this is an error or would like to continue accessing additional features.', 'accessibility-checker' ), Connector::PRODUCT_NAME ); case 'missing': return sprintf( /* translators: %1$s: item name, %2$s: license url, %3$s: item name */ __( 'The license key for %1$s appears to be invalid. Please check your license key to access additional accessibility features and services for %3$s.', 'accessibility-checker' ), Connector::PRODUCT_NAME, $license_url, Connector::PRODUCT_NAME ); case 'invalid': case 'site_inactive': return sprintf( /* translators: %s: item name */ __( 'This license key for %s is not active for this site. Please activate it to access additional features on this website.', 'accessibility-checker' ), Connector::PRODUCT_NAME ); case 'item_name_mismatch': return sprintf( /* translators: %s: the plugins item name */ __( 'This license key does not appear to be valid for %s. Please verify you\'ve entered the correct license key.', 'accessibility-checker' ), Connector::PRODUCT_NAME ); case 'no_activations_left': return sprintf( /* translators: %s: the plugins item name */ __( 'Your %s license key has reached its site activation limit. You can upgrade your license or deactivate it on another site to use the additional features here.', 'accessibility-checker' ), Connector::PRODUCT_NAME ); default: return sprintf( /* translators: %s: the plugins item name */ __( 'There was an issue validating your %s license key. Please try again or contact our support team if the problem persists.', 'accessibility-checker' ), Connector::PRODUCT_NAME ); } } }