dashboard = $dashboard; } /** * Registers settings-related WordPress hooks. */ public function register_hooks(): void { add_action( 'admin_init', array( $this, 'register' ) ); add_action( 'admin_menu', array( $this, 'add_menu_page' ) ); } /** * Registers the settings schema and fields. */ public function register(): void { register_setting( self::GROUP, Options::SETTINGS, array( 'type' => 'array', 'sanitize_callback' => array( $this, 'sanitize' ), 'default' => self::defaults(), ) ); add_settings_section( self::SECTION, esc_html__( 'Monitoring modules', '2ua-seo-release-guard' ), array( $this, 'render_section' ), self::PAGE ); $this->add_module_field( 'release_guard', esc_html__( 'SEO Release Guard', '2ua-seo-release-guard' ) ); $this->add_module_field( 'sitemap_watch', esc_html__( 'Sitemap & Indexability Watch', '2ua-seo-release-guard' ) ); $this->add_module_field( 'schema_watch', esc_html__( 'Schema Regression Watch', '2ua-seo-release-guard' ) ); } /** * Adds the plugin page under Settings. */ public function add_menu_page(): void { add_options_page( esc_html__( '2UA SEO Release Guard', '2ua-seo-release-guard' ), esc_html__( '2UA Release Guard', '2ua-seo-release-guard' ), Capabilities::MANAGE, self::PAGE, array( $this, 'render_page' ) ); } /** * Renders the settings page without exposing credential options. */ public function render_page(): void { if ( ! Capabilities::can_manage() ) { wp_die( esc_html__( 'You are not allowed to manage 2UA SEO Release Guard.', '2ua-seo-release-guard' ) ); } ?>

render_connection_notice(); ?> render_connection(); ?> dashboard->render( $this->connected() ); ?>

connected(); ?>

render_data_disclosure(); ?> render_connected_actions(); return; } $this->render_connect_action(); } private function connected(): bool { return Options::CONNECTION_CONNECTED === get_option( Options::CONNECTION_STATUS, '' ); } /** * Explains the exact public metadata used by cloud monitoring. */ private function render_data_disclosure(): void { ?>

ยท

'; esc_html_e( 'Disconnect before uninstalling to revoke the remote credential. Uninstall removes all local 2UA options and scheduled events.', '2ua-seo-release-guard' ); echo '

'; $this->render_connection_form( 'rotate', esc_html__( 'Rotate connection secret', '2ua-seo-release-guard' ) ); $this->render_connection_form( 'disconnect', esc_html__( 'Disconnect from 2UA', '2ua-seo-release-guard' ) ); } private function render_connection_form( string $action, string $label ): void { ?>
esc_html__( 'The site is connected to 2UA.', '2ua-seo-release-guard' ), 'rotated' => esc_html__( 'The connection secret was rotated.', '2ua-seo-release-guard' ), 'disconnected' => esc_html__( 'The site was disconnected from 2UA.', '2ua-seo-release-guard' ), 'consent_required' => esc_html__( 'Confirm the public metadata transfer before connecting.', '2ua-seo-release-guard' ), 'failed' => esc_html__( 'The 2UA connection request failed. Please try again.', '2ua-seo-release-guard' ), ); if ( isset( $messages[ $status ] ) ) { echo '

' . esc_html( $messages[ $status ] ) . '

'; } } /** * Explains the privacy-safe default state. */ public function render_section(): void { echo '

'; esc_html_e( 'Activation alone does not send data to 2UA. Cloud connection requires a separate administrator action.', '2ua-seo-release-guard' ); echo '

'; } /** * Renders one module checkbox. * * @param array{key: string, label: string} $args Field arguments. */ public function render_checkbox( array $args ): void { $settings = $this->settings(); $key = $args['key']; $name = Options::SETTINGS . '[' . $key . ']'; ?> isset( $input['release_guard'] ) ? 1 : 0, 'sitemap_watch' => isset( $input['sitemap_watch'] ) ? 1 : 0, 'schema_watch' => isset( $input['schema_watch'] ) ? 1 : 0, ); } /** * Registers one settings field. * * @param string $key Persisted module key. * @param string $label User-facing module label. */ private function add_module_field( string $key, string $label ): void { add_settings_field( 'two_ua_' . $key, $label, array( $this, 'render_checkbox' ), self::PAGE, self::SECTION, array( 'key' => $key, 'label' => $label, ) ); } /** * Returns sanitized module settings. * * @return array{release_guard: int, sitemap_watch: int, schema_watch: int} */ private function settings(): array { $value = get_option( Options::SETTINGS, self::defaults() ); return $this->sanitize( $value ); } /** * Returns privacy-safe local defaults. * * @return array{release_guard: int, sitemap_watch: int, schema_watch: int} */ private static function defaults(): array { return array( 'release_guard' => 1, 'sitemap_watch' => 1, 'schema_watch' => 1, ); } }