PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.1
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.1
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / inc / sitemaps / class-author-sitemap-provider.php

class-author-sitemap-provider.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.1, at inc/sitemaps/class-author-sitemap-provider.php

254 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPSEO plugin file.
4 *
5 * @package WPSEO\XML_Sitemaps
6 */
7
8 /**
9 * Sitemap provider for author archives.
10 */
11 class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider {
12
13 /**
14 * Check if provider supports given item type.
15 *
16 * @param string $type Type string to check for.
17 *
18 * @return bool
19 */
20 public function handles_type( $type ) {
21 // If the author archives have been disabled, we don't do anything.
22 if ( WPSEO_Options::get( 'disable-author', false ) || WPSEO_Options::get( 'noindex-author-wpseo', false ) ) {
23 return false;
24 }
25
26 return $type === 'author';
27 }
28
29 /**
30 * Get the links for the sitemap index.
31 *
32 * @param int $max_entries Entries per sitemap.
33 *
34 * @return array
35 */
36 public function get_index_links( $max_entries ) {
37
38 if ( ! $this->handles_type( 'author' ) ) {
39 return [];
40 }
41
42 // @todo Consider doing this less often / when necessary. R.
43 $this->update_user_meta();
44
45 $has_exclude_filter = has_filter( 'wpseo_sitemap_exclude_author' );
46
47 $query_arguments = [];
48
49 if ( ! $has_exclude_filter ) { // We only need full users if legacy filter(s) hooked to exclusion logic. R.
50 $query_arguments['fields'] = 'ID';
51 }
52
53 $users = $this->get_users( $query_arguments );
54
55 if ( $has_exclude_filter ) {
56 $users = $this->exclude_users( $users );
57 $users = wp_list_pluck( $users, 'ID' );
58 }
59
60 if ( empty( $users ) ) {
61 return [];
62 }
63
64 $index = [];
65 $user_pages = array_chunk( $users, $max_entries );
66
67 foreach ( $user_pages as $page_counter => $users_page ) {
68
69 $current_page = ( $page_counter === 0 ) ? '' : ( $page_counter + 1 );
70
71 $user_id = array_shift( $users_page ); // Time descending, first user on page is most recently updated.
72 $user = get_user_by( 'id', $user_id );
73 $index[] = [
74 'loc' => WPSEO_Sitemaps_Router::get_base_url( 'author-sitemap' . $current_page . '.xml' ),
75 'lastmod' => ( $user->_yoast_wpseo_profile_updated ) ? YoastSEO()->helpers->date->format_timestamp( $user->_yoast_wpseo_profile_updated ) : null,
76 ];
77 }
78
79 return $index;
80 }
81
82 /**
83 * Retrieve users, taking account of all necessary exclusions.
84 *
85 * @param array $arguments Arguments to add.
86 *
87 * @return array
88 */
89 protected function get_users( $arguments = [] ) {
90
91 $defaults = [
92 'meta_key' => '_yoast_wpseo_profile_updated',
93 'orderby' => 'meta_value_num',
94 'order' => 'DESC',
95 'meta_query' => [
96 'relation' => 'OR',
97 [
98 'key' => 'wpseo_noindex_author',
99 'value' => 'on',
100 'compare' => '!=',
101 ],
102 [
103 'key' => 'wpseo_noindex_author',
104 'compare' => 'NOT EXISTS',
105 ],
106 ],
107 ];
108
109 $defaults = $this->apply_author_eligibility_filter( $defaults );
110
111 return get_users( array_merge( $defaults, $arguments ) );
112 }
113
114 /**
115 * Applies the author-eligibility clause (capability or has_published_posts) to a get_users() criteria array.
116 *
117 * Centralises the `noindex-author-noposts-wpseo` branching so the sitemap query and its
118 * backfill counterpart always agree on which users are considered eligible.
119 *
120 * @param array<string, array<array<string, string>>> $criteria The get_users() criteria array to extend.
121 *
122 * @return array<string, array<array<string, string>>> The criteria array with the eligibility clause applied.
123 */
124 protected function apply_author_eligibility_filter( array $criteria ) {
125 if ( WPSEO_Options::get( 'noindex-author-noposts-wpseo', true ) ) {
126 $criteria['has_published_posts'] = YoastSEO()->helpers->author_archive->get_author_archive_post_types();
127
128 return $criteria;
129 }
130
131 $criteria['capability'] = [ 'edit_posts' ];
132
133 return $criteria;
134 }
135
136 /**
137 * Get set of sitemap link data.
138 *
139 * @param string $type Sitemap type.
140 * @param int $max_entries Entries per sitemap.
141 * @param int $current_page Current page of the sitemap.
142 *
143 * @return array
144 *
145 * @throws OutOfBoundsException When an invalid page is requested.
146 */
147 public function get_sitemap_links( $type, $max_entries, $current_page ) {
148
149 $links = [];
150
151 if ( ! $this->handles_type( 'author' ) ) {
152 return $links;
153 }
154
155 $user_criteria = [
156 'offset' => ( ( $current_page - 1 ) * $max_entries ),
157 'number' => $max_entries,
158 ];
159
160 $users = $this->get_users( $user_criteria );
161
162 // Throw an exception when there are no users in the sitemap.
163 if ( count( $users ) === 0 ) {
164 throw new OutOfBoundsException( 'Invalid sitemap page requested' );
165 }
166
167 $users = $this->exclude_users( $users );
168 if ( empty( $users ) ) {
169 $users = [];
170 }
171
172 $time = time();
173
174 foreach ( $users as $user ) {
175
176 $author_link = get_author_posts_url( $user->ID );
177
178 if ( empty( $author_link ) ) {
179 continue;
180 }
181
182 $mod = $time;
183
184 if ( isset( $user->_yoast_wpseo_profile_updated ) ) {
185 $mod = $user->_yoast_wpseo_profile_updated;
186 }
187
188 $url = [
189 'loc' => $author_link,
190 'mod' => date( DATE_W3C, $mod ),
191
192 // Deprecated, kept for backwards data compat. R.
193 'chf' => 'daily',
194 'pri' => 1,
195 ];
196
197 /** This filter is documented at inc/sitemaps/class-post-type-sitemap-provider.php */
198 $url = apply_filters( 'wpseo_sitemap_entry', $url, 'user', $user );
199
200 if ( ! empty( $url ) ) {
201 $links[] = $url;
202 }
203 }
204
205 return $links;
206 }
207
208 /**
209 * Update any users that don't have last profile update timestamp.
210 *
211 * @return int Count of users updated.
212 */
213 protected function update_user_meta() {
214
215 $user_criteria = [
216 'meta_query' => [
217 [
218 'key' => '_yoast_wpseo_profile_updated',
219 'compare' => 'NOT EXISTS',
220 ],
221 ],
222 ];
223
224 $user_criteria = $this->apply_author_eligibility_filter( $user_criteria );
225
226 $users = get_users( $user_criteria );
227
228 $time = time();
229
230 foreach ( $users as $user ) {
231 update_user_meta( $user->ID, '_yoast_wpseo_profile_updated', $time );
232 }
233
234 return count( $users );
235 }
236
237 /**
238 * Wrap legacy filter to deduplicate calls.
239 *
240 * @param array $users Array of user objects to filter.
241 *
242 * @return array
243 */
244 protected function exclude_users( $users ) {
245
246 /**
247 * Filter the authors, included in XML sitemap.
248 *
249 * @param array $users Array of user objects to filter.
250 */
251 return apply_filters( 'wpseo_sitemap_exclude_author', $users );
252 }
253 }
254