Domain → agreeing-provider count, sorted descending. */ public static function get_consensus_domains( int $attachment_id, int $min_providers = 2 ): array { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.InterpolatedNotPrepared $rows = $wpdb->get_results( $wpdb->prepare( "SELECT provider, top_domains FROM {$wpdb->prefix}mra_external_results WHERE attachment_id = %d", $attachment_id ), ARRAY_A ); if ( ! $rows ) { return array(); } return self::aggregate_consensus( $rows, $min_providers ); } /** * Computes consensus domains from an array of provider result rows. * * Each row must contain 'provider' (string) and 'top_domains' (JSON string * mapping domain → count). Designed to be called directly in unit tests * by passing mock row data. * * @param array> $rows Provider result rows. * @param int $min_providers Minimum provider agreement. * * @return array Domain → agreeing-provider count, sorted descending. */ public static function aggregate_consensus( array $rows, int $min_providers = 2 ): array { $domain_to_providers = array(); foreach ( $rows as $row ) { $provider_val = $row['provider'] ?? null; $provider = is_string( $provider_val ) ? $provider_val : ''; if ( '' === $provider ) { continue; } $domains_val = $row['top_domains'] ?? null; $domains_raw = is_string( $domains_val ) ? json_decode( $domains_val, true ) : null; $domains = is_array( $domains_raw ) ? $domains_raw : array(); foreach ( $domains as $domain => $count ) { if ( ! is_string( $domain ) ) { continue; } if ( ! isset( $domain_to_providers[ $domain ] ) ) { $domain_to_providers[ $domain ] = array(); } $domain_to_providers[ $domain ][ $provider ] = true; } } $consensus = array(); foreach ( $domain_to_providers as $domain => $providers_map ) { $provider_count = count( $providers_map ); if ( $provider_count >= $min_providers ) { $consensus[ $domain ] = $provider_count; } } arsort( $consensus ); return $consensus; } }