|mixed> $snapshots * @return array{findings:list>,issueCount:int,rejected:int,truncated:bool,networkRequests:int,writesPerformed:int} */ public static function assess(array $snapshots, int $site_id): array { if ($site_id <= 0 || count($snapshots) > self::MAX_SNAPSHOTS) { return self::unavailable_result($snapshots, $site_id); } $safe = []; $rejected = 0; $seen_page_ids = []; foreach ($snapshots as $row) { if (!is_array($row) || !self::belongs_to_site($row, $site_id) || self::duplicate_page_id($row, $seen_page_ids)) { ++$rejected; continue; } $normalized = self::snapshot($row); if ($normalized === null) { ++$rejected; continue; } $seen_page_ids[$normalized['pageId']] = true; $safe[] = $normalized; } usort($safe, static fn(array $a, array $b): int => [$a['path'], $a['pageId']] <=> [$b['path'], $b['pageId']]); $title_counts = self::counts($safe, 'title'); $meta_counts = self::counts($safe, 'metaDescription'); $findings = []; foreach ($safe as $page) { $base = self::finding_base($site_id, $page); if ($page['excluded']) { $findings[] = $base + self::finding('scope', self::NOT_APPLICABLE, 'Excluded from the supplied snapshot scope.', 'No full-site coverage claim is made.'); continue; } if ($page['snapshotSource'] === 'unknown' || $page['snapshotTime'] === '') { $findings[] = $base + self::finding('snapshot', self::UNKNOWN, 'Snapshot source or time is unavailable.', 'No current-state claim is made.'); continue; } self::append_page_findings($findings, $base, $page, $title_counts, $meta_counts); } usort($findings, static fn(array $left, array $right): int => [$left['path'], $left['check'], $left['status']] <=> [$right['path'], $right['check'], $right['status']]); return [ 'findings' => $findings, 'issueCount' => self::issue_count($findings), 'rejected' => $rejected, 'truncated' => false, 'networkRequests' => 0, 'writesPerformed' => 0, ]; } /** @return list> */ public static function synthetic_visual_qa_snapshots(int $site_id): array { return [ [ 'siteId' => $site_id, 'pageId' => 901, 'path' => '/very-long-local-content-health-example-page', 'pageType' => 'page', 'status' => 'publish', 'title' => 'Local duplicate title', 'metaDescription' => '', 'canonical' => '', 'robots' => 'index', 'headings' => [['level' => 1], ['level' => 3]], 'imageMissingAlt' => 1, 'decorativeImages' => 2, 'contentWords' => 12, 'snapshotSource' => 'synthetic_local_fixture', 'snapshotTime' => '2026-08-24T12:00:00Z', 'scope' => 'indexable', 'exclusions' => [], 'siteOrigin' => 'https://example.invalid', ], [ 'siteId' => $site_id, 'pageId' => 902, 'path' => '/excluded-local-example', 'pageType' => 'page', 'status' => 'publish', 'title' => 'Local duplicate title', 'metaDescription' => 'Shared sample', 'canonical' => 'https://example.invalid/excluded-local-example', 'robots' => 'noindex', 'headings' => [['level' => 1]], 'imageMissingAlt' => 0, 'decorativeImages' => 1, 'contentWords' => 90, 'snapshotSource' => 'synthetic_local_fixture', 'snapshotTime' => '2026-08-24T12:00:00Z', 'scope' => 'excluded', 'exclusions' => ['synthetic exclusion'], 'siteOrigin' => 'https://example.invalid', ], [ 'siteId' => $site_id, 'pageId' => 903, 'path' => '/unknown-local-example', 'pageType' => 'page', 'status' => 'publish', 'title' => 'Unknown sample', 'metaDescription' => '', 'canonical' => '', 'robots' => '', 'headings' => [['level' => 1]], 'imageMissingAlt' => 0, 'decorativeImages' => 0, 'contentWords' => 80, 'snapshotSource' => 'unknown', 'snapshotTime' => '', 'scope' => 'unknown', 'exclusions' => [], 'siteOrigin' => 'https://example.invalid', ], ]; } /** @return array|null */ private static function snapshot(array $row): ?array { $path = self::safe_string($row['path'] ?? ''); $title = self::safe_string($row['title'] ?? ''); $meta_description = self::safe_string($row['metaDescription'] ?? ''); $canonical = self::safe_string($row['canonical'] ?? '', 512); $origin = is_string($row['siteOrigin'] ?? null) ? rtrim($row['siteOrigin'], '/') : ''; if (!self::valid_snapshot_scalars($row, $path, $title, $meta_description, $canonical, $origin)) { return null; } $headings = self::headings($row['headings']); $exclusions = self::exclusions($row['exclusions'] ?? null); if ($headings === null || $exclusions === null) { return null; } $source = self::source($row['snapshotSource'] ?? null); $scope = self::scope($row['scope'] ?? null); $robots = is_string($row['robots'] ?? null) ? $row['robots'] : ''; return [ 'pageId' => $row['pageId'], 'path' => $path, 'title' => self::key($title), 'metaDescription' => self::key($meta_description), 'canonical' => $canonical, 'canonicalKnown' => !array_key_exists('canonicalKnown', $row) || $row['canonicalKnown'] === true, 'headings' => $headings, 'imageMissingAlt' => max(0, min(100, $row['imageMissingAlt'])), 'contentWords' => max(0, min(100000, $row['contentWords'])), 'snapshotSource' => $source, 'snapshotTime' => self::snapshot_time($row['snapshotTime'] ?? null), 'scope' => $scope, 'exclusions' => $exclusions, 'excluded' => $scope === 'excluded', 'noindex' => str_contains(strtolower($robots), 'noindex'), 'siteOrigin' => $origin, ]; } private static function unavailable_result(array $snapshots, int $site_id): array { return [ 'findings' => [[ 'siteId' => $site_id, 'pageId' => 0, 'path' => '', 'snapshotSource' => 'unknown', 'snapshotTime' => '', 'scope' => 'unknown', 'exclusions' => [], 'nextAction' => 'Provide a complete bounded local snapshot before review.', 'check' => 'snapshot scope', 'status' => self::UNKNOWN, 'evidence' => 'The supplied snapshot set is unavailable or truncated.', 'uncertainty' => 'No page-level or full-site coverage claim is made.', ]], 'issueCount' => 0, 'rejected' => count($snapshots), 'truncated' => count($snapshots) > self::MAX_SNAPSHOTS, 'networkRequests' => 0, 'writesPerformed' => 0, ]; } private static function finding_base(int $site_id, array $page): array { return [ 'siteId' => $site_id, 'pageId' => $page['pageId'], 'path' => $page['path'], 'snapshotSource' => $page['snapshotSource'], 'snapshotTime' => $page['snapshotTime'], 'scope' => $page['scope'], 'exclusions' => $page['exclusions'], 'nextAction' => 'Open and review locally', ]; } private static function finding(string $check, string $status, string $evidence, string $uncertainty): array { return [ 'check' => $check, 'status' => $status, 'evidence' => $evidence, 'uncertainty' => $uncertainty, ]; } private static function safe_string(mixed $value, int $maximum = 256): ?string { if (!is_string($value)) { return null; } if (strlen($value) > $maximum || preg_match('/[<>\x00-\x1F]/', $value)) { return null; } return trim(preg_replace('/\s+/u', ' ', $value) ?? ''); } private static function valid_snapshot_scalars(array $row, ?string $path, ?string $title, ?string $meta_description, ?string $canonical, string $origin): bool { return $path !== null && str_starts_with($path, '/') && !str_contains($path, '?') && !str_contains($path, '#') && $title !== null && $meta_description !== null && $canonical !== null && (!array_key_exists('canonicalKnown', $row) || is_bool($row['canonicalKnown'])) && is_array($row['headings'] ?? null) && is_int($row['imageMissingAlt'] ?? null) && is_int($row['contentWords'] ?? null) && ($origin === '' || (bool) filter_var($origin, FILTER_VALIDATE_URL)); } private static function belongs_to_site(array $row, int $site_id): bool { return (int) ($row['siteId'] ?? 0) === $site_id && is_int($row['pageId'] ?? null); } private static function duplicate_page_id(array $row, array $seen_page_ids): bool { return isset($seen_page_ids[(int) $row['pageId']]); } private static function headings(array $raw_headings): ?array { $headings = []; foreach ($raw_headings as $heading) { if (!is_array($heading) || !is_int($heading['level'] ?? null) || $heading['level'] < 1 || $heading['level'] > 6) { return null; } $headings[] = ['level' => $heading['level']]; } return $headings; } private static function exclusions(mixed $raw_exclusions): ?array { if (!is_array($raw_exclusions)) { return null; } $exclusions = []; foreach ($raw_exclusions as $exclusion) { $safe = self::safe_string($exclusion, 80); if ($safe === null) { return null; } $exclusions[] = $safe; if (count($exclusions) > 5) { return null; } } return $exclusions; } private static function source(mixed $raw_source): string { if (!is_string($raw_source)) { return 'unknown'; } $source = sanitize_key($raw_source); if (!in_array($source, ['local_snapshot', 'local_post_snapshot', 'synthetic_local_fixture'], true)) { return 'unknown'; } return $source; } private static function scope(mixed $raw_scope): string { if (!is_string($raw_scope)) { return 'unknown'; } if (!in_array($raw_scope, ['indexable', 'excluded', 'unknown'], true)) { return 'unknown'; } return $raw_scope; } private static function snapshot_time(mixed $raw_time): string { if (!is_string($raw_time)) { return ''; } if (preg_match('/^\d{4}-\d{2}-\d{2}T/', $raw_time) !== 1) { return ''; } return $raw_time; } private static function append_page_findings(array &$findings, array $base, array $page, array $title_counts, array $meta_counts): void { if (self::stale($page['snapshotTime'])) { $findings[] = $base + self::finding('freshness', self::REVIEW_NEEDED, 'The supplied snapshot is stale.', 'Review the current page manually.'); } self::append_duplicate_finding($findings, $base, $page['title'], $title_counts, 'title', 'Title'); self::append_duplicate_finding($findings, $base, $page['metaDescription'], $meta_counts, 'meta description', 'Meta description'); self::append_heading_finding($findings, $base, $page['headings']); if ($page['imageMissingAlt'] > 0) { $findings[] = $base + self::finding('image alt', self::CONFIRMED_ISSUE, 'Non-decorative images are missing supplied alt text.', 'Decorative images are not counted.'); } if ($page['contentWords'] < 40) { $findings[] = $base + self::finding('main content', self::REVIEW_NEEDED, 'Supplied main-content summary is very thin.', 'This is a review signal, not a quality judgement.'); } if (!$page['canonicalKnown']) { $findings[] = $base + self::finding('canonical', self::UNKNOWN, 'Canonical markup was not inspected by this local post snapshot.', 'Review the rendered page manually.'); } elseif ($page['canonical'] === '') { $findings[] = $base + self::finding('canonical', self::CONFIRMED_ISSUE, 'Canonical is missing in the supplied snapshot.', 'Local snapshot evidence only.'); } elseif (!self::same_site_canonical($page['canonical'], $page['siteOrigin'])) { $findings[] = $base + self::finding('canonical', self::REVIEW_NEEDED, 'Canonical needs same-site manual review.', 'No canonical change is proposed.'); } if ($page['noindex'] && $page['scope'] === 'indexable') { $findings[] = $base + self::finding('indexability', self::REVIEW_NEEDED, 'Supplied noindex value conflicts with the supplied indexable scope.', 'Review scope and robots manually.'); } } private static function append_duplicate_finding(array &$findings, array $base, string $value, array $counts, string $check, string $label): void { if ($value === '') { $findings[] = $base + self::finding($check, self::CONFIRMED_ISSUE, $label . ' is missing in the supplied snapshot.', 'Local snapshot evidence only.'); return; } if (($counts[$value] ?? 0) > 1) { $findings[] = $base + self::finding($check, self::CONFIRMED_ISSUE, $label . ' is duplicated within the supplied snapshot set.', 'Local snapshot evidence only.'); } } private static function append_heading_finding(array &$findings, array $base, array $headings): void { $h1_count = count(array_filter($headings, static fn(array $heading): bool => $heading['level'] === 1)); if ($h1_count === 0) { $findings[] = $base + self::finding('heading', self::CONFIRMED_ISSUE, 'H1 is missing in the supplied heading outline.', 'Local snapshot evidence only.'); return; } if ($h1_count > 1) { $findings[] = $base + self::finding('heading', self::CONFIRMED_ISSUE, 'Multiple H1 headings appear in the supplied outline.', 'Local snapshot evidence only.'); return; } if (self::heading_gap($headings)) { $findings[] = $base + self::finding('heading', self::REVIEW_NEEDED, 'Heading levels skip in the supplied outline.', 'Review structure manually.'); } } private static function key(string $value): string { return strtolower(trim(preg_replace('/\s+/u', ' ', $value) ?? '')); } private static function counts(array $pages, string $key): array { $counts = []; foreach ($pages as $page) { if ($page[$key] !== '') { $counts[$page[$key]] = ($counts[$page[$key]] ?? 0) + 1; } } return $counts; } private static function issue_count(array $findings): int { return count(array_filter( $findings, static fn(array $finding): bool => in_array($finding['status'], [self::CONFIRMED_ISSUE, self::REVIEW_NEEDED], true), )); } private static function stale(string $time): bool { $timestamp = strtotime($time); return $timestamp === false || $timestamp < strtotime('2026-08-23T12:00:00Z'); } private static function heading_gap(array $headings): bool { $previous = 0; foreach ($headings as $heading) { if ($previous && $heading['level'] > $previous + 1) { return true; } $previous = $heading['level']; } return false; } private static function same_site_canonical(string $canonical, string $origin): bool { $canonical_parts = wp_parse_url($canonical); $origin_parts = wp_parse_url($origin); return is_array($canonical_parts) && is_array($origin_parts) && isset($canonical_parts['scheme'], $canonical_parts['host'], $origin_parts['scheme'], $origin_parts['host']) && strtolower((string) $canonical_parts['scheme']) === strtolower((string) $origin_parts['scheme']) && strtolower((string) $canonical_parts['host']) === strtolower((string) $origin_parts['host']) && !isset($canonical_parts['query'], $canonical_parts['fragment']); } }