'; echo '

' . esc_html__( 'Provider API Key', 'pr-vision' ) . '

'; $this->render_status_badge( $source, $status, $last_check ); $this->render_key_form( $is_const, $is_set_opt ); $this->render_test_button( $source ); echo ''; } /** * Render the read-only source + health status badge. * * @param string $source One of PRV_Key_Store::SOURCE_* constants. * @param string $api_status Last stored API status (ok/failed/unknown). * @param string $last_check ISO date of last status update. * * @return void */ private function render_status_badge( string $source, string $api_status, string $last_check ): void { echo '
'; if ( PRV_Key_Store::SOURCE_CONSTANT === $source ) { echo ''; echo '● ' . esc_html__( 'Set via wp-config (takes precedence)', 'pr-vision' ); echo ''; } elseif ( PRV_Key_Store::SOURCE_OPTION === $source ) { echo ''; echo '● ' . esc_html__( 'Set via admin', 'pr-vision' ); echo ''; } else { echo ''; echo '● ' . esc_html__( 'Not set', 'pr-vision' ); echo ''; } // Last-run health state. if ( '' !== $last_check && PRV_Key_Store::SOURCE_NONE !== $source ) { if ( 'failed' === $api_status ) { echo ' ' . esc_html__( 'Last run: failed (key may be invalid or revoked)', 'pr-vision' ) . ''; } elseif ( 'ok' === $api_status ) { echo ' ' . esc_html__( 'Last run: OK', 'pr-vision' ) . ''; } } echo '
'; } /** * Render the set/replace/remove key form. * * The password input always renders empty. When constant is set, the * input is disabled with an explanatory note. * * @param bool $is_const Whether the constant is currently defined. * @param bool $is_set_opt Whether an admin-stored (option) key exists. * * @return void */ private function render_key_form( bool $is_const, bool $is_set_opt ): void { echo '
'; echo ''; wp_nonce_field( PRV_Settings_Page::NONCE_KEY, 'prv_nonce' ); echo '
'; echo ''; // Input always renders empty — never outputs stored key. // Placeholder must not include a key-format prefix (e.g. 'sk-or-'); // even a format hint leaks provider information and will trip // write-only security assertions in the smoke suite. echo ''; if ( $is_const ) { echo '

' . esc_html__( 'PRV_OPENROUTER_API_KEY is defined in wp-config.php and takes precedence. Remove it from wp-config to manage the key here.', 'pr-vision' ) . '

'; } echo '
'; if ( ! $is_const ) { echo ''; } echo '
'; // Remove key form (only when admin option is set, not constant). if ( $is_set_opt && ! $is_const ) { echo '
'; echo ''; wp_nonce_field( PRV_Settings_Page::NONCE_KEY, 'prv_nonce' ); echo ''; echo '
'; } } /** * Render the Test key button and aria-live result area. * * Only shown when a key source is available. The test sends one cheap * probe via AJAX and reports valid/invalid without leaking the key. * * @param string $source Current key source. * * @return void */ private function render_test_button( string $source ): void { if ( PRV_Key_Store::SOURCE_NONE === $source ) { return; } $nonce = wp_create_nonce( PRV_Settings_Page::NONCE_KEY_TEST ); $ajax_url = admin_url( 'admin-ajax.php' ); echo '
'; echo ''; echo ''; echo '
'; // Inline JS — only a button wirer, no key value in JS. // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo ''; } }