*/ public function get(): array { $stored = get_option( self::OPTION_NAME, array() ); return wp_parse_args( is_array( $stored ) ? $stored : array(), self::defaults() ); } /** * @param array $settings */ public function update( array $settings ): bool { $sanitized = self::sanitize( wp_parse_args( $settings, $this->get() ) ); return update_option( self::OPTION_NAME, $sanitized ); } /** * @return array */ private static function defaults(): array { return array( 'gsc_verification_code' => '', 'bing_verification_code' => '', 'yandex_verification_code' => '', 'pinterest_verification_code' => '', 'baidu_verification_code' => '', 'facebook_verification_code' => '', 'gtm_container_id' => '', 'ga_measurement_id' => '', 'hotjar_site_id' => '', 'exclude_admins' => false, ); } /** * @param array $settings * * @return array */ private static function sanitize( array $settings ): array { return array( 'gsc_verification_code' => self::sanitize_verification_token( (string) $settings['gsc_verification_code'] ), 'bing_verification_code' => self::sanitize_verification_token( (string) $settings['bing_verification_code'] ), 'yandex_verification_code' => self::sanitize_verification_token( (string) $settings['yandex_verification_code'] ), 'pinterest_verification_code' => self::sanitize_verification_token( (string) $settings['pinterest_verification_code'] ), 'baidu_verification_code' => self::sanitize_verification_token( (string) $settings['baidu_verification_code'] ), 'facebook_verification_code' => self::sanitize_verification_token( (string) $settings['facebook_verification_code'] ), 'gtm_container_id' => self::sanitize_gtm_id( (string) $settings['gtm_container_id'] ), 'ga_measurement_id' => self::sanitize_ga_id( (string) $settings['ga_measurement_id'] ), 'hotjar_site_id' => self::sanitize_hotjar_id( (string) $settings['hotjar_site_id'] ), 'exclude_admins' => (bool) $settings['exclude_admins'], ); } /** * Search-engine / social ownership-verification meta tags, as * `option key => meta name`. Every provider here documents a * `` tag as its verification method, * so one shared token sanitizer covers all of them. * * @return array */ public static function verification_meta_names(): array { return array( 'gsc_verification_code' => 'google-site-verification', 'bing_verification_code' => 'msvalidate.01', 'yandex_verification_code' => 'yandex-verification', 'pinterest_verification_code' => 'p:domain_verify', 'baidu_verification_code' => 'baidu-site-verification', 'facebook_verification_code' => 'facebook-domain-verification', ); } /** * Verification tokens are opaque, provider-issued strings — never markup * and never code. Two deliberate steps: * * 1. Every provider hands the user a whole `` tag to copy, and * users paste exactly that, so pull `content="…"` out of it first. * 2. Reduce to the character set these tokens are actually built from * (base64url / hex / alphanumeric). This is a whitelist, not a * blacklist: anything outside it is dropped rather than escaped. * * The per-provider format is deliberately NOT enforced beyond that — * providers change token shapes without notice, and a regex mismatch * would silently blank a valid code the user just pasted. */ private static function sanitize_verification_token( string $value ): string { $value = trim( $value ); if ( str_contains( $value, '