PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.5.1
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.5.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 / src / surfaces / meta-surface.php

meta-surface.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 18.5.1, at src/surfaces/meta-surface.php

377 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Surfaces;
4
5 use Yoast\WP\SEO\Context\Meta_Tags_Context;
6 use Yoast\WP\SEO\Helpers\Indexable_Helper;
7 use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
8 use Yoast\WP\SEO\Models\Indexable;
9 use Yoast\WP\SEO\Repositories\Indexable_Repository;
10 use Yoast\WP\SEO\Surfaces\Values\Meta;
11 use Yoast\WP\SEO\Wrappers\WP_Rewrite_Wrapper;
12 use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
13
14 /**
15 * Meta_Surface class.
16 *
17 * Surface for the indexables.
18 */
19 class Meta_Surface {
20
21 /**
22 * The container.
23 *
24 * @var ContainerInterface
25 */
26 private $container;
27
28 /**
29 * The memoizer for the meta tags context.
30 *
31 * @var Meta_Tags_Context_Memoizer
32 */
33 private $context_memoizer;
34
35 /**
36 * The indexable repository.
37 *
38 * @var Indexable_Repository
39 */
40 private $repository;
41
42 /**
43 * Holds the WP rewrite wrapper instance.
44 *
45 * @var WP_Rewrite_Wrapper
46 */
47 private $wp_rewrite_wrapper;
48
49 /**
50 * The indexable helper.
51 *
52 * @var Indexable_Helper
53 */
54 private $indexable_helper;
55
56 /**
57 * Meta_Surface constructor.
58 *
59 * @param ContainerInterface $container The DI container.
60 * @param Meta_Tags_Context_Memoizer $context_memoizer The meta tags context memoizer.
61 * @param Indexable_Repository $indexable_repository The indexable repository.
62 * @param WP_Rewrite_Wrapper $wp_rewrite_wrapper The WP rewrite wrapper.
63 * @param Indexable_Helper $indexable_helper The indexable helper.
64 */
65 public function __construct(
66 ContainerInterface $container,
67 Meta_Tags_Context_Memoizer $context_memoizer,
68 Indexable_Repository $indexable_repository,
69 WP_Rewrite_Wrapper $wp_rewrite_wrapper,
70 Indexable_Helper $indexable_helper
71 ) {
72 $this->container = $container;
73 $this->context_memoizer = $context_memoizer;
74 $this->repository = $indexable_repository;
75 $this->wp_rewrite_wrapper = $wp_rewrite_wrapper;
76 $this->indexable_helper = $indexable_helper;
77 }
78
79 /**
80 * Returns the meta tags context for the current page.
81 *
82 * @return Meta The meta values.
83 */
84 public function for_current_page() {
85 return $this->build_meta( $this->context_memoizer->for_current_page() );
86 }
87
88 /**
89 * Returns the meta tags context for the home page.
90 *
91 * @return Meta|false The meta values. False if none could be found.
92 */
93 public function for_home_page() {
94 $front_page_id = (int) \get_option( 'page_on_front' );
95 if ( \get_option( 'show_on_front' ) === 'page' && $front_page_id !== 0 ) {
96 $indexable = $this->repository->find_by_id_and_type( $front_page_id, 'post' );
97
98 if ( ! $indexable ) {
99 return false;
100 }
101
102 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Home_Page' ) );
103 }
104
105 $indexable = $this->repository->find_for_home_page();
106
107 if ( ! $indexable ) {
108 return false;
109 }
110
111 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) );
112 }
113
114 /**
115 * Returns the meta tags context for the posts page.
116 *
117 * @return Meta|false The meta values. False if none could be found.
118 */
119 public function for_posts_page() {
120 $posts_page_id = (int) \get_option( 'page_for_posts' );
121 if ( $posts_page_id !== 0 ) {
122 $indexable = $this->repository->find_by_id_and_type( $posts_page_id, 'post' );
123
124 if ( ! $indexable ) {
125 return false;
126 }
127
128 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Posts_Page' ) );
129 }
130
131 $indexable = $this->repository->find_for_home_page();
132
133 if ( ! $indexable ) {
134 return false;
135 }
136
137
138 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) );
139 }
140
141 /**
142 * Returns the meta tags context for a post type archive.
143 *
144 * @param string|null $post_type Optional. The post type to get the archive meta for. Defaults to the current post type.
145 *
146 * @return Meta|false The meta values. False if none could be found.
147 */
148 public function for_post_type_archive( $post_type = null ) {
149 if ( $post_type === null ) {
150 $post_type = \get_post_type();
151 }
152
153 $indexable = $this->repository->find_for_post_type_archive( $post_type );
154
155 if ( ! $indexable ) {
156 return false;
157 }
158
159 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type_Archive' ) );
160 }
161
162 /**
163 * Returns the meta tags context for the search result page.
164 *
165 * @return Meta|false The meta values. False if none could be found.
166 */
167 public function for_search_result() {
168 $indexable = $this->repository->find_for_system_page( 'search-result' );
169
170 if ( ! $indexable ) {
171 return false;
172 }
173
174 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Search_Result_Page' ) );
175 }
176
177 /**
178 * Returns the meta tags context for the search result page.
179 *
180 * @return Meta|false The meta values. False if none could be found.
181 */
182 public function for_404() {
183 $indexable = $this->repository->find_for_system_page( '404' );
184
185 if ( ! $indexable ) {
186 return false;
187 }
188
189
190 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Error_Page' ) );
191 }
192
193 /**
194 * Returns the meta tags context for a post.
195 *
196 * @param int $id The ID of the post.
197 *
198 * @return Meta|false The meta values. False if none could be found.
199 */
200 public function for_post( $id ) {
201 $indexable = $this->repository->find_by_id_and_type( $id, 'post' );
202
203 if ( ! $indexable ) {
204 return false;
205 }
206
207 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) );
208 }
209
210 /**
211 * Returns the meta tags context for a number of posts.
212 *
213 * @param int[] $ids The IDs of the posts.
214 *
215 * @return Meta[]|false The meta values. False if none could be found.
216 */
217 public function for_posts( $ids ) {
218 $indexables = $this->repository->find_by_multiple_ids_and_type( $ids, 'post' );
219
220 if ( empty( $indexables ) ) {
221 return false;
222 }
223
224 return \array_map(
225 function( $indexable ) {
226 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) );
227 },
228 $indexables
229 );
230 }
231
232 /**
233 * Returns the meta tags context for a term.
234 *
235 * @param int $id The ID of the term.
236 *
237 * @return Meta|false The meta values. False if none could be found.
238 */
239 public function for_term( $id ) {
240 $indexable = $this->repository->find_by_id_and_type( $id, 'term' );
241
242 if ( ! $indexable ) {
243 return false;
244 }
245
246 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Term_Archive' ) );
247 }
248
249 /**
250 * Returns the meta tags context for an author.
251 *
252 * @param int $id The ID of the author.
253 *
254 * @return Meta|false The meta values. False if none could be found.
255 */
256 public function for_author( $id ) {
257 $indexable = $this->repository->find_by_id_and_type( $id, 'user' );
258
259 if ( ! $indexable ) {
260 return false;
261 }
262
263 return $this->build_meta( $this->context_memoizer->get( $indexable, 'Author_Archive' ) );
264 }
265
266 /**
267 * Returns the meta for an indexable.
268 *
269 * @param Indexable $indexable The indexable.
270 * @param string|null $page_type Optional. The page type if already known.
271 *
272 * @return Meta|false The meta values. False if none could be found.
273 */
274 public function for_indexable( $indexable, $page_type = null ) {
275 if ( \is_null( $page_type ) ) {
276 $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
277 }
278
279 return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) );
280 }
281
282 /**
283 * Returns the meta for an indexable.
284 *
285 * @param Indexable[] $indexables The indexables.
286 * @param string|null $page_type Optional. The page type if already known.
287 *
288 * @return Meta|false The meta values. False if none could be found.
289 */
290 public function for_indexables( $indexables, $page_type = null ) {
291 $closure = function( $indexable ) use ( $page_type ) {
292 $this_page_type = $page_type;
293 if ( \is_null( $this_page_type ) ) {
294 $this_page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
295 }
296
297 return $this->build_meta( $this->context_memoizer->get( $indexable, $this_page_type ) );
298 };
299
300 return \array_map( $closure, $indexables );
301 }
302
303 /**
304 * Returns the meta tags context for a url.
305 *
306 * @param string $url The url of the page. Required to be relative to the site url.
307 *
308 * @return Meta|false The meta values. False if none could be found.
309 */
310 public function for_url( $url ) {
311 $url_parts = \wp_parse_url( $url );
312 $site_parts = \wp_parse_url( \site_url() );
313 if ( $url_parts['host'] !== $site_parts['host'] ) {
314 return false;
315 }
316 // Ensure the scheme is consistent with values in the DB.
317 $url = $site_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
318
319 if ( $this->is_date_archive_url( $url ) ) {
320 $indexable = $this->repository->find_for_date_archive();
321 }
322 else {
323 $indexable = $this->repository->find_by_permalink( $url );
324 }
325
326 // If we still don't have an indexable abort, the WP globals could be anything so we can't use the unknown indexable.
327 if ( ! $indexable ) {
328 return false;
329 }
330 $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
331
332 if ( $page_type === false ) {
333 return false;
334 }
335
336 return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) );
337 }
338
339 /**
340 * Checks if a given URL is a date archive URL.
341 *
342 * @param string $url The url.
343 *
344 * @return bool
345 */
346 protected function is_date_archive_url( $url ) {
347 $path = \wp_parse_url( $url, \PHP_URL_PATH );
348 if ( $path === null ) {
349 return false;
350 }
351
352 $path = \ltrim( $path, '/' );
353 $wp_rewrite = $this->wp_rewrite_wrapper->get();
354 $date_rewrite = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), \EP_DATE );
355 $date_rewrite = \apply_filters( 'date_rewrite_rules', $date_rewrite );
356
357 foreach ( (array) $date_rewrite as $match => $query ) {
358 if ( \preg_match( "#^$match#", $path ) ) {
359 return true;
360 }
361 }
362
363 return false;
364 }
365
366 /**
367 * Creates a new meta value object
368 *
369 * @param Meta_Tags_Context $context The meta tags context.
370 *
371 * @return Meta The meta value
372 */
373 protected function build_meta( Meta_Tags_Context $context ) {
374 return new Meta( $context, $this->container );
375 }
376 }
377