PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.10.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.10.0
2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 All 51 releases
thinkrank / includes / seo / email-report-sections / class-top-posts-renderer.php

class-top-posts-renderer.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.10.0, at includes/seo/email-report-sections/class-top-posts-renderer.php

111 lines 3.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Top Posts Renderer
4 *
5 * Shared row-shaping helper used by the four growing / losing sections so
6 * pages and queries read the same way in every card. Not a section itself
7 * — purely a stateless presentation helper on top of Email_Report_Html.
8 *
9 * @package ThinkRank
10 * @subpackage SEO\Email_Report_Sections
11 * @since 1.9.0
12 */
13
14 declare(strict_types=1);
15
16 namespace ThinkRank\SEO\Email_Report_Sections;
17
18 if (!defined('ABSPATH')) {
19 exit;
20 }
21
22 final class Top_Posts_Renderer {
23
24 /**
25 * Shape page entries into list rows: title (resolved from the URL when
26 * it is one of this site's posts), the path underneath, a ±N clicks pill.
27 *
28 * @param array $rows Each row: ['url' => string, 'clicks' => int, 'change' => int]
29 * @return array<int,array{title:string,subtitle:string,pill:string,href:string}>
30 */
31 public static function page_rows(array $rows): array {
32 $out = [];
33 foreach ($rows as $row) {
34 $url = (string) ($row['url'] ?? $row['page'] ?? '');
35 if ($url === '') {
36 continue;
37 }
38 $title = (string) ($row['title'] ?? '');
39 if ($title === '') {
40 $title = Email_Report_Html::page_title($url);
41 }
42 $path = Email_Report_Html::display_path($url);
43 $out[] = [
44 'title' => $title,
45 'subtitle' => $path !== $title ? $path : '',
46 'pill' => self::clicks_pill((int) ($row['change'] ?? 0)),
47 'href' => $url,
48 ];
49 }
50 return $out;
51 }
52
53 /**
54 * Shape query entries into list rows: the query, its average position
55 * (and the previous one when it moved), a ±N clicks pill.
56 *
57 * @param array $rows Each row: ['query' => string, 'position' => ?float, 'prev_position' => ?float, 'change' => int]
58 * @return array<int,array{title:string,subtitle:string,pill:string}>
59 */
60 public static function keyword_rows(array $rows): array {
61 $out = [];
62 foreach ($rows as $row) {
63 $query = (string) ($row['query'] ?? ($row['keys'][0] ?? ''));
64 if ($query === '') {
65 continue;
66 }
67 $out[] = [
68 'title' => $query,
69 'subtitle' => self::position_line($row['position'] ?? null, $row['prev_position'] ?? null),
70 'pill' => self::clicks_pill((int) ($row['change'] ?? 0)),
71 ];
72 }
73 return $out;
74 }
75
76 /**
77 * "Avg. position 9.4 (was 5.1)". A null current position means the query
78 * had no impressions this period — say so rather than print 0.0.
79 */
80 private static function position_line($position, $previous): string {
81 if ($position === null) {
82 return __('No impressions this period', 'thinkrank');
83 }
84 $line = sprintf(
85 /* translators: %s: average position, one decimal. */
86 __('Avg. position %s', 'thinkrank'),
87 number_format_i18n((float) $position, 1)
88 );
89 if ($previous !== null && abs((float) $previous - (float) $position) >= 0.1) {
90 $line .= ' ' . sprintf(
91 /* translators: %s: previous average position, one decimal. */
92 __('(was %s)', 'thinkrank'),
93 number_format_i18n((float) $previous, 1)
94 );
95 }
96 return $line;
97 }
98
99 /**
100 * "+412 clicks" / "−188 clicks".
101 */
102 private static function clicks_pill(int $change): string {
103 $sign = $change < 0 ? '−' : '+';
104 return $sign . sprintf(
105 /* translators: %s: number of clicks. */
106 _n('%s click', '%s clicks', abs($change), 'thinkrank'),
107 number_format_i18n(abs($change))
108 );
109 }
110 }
111