string, 'clicks' => int, 'change' => ?int, 'title' => ?string] * @param string $variant 'gain' | 'loss' — controls accent color only. */ public static function render(array $rows, string $variant = 'gain'): string { if (empty($rows)) { return ''; } $accent = $variant === 'loss' ? '#dc2626' : '#16a34a'; $html = ''; $html .= '' . self::th(__('Page', 'thinkrank'), 'left') . self::th(__('Clicks', 'thinkrank'), 'right') . self::th(__('Change', 'thinkrank'), 'right') . ''; foreach ($rows as $row) { $url = (string) ($row['url'] ?? $row['page'] ?? ''); $title = (string) ($row['title'] ?? ''); $clicks = (int) ($row['clicks'] ?? 0); $display = $title !== '' ? $title : $url; $html .= '' . '' . '' . self::change_cell($row['change'] ?? null, $accent) . ''; } $html .= '
' . ($url !== '' ? '' . esc_html($display) . '' : '' . esc_html($display) . '') . '' . esc_html(number_format_i18n($clicks)) . '
'; return $html; } /** * Render a keyword table (query, position, clicks, click change). * * @param array $rows Each row: ['query' => string, 'position' => ?float, 'clicks' => int, 'change' => ?int] * @param string $variant 'gain' | 'loss' */ public static function render_keywords(array $rows, string $variant = 'gain'): string { if (empty($rows)) { return ''; } $accent = $variant === 'loss' ? '#dc2626' : '#16a34a'; $html = ''; $html .= '' . self::th(__('Keyword', 'thinkrank'), 'left') . self::th(__('Position', 'thinkrank'), 'right') . self::th(__('Clicks', 'thinkrank'), 'right') . self::th(__('Change', 'thinkrank'), 'right') . ''; foreach ($rows as $row) { $query = (string) ($row['query'] ?? ($row['keys'][0] ?? '')); // Null position means "no data this period" (e.g. a keyword that // dropped out entirely) — a literal 0.0 would read as rank #1. $position = isset($row['position']) ? number_format_i18n((float) $row['position'], 1) : '—'; $clicks = (int) ($row['clicks'] ?? 0); if ($query === '') { continue; } $html .= '' . '' . '' . '' . self::change_cell($row['change'] ?? null, $accent) . ''; } $html .= '
' . esc_html($query) . '' . esc_html($position) . '' . esc_html(number_format_i18n($clicks)) . '
'; return $html; } /** * Table header cell. */ private static function th(string $label, string $align): string { return '' . esc_html($label) . ''; } /** * Signed click-change cell. Positive renders green with ▲, negative red * with ▼. A null/zero change renders a neutral dash. */ private static function change_cell($change, string $accent): string { $td = '%s'; if ($change === null || (int) $change === 0) { return sprintf($td, '#9ca3af', '—'); } $change = (int) $change; $arrow = $change > 0 ? '▲' : '▼'; return sprintf($td, esc_attr($accent), esc_html($arrow . ' ' . number_format_i18n(abs($change)))); } }