$settings */ public function update( array $settings ): bool { // Merge with CURRENT stored values (not defaults) — same merge-safe // pattern as the other repositories. $merged = wp_parse_args( $settings, $this->get() ); return update_option( self::OPTION_NAME, array( 'llms_enabled' => (bool) $merged['llms_enabled'], 'llms_title' => sanitize_text_field( (string) $merged['llms_title'] ), 'llms_description' => sanitize_textarea_field( (string) $merged['llms_description'] ), 'llms_intro' => sanitize_textarea_field( (string) $merged['llms_intro'] ), // Pro-only field (M57) — stored here regardless so the value // survives a license lapsing and reactivating (soft-degradation // doctrine); the Tab/Builder gate WHETHER it is read/rendered. 'llms_footer' => sanitize_textarea_field( (string) $merged['llms_footer'] ), // M61 — explicit opt-in: llms.txt is noindex'd by default (own // text digest for LLM crawlers, not a search result); this is a // conscious "yes, index it too" decision, same doctrine as // llms_enabled itself being opt-in. 'llms_sitemap_opt_in' => (bool) $merged['llms_sitemap_opt_in'], 'noai' => (bool) $merged['noai'], ) ); } /** * @return array{llms_enabled: bool, llms_title: string, llms_description: string, llms_intro: string, llms_footer: string, llms_sitemap_opt_in: bool, noai: bool} */ private static function defaults(): array { return array( 'llms_enabled' => false, 'llms_title' => '', 'llms_description' => '', 'llms_intro' => '', 'llms_footer' => '', 'llms_sitemap_opt_in' => false, 'noai' => false, ); } }