PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.26.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.26.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 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / includes / seo / class-author-archives-manager.php

class-author-archives-manager.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.26.0, at includes/seo/class-author-archives-manager.php

205 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Author Archives Manager
4 *
5 * Handles author archives functionality including redirects
6 *
7 * @package ThinkRank
8 * @subpackage SEO
9 * @since 1.0.0
10 */
11
12 declare(strict_types=1);
13
14 namespace ThinkRank\SEO;
15
16 // Prevent direct access.
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 use ThinkRank\Core\Settings;
22
23 /**
24 * Author Archives Manager Class
25 *
26 * @since 1.0.0
27 */
28 class Author_Archives_Manager {
29
30 /**
31 * Initialize the manager
32 *
33 * @since 1.0.0
34 * @return void
35 */
36 public function init(): void {
37 add_action('template_redirect', [$this, 'maybe_redirect_author_archives']);
38 add_filter('thinkrank_robots_meta', [$this, 'filter_robots']);
39 add_filter('pre_get_document_title', [$this, 'modify_document_title'], 15);
40 add_action('wp_head', [$this, 'add_meta_description'], 5);
41 }
42
43 /**
44 * Add meta description for author archives
45 *
46 * @since 1.0.0
47 * @return void
48 */
49 public function add_meta_description(): void {
50 if (is_author()) {
51 $author_id = get_queried_object_id();
52
53 // A per-author meta description (e.g. imported from another SEO plugin)
54 // overrides the global template.
55 $custom_desc = (string) get_user_meta($author_id, '_thinkrank_meta_description', true);
56 if ($custom_desc !== '') {
57 echo '<meta name="description" content="' . esc_attr($custom_desc) . '" />' . "\n";
58 return;
59 }
60
61 $settings = Settings::instance();
62 // Default value matches what we set in endpoint
63 $template = $settings->get('author_archives_meta_desc', 'Articles written by %author_name% on %site_title%');
64 if (empty($template)) {
65 return;
66 }
67
68 // Get variables
69 $author_name = get_the_author_meta('display_name', $author_id);
70 $site_title = get_bloginfo('name');
71
72 $replacements = [
73 '%author_name%' => $author_name,
74 '%site_title%' => $site_title
75 ];
76
77 $meta_desc = str_replace(array_keys($replacements), array_values($replacements), $template);
78 $meta_desc = trim($meta_desc);
79
80 if (!empty($meta_desc)) {
81 echo '<meta name="description" content="' . esc_attr($meta_desc) . '" />' . "\n";
82 }
83 }
84 }
85
86 /**
87 * Modify document title for author archives
88 *
89 * @since 1.0.0
90 * @param string $title Original title
91 * @return string Modified title
92 */
93 public function modify_document_title(string $title): string {
94 if (is_author()) {
95 $author_id = get_queried_object_id();
96
97 // A per-author SEO title (e.g. imported from another SEO plugin)
98 // overrides the global template entirely.
99 $custom_title = (string) get_user_meta($author_id, '_thinkrank_seo_title', true);
100 if ($custom_title !== '') {
101 return $custom_title;
102 }
103
104 $settings = Settings::instance();
105 $template = $settings->get('author_archives_title', '%author_name% – %site_title% %page%');
106
107 if (empty($template)) {
108 return $title;
109 }
110
111 // Get variables
112 $author_name = get_the_author_meta('display_name', $author_id);
113 $site_title = get_bloginfo('name');
114
115 // Separator
116 $separator = '-';
117 if (class_exists('ThinkRank\SEO\Site_Identity_Manager')) {
118 $separator = \ThinkRank\SEO\Site_Identity_Manager::get_active_separator_symbol();
119 }
120
121 // Page number
122 $page_str = '';
123 $paged = get_query_var('paged') ? (int) get_query_var('paged') : 1;
124 if ($paged > 1) {
125 // translators: %d is the page number for paginated author archives.
126 $page_str = sprintf(__('Page %d', 'thinkrank'), $paged);
127 }
128
129 $replacements = [
130 '%author_name%' => $author_name,
131 '%site_title%' => $site_title,
132 '%separator%' => $separator,
133 '%page%' => $page_str
134 ];
135
136 return str_replace(array_keys($replacements), array_values($replacements), $template);
137 }
138 return $title;
139 }
140
141 /**
142 * Filter robots meta tag
143 *
144 * @since 1.0.0
145 * @param array $robots Robots meta array
146 * @return array Filtered robots meta
147 */
148 public function filter_robots(array $robots): array {
149 if (is_author()) {
150 $settings = Settings::instance();
151 $index = $settings->get('author_archives_index', true);
152
153 if (!$index) {
154 // Remove 'index' if present
155 if (($key = array_search('index', $robots)) !== false) {
156 unset($robots[$key]);
157 }
158 // Add 'noindex' if not present
159 if (!in_array('noindex', $robots)) {
160 $robots[] = 'noindex';
161 }
162 } else {
163 // If showing in search results, check if empty archives should be hidden
164 $show_empty = $settings->get('author_archives_show_empty', false);
165 if (!$show_empty) {
166 $author_id = get_queried_object_id();
167 // Check if author has any published posts
168 $post_count = count_user_posts($author_id, 'post', true); // true = only public posts
169 if ($post_count == 0) {
170 // Remove 'index' if present
171 if (($key = array_search('index', $robots)) !== false) {
172 unset($robots[$key]);
173 }
174 // Add 'noindex' if not present
175 if (!in_array('noindex', $robots)) {
176 $robots[] = 'noindex';
177 }
178 }
179 }
180 }
181 }
182
183 return array_values($robots);
184 }
185
186 /**
187 * Redirect author archives to homepage if disabled
188 *
189 * @since 1.0.0
190 * @return void
191 */
192 public function maybe_redirect_author_archives(): void {
193 if (is_author()) {
194 $settings = Settings::instance();
195 // Default to true (enabled)
196 $enabled = $settings->get('author_archives_enabled', true);
197
198 if (!$enabled) {
199 wp_safe_redirect(home_url(), 301);
200 exit;
201 }
202 }
203 }
204 }
205