,total:int,triaging:int}|null */ public static function get(): ?array { $siteKey = (string) Options::get('site_key'); $secret = (string) Options::get('sidecar_key'); if ($siteKey === '' || $secret === '') { return null; } $cached = get_transient(self::TRANSIENT); if (is_array($cached) && isset($cached['total'])) { return empty($cached['failed']) ? $cached : null; } $response = wp_remote_get( sprintf('%s/api/sites/%s/inbox-summary', Options::apiUrl(), rawurlencode($siteKey)), [ 'headers' => ['Authorization' => 'Bearer ' . $secret], 'redirection' => 0, 'timeout' => 3, ], ); $status = is_wp_error($response) ? 0 : (int) wp_remote_retrieve_response_code($response); $body = $status === 200 ? json_decode((string) wp_remote_retrieve_body($response), true) : null; if (!is_array($body)) { set_transient(self::TRANSIENT, ['failed' => true, 'total' => -1], self::CACHE_SEC); return null; } $summary = [ 'awaitingSecondApproval' => max(0, (int) ($body['awaitingSecondApproval'] ?? 0)), 'live' => max(0, (int) ($body['live'] ?? 0)), 'needsReview' => max(0, (int) ($body['needsReview'] ?? 0)), 'noticeEnabled' => !empty($body['noticeEnabled']), 'noticed' => max(0, (int) ($body['noticed'] ?? 0)), 'openRequests' => max(0, (int) ($body['openRequests'] ?? 0)), 'signals' => self::signals($body['signals'] ?? null), 'total' => max(0, (int) ($body['total'] ?? 0)), 'triaging' => max(0, (int) ($body['triaging'] ?? 0)), ]; set_transient(self::TRANSIENT, $summary, self::CACHE_SEC); return $summary; } /** * What failed for visitors lately, as the API lists it, kept to what the * dashboard shows: no visitor keys, nothing a visitor typed. * * @return array */ public static function signals(mixed $raw): array { $out = []; foreach (is_array($raw) ? array_slice($raw, 0, 5) : [] as $signal) { if (!is_array($signal) || !is_string($signal['sample'] ?? null)) { continue; } $out[] = [ 'count' => max(0, (int) ($signal['count'] ?? 0)), 'kind' => in_array($signal['kind'] ?? '', ['request', 'network'], true) ? 'request' : 'error', 'lastSeenAt' => (string) ($signal['lastSeenAt'] ?? ''), 'method' => isset($signal['method']) && is_string($signal['method']) ? $signal['method'] : null, 'reported' => !empty($signal['reported']), 'sample' => mb_substr(sanitize_text_field($signal['sample']), 0, 160), 'status' => isset($signal['status']) && is_numeric($signal['status']) ? (int) $signal['status'] : null, 'urlPath' => mb_substr(sanitize_text_field((string) (wp_parse_url((string) ($signal['urlPath'] ?? ''), PHP_URL_PATH) ?: ($signal['urlPath'] ?? '/'))), 0, 200), ]; } return $out; } public static function forget(): void { delete_transient(self::TRANSIENT); } public static function badge(): string { $summary = self::get(); $count = $summary === null ? 0 : $summary['total']; if ($count < 1) { return ''; } return sprintf( ' %2$s', $count, esc_html(sprintf( /* translators: %d: number of reports waiting. */ _n('%d report waiting', '%d reports waiting', $count, 'sarcio'), $count, )), ); } }