*/ public static function defaults(): array { return [ 'api_base_url' => TheDotDevAgenticBridge_Connector::OFFICIAL_API_BASE_URL, 'site_id' => '', 'site_hmac_key' => '', 'organization_id' => '', 'connection_status' => 'disconnected', 'kill_switch' => false, 'artifacts_published' => false, 'approved_claims' => [], 'excluded_content_ids' => [], 'last_known_good' => [ 'llms_txt' => '', 'agent_map' => [], 'content_ids' => [], 'published_at' => '', ], 'last_snapshot_at' => '', 'last_sync_at' => '', 'last_error' => '', 'delete_data_on_uninstall' => false, 'readiness_scan' => [ 'latest' => null, 'history' => [], ], 'local_rechecks' => ['enabled' => false, 'frequency' => 'thedotdev_agentic_bridge_weekly', 'nextRun' => 0, 'lastRun' => '', 'lastError' => '', 'lastOutcome' => 'never', 'lastFailureAt' => '', 'lockUntil' => 0, 'lockOwner' => '', 'snapshots' => []], 'crawler_access_policy' => ['active' => [], 'proposal' => null, 'audit' => []], 'content_metadata' => [ 'version' => TheDotDevAgenticBridge_Content_Metadata::VERSION, 'defaults' => TheDotDevAgenticBridge_Content_Metadata::defaults(), 'defaultsReviewedAt' => '', 'by_content_id' => [], ], 'artifact_preview_draft' => null, 'artifact_revisions' => [], 'fix_engine_enabled' => false, 'fix_engine_pending_preview' => null, 'fix_engine_audit_log' => [], 'fix_engine_schema_enabled' => false, 'fix_engine_schema_nodes' => [], 'fix_engine_meta_tags' => [], 'admin_ui' => [ 'scanning' => [ 'priorityFindingsLimit' => 3, 'trendRuns' => 8, 'allowTargetedRecheck' => true, ], 'thresholds' => [ 'strongScoreMin' => 90, 'buildingScoreMin' => 50, 'attentionScoreMax' => 49, ], 'contentTypes' => [ 'post' => true, 'page' => true, ], 'display' => [ 'inventoryPerPage' => 50, 'findingsPerPage' => 25, 'density' => 'comfortable', 'defaultOpenEvidence' => false, ], 'advanced' => [ 'showDeveloperEvidence' => true, 'showCloudTab' => true, ], ], 'onboarding_complete' => false, ]; } /** @return array */ public static function get(): array { $stored = get_option(self::OPTION_KEY, self::defaults()); if (!is_array($stored)) { $stored = []; } $merged = array_merge(self::defaults(), $stored); $normalized = self::normalize_legacy_settings($merged); if ($normalized !== $merged) { update_option(self::OPTION_KEY, $normalized, false); } return $normalized; } /** @param array $patch */ public static function update(array $patch): void { $current = self::get(); update_option(self::OPTION_KEY, array_merge($current, $patch), false); } public static function is_connected(): bool { $settings = self::get(); return ($settings['connection_status'] ?? '') === 'connected' && !empty($settings['site_id']) && !empty($settings['site_hmac_key']); } public static function kill_switch_enabled(): bool { return (bool) (self::get()['kill_switch'] ?? false); } public static function artifacts_published(): bool { return (bool) (self::get()['artifacts_published'] ?? false); } /** @param array{llms_txt?: string, agent_map?: array, content_ids?: list} $artifacts */ public static function save_last_known_good(array $artifacts): void { $content_ids = []; if (isset($artifacts['content_ids']) && is_array($artifacts['content_ids'])) { foreach ($artifacts['content_ids'] as $id) { $int_id = (int) $id; if ($int_id > 0) { $content_ids[] = $int_id; } } } self::update([ 'last_known_good' => [ 'llms_txt' => $artifacts['llms_txt'] ?? '', 'agent_map' => $artifacts['agent_map'] ?? [], 'content_ids' => array_values(array_unique($content_ids)), 'published_at' => gmdate('c'), ], 'artifacts_published' => true, ]); } public static function disconnect(): void { self::update([ 'connection_status' => 'disconnected', 'site_hmac_key' => '', 'organization_id' => '', 'last_error' => '', ]); } public static function should_delete_on_uninstall(): bool { $stored = get_option(self::OPTION_KEY, false); if (!is_array($stored)) { return false; } return self::normalize_delete_flag($stored['delete_data_on_uninstall'] ?? false); } public static function maybe_purge_on_uninstall(): void { if (!self::should_delete_on_uninstall()) { return; } self::purge_all_plugin_data(); } public static function uninstall_plugin_data(): void { if (is_multisite() && function_exists('get_sites') && function_exists('switch_to_blog') && function_exists('restore_current_blog')) { self::uninstall_multisite(); return; } self::maybe_purge_on_uninstall(); } public static function uninstall_multisite(): void { $site_ids = get_sites(['fields' => 'ids', 'number' => 0]); if (!is_array($site_ids)) { return; } foreach ($site_ids as $site_id) { $blog_id = (int) $site_id; if ($blog_id <= 0) { continue; } $switched = switch_to_blog($blog_id); if (!$switched) { continue; } try { self::maybe_purge_on_uninstall(); } finally { restore_current_blog(); } } } public static function is_valid_api_base_url(string $url): bool { if ($url === '') { return false; } $parts = wp_parse_url($url); if (!is_array($parts) || empty($parts['scheme']) || empty($parts['host'])) { return false; } return in_array(strtolower((string) $parts['scheme']), ['http', 'https'], true); } public static function purge_all_plugin_data(): void { delete_option(self::OPTION_KEY); if (class_exists('TheDotDevAgenticBridge_Outbound_Preview')) { TheDotDevAgenticBridge_Outbound_Preview::purge_all(); } } public static function normalize_delete_flag(mixed $value): bool { return $value === true; } /** @param array $settings */ private static function normalize_legacy_settings(array $settings): array { if (!array_key_exists('site_secret', $settings)) { return $settings; } $had_legacy_secret = !empty($settings['site_secret']); $has_hmac = !empty($settings['site_hmac_key']); unset($settings['site_secret']); if ($had_legacy_secret && !$has_hmac) { $settings['connection_status'] = 'disconnected'; $settings['organization_id'] = ''; } return $settings; } public static function is_onboarding_complete(): bool { return (bool) (self::get()['onboarding_complete'] ?? false); } public static function mark_onboarding_complete(): bool { $merged = array_merge(self::get(), ['onboarding_complete' => true]); update_option(self::OPTION_KEY, $merged, false); if (function_exists('wp_cache_delete')) { wp_cache_delete(self::OPTION_KEY, 'options'); wp_cache_delete('alloptions', 'options'); } $stored = get_option(self::OPTION_KEY, []); if (!is_array($stored)) { return false; } return !empty($stored['onboarding_complete']); } }