v1.0.0
This commit is contained in:
commit
6708bbb67f
43 changed files with 8342 additions and 0 deletions
99
includes/External/ResultsConsolidator.php
vendored
Normal file
99
includes/External/ResultsConsolidator.php
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* Cross-provider result consolidation.
|
||||
*
|
||||
* @package MediaRightsAudit\External
|
||||
*/
|
||||
|
||||
namespace MediaRightsAudit\External;
|
||||
|
||||
/**
|
||||
* Aggregates external scan results across multiple providers to surface
|
||||
* domains that appear in more than one provider's findings (consensus signals).
|
||||
*
|
||||
* Consensus detection provides stronger copyright-risk signals: a domain
|
||||
* independently found by both Google Vision and TinEye is more likely to be
|
||||
* a genuine unauthorised copy than one found by a single provider.
|
||||
*/
|
||||
class ResultsConsolidator {
|
||||
|
||||
/**
|
||||
* Returns domains confirmed by results from at least $min_providers distinct providers.
|
||||
*
|
||||
* Reads top_domains JSON stored in mra_external_results for the given attachment
|
||||
* and counts how many providers reported each domain. Only domains meeting the
|
||||
* threshold are returned, sorted descending by provider-agreement count.
|
||||
*
|
||||
* @param int $attachment_id WordPress attachment ID.
|
||||
* @param int $min_providers Minimum number of providers that must agree (default: 2).
|
||||
*
|
||||
* @return array<string, int> 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<int, array<string, mixed>> $rows Provider result rows.
|
||||
* @param int $min_providers Minimum provider agreement.
|
||||
*
|
||||
* @return array<string, int> 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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue