This commit is contained in:
Javier Casares 2026-06-03 06:29:56 +00:00
commit 98b1cf0f3b
17 changed files with 2968 additions and 1313 deletions

View file

@ -7,6 +7,8 @@
namespace MediaRightsAudit\Admin;
use MediaRightsAudit\External\HostnameFilter;
/**
* Registers and renders the hidden attachment detail admin page.
*
@ -231,6 +233,10 @@ class AttachmentDetailPage {
/**
* Fetches and renders the external scan results for a given attachment.
*
* After rendering all per-provider sections, aggregates top_domains across
* all providers and passes them to render_domain_classification() for a
* consolidated view grouped by alert / other / ignored status.
*
* @param int $attachment_id Attachment post ID.
*
* @return void
@ -241,7 +247,7 @@ class AttachmentDetailPage {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery
$rows = $wpdb->get_results(
$wpdb->prepare(
"SELECT provider, match_count, raw_response, created_at
"SELECT provider, match_count, top_domains, raw_response, created_at
FROM {$wpdb->prefix}mra_external_results
WHERE attachment_id = %d
ORDER BY provider ASC",
@ -261,6 +267,8 @@ class AttachmentDetailPage {
'picdefense' => 'PicDefense',
);
$merged_domains = array();
foreach ( $rows as $row ) {
if ( ! is_array( $row ) ) {
continue;
@ -273,6 +281,9 @@ class AttachmentDetailPage {
$match_count = is_numeric( $mc_val ) ? (int) $mc_val : 0;
$at_val = $row['created_at'] ?? null;
$scanned_at = is_string( $at_val ) ? $at_val : '';
$td_val = $row['top_domains'] ?? null;
$td_raw = is_string( $td_val ) ? json_decode( $td_val, true ) : null;
$domains = is_array( $td_raw ) ? $td_raw : array();
$rr_val = $row['raw_response'] ?? null;
$raw = null;
if ( is_string( $rr_val ) && '' !== $rr_val ) {
@ -280,6 +291,19 @@ class AttachmentDetailPage {
$raw = is_array( $decoded ) ? $decoded : null;
}
// Accumulate top_domains across all providers.
foreach ( $domains as $domain => $count ) {
if ( ! is_string( $domain ) ) {
continue;
}
$c = is_numeric( $count ) ? (int) $count : 0;
if ( isset( $merged_domains[ $domain ] ) ) {
$merged_domains[ $domain ] += $c;
} else {
$merged_domains[ $domain ] = $c;
}
}
echo '<h3>';
echo esc_html( $name );
echo ' &mdash; ';
@ -311,6 +335,87 @@ class AttachmentDetailPage {
}
}
}
// Render consolidated domain classification section.
if ( ! empty( $merged_domains ) ) {
$this->render_domain_classification( $merged_domains );
}
}
/**
* Renders a domain classification summary grouped into Alert, Other, and Ignored sections.
*
* Each section is rendered only when non-empty. Alert domains are shown with
* a warning note about copyright risk.
*
* @param array<string, int> $domains Map of domain => total occurrence count.
*
* @return void
*/
private function render_domain_classification( array $domains ): void {
$alert_domains = array();
$other_domains = array();
$ignored_domains = array();
foreach ( $domains as $domain => $count ) {
$classification = HostnameFilter::classify( $domain );
if ( 'alert' === $classification ) {
$alert_domains[ $domain ] = $count;
} elseif ( 'ignored' === $classification ) {
$ignored_domains[ $domain ] = $count;
} else {
$other_domains[ $domain ] = $count;
}
}
if ( ! empty( $alert_domains ) ) {
echo '<h3>' . esc_html__( 'Alert Domains', 'robotstxt-mediaaudit' ) . '</h3>';
echo '<p class="description">' . esc_html__( 'These domains are associated with copyright-protected content and may indicate a copyright risk.', 'robotstxt-mediaaudit' ) . '</p>';
echo '<table class="widefat mra-detail-table">';
echo '<thead><tr>';
echo '<th>' . esc_html__( 'Domain', 'robotstxt-mediaaudit' ) . '</th>';
echo '<th>' . esc_html__( 'Occurrences', 'robotstxt-mediaaudit' ) . '</th>';
echo '</tr></thead><tbody>';
foreach ( $alert_domains as $domain => $count ) {
echo '<tr>';
echo '<td>' . esc_html( $domain ) . '</td>';
echo '<td>' . esc_html( (string) $count ) . '</td>';
echo '</tr>';
}
echo '</tbody></table>';
}
if ( ! empty( $other_domains ) ) {
echo '<h3>' . esc_html__( 'Other Domains', 'robotstxt-mediaaudit' ) . '</h3>';
echo '<table class="widefat mra-detail-table">';
echo '<thead><tr>';
echo '<th>' . esc_html__( 'Domain', 'robotstxt-mediaaudit' ) . '</th>';
echo '<th>' . esc_html__( 'Occurrences', 'robotstxt-mediaaudit' ) . '</th>';
echo '</tr></thead><tbody>';
foreach ( $other_domains as $domain => $count ) {
echo '<tr>';
echo '<td>' . esc_html( $domain ) . '</td>';
echo '<td>' . esc_html( (string) $count ) . '</td>';
echo '</tr>';
}
echo '</tbody></table>';
}
if ( ! empty( $ignored_domains ) ) {
echo '<h3>' . esc_html__( 'Ignored Domains', 'robotstxt-mediaaudit' ) . '</h3>';
echo '<table class="widefat mra-detail-table">';
echo '<thead><tr>';
echo '<th>' . esc_html__( 'Domain', 'robotstxt-mediaaudit' ) . '</th>';
echo '<th>' . esc_html__( 'Occurrences', 'robotstxt-mediaaudit' ) . '</th>';
echo '</tr></thead><tbody>';
foreach ( $ignored_domains as $domain => $count ) {
echo '<tr>';
echo '<td>' . esc_html( $domain ) . '</td>';
echo '<td>' . esc_html( (string) $count ) . '</td>';
echo '</tr>';
}
echo '</tbody></table>';
}
}
/**