PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.5
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 / presentations / indexable-post-type-presentation.php

indexable-post-type-presentation.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.5, at src/presentations/indexable-post-type-presentation.php

420 lines 10.4 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\Presentations;
4
5 use Yoast\WP\SEO\Helpers\Date_Helper;
6 use Yoast\WP\SEO\Helpers\Pagination_Helper;
7 use Yoast\WP\SEO\Helpers\Post_Helper;
8 use Yoast\WP\SEO\Helpers\Post_Type_Helper;
9
10 /**
11 * Class Indexable_Post_Type_Presentation.
12 *
13 * Presentation object for indexables.
14 */
15 class Indexable_Post_Type_Presentation extends Indexable_Presentation {
16
17 /**
18 * Holds the Post_Type_Helper instance.
19 *
20 * @var Post_Type_Helper
21 */
22 protected $post_type;
23
24 /**
25 * Holds the Date_Helper instance.
26 *
27 * @var Date_Helper
28 */
29 protected $date;
30
31 /**
32 * Holds the Pagination_Helper instance.
33 *
34 * @var Pagination_Helper
35 */
36 protected $pagination;
37
38 /**
39 * Holds the Post_Helper instance.
40 *
41 * @var Post_Helper
42 */
43 protected $post;
44
45 /**
46 * Indexable_Post_Type_Presentation constructor.
47 *
48 * @codeCoverageIgnore
49 *
50 * @param Post_Type_Helper $post_type The post type helper.
51 * @param Date_Helper $date The date helper.
52 * @param Pagination_Helper $pagination The pagination helper.
53 * @param Post_Helper $post The post helper.
54 */
55 public function __construct(
56 Post_Type_Helper $post_type,
57 Date_Helper $date,
58 Pagination_Helper $pagination,
59 Post_Helper $post
60 ) {
61 $this->post_type = $post_type;
62 $this->date = $date;
63 $this->pagination = $pagination;
64 $this->post = $post;
65 }
66
67 /**
68 * Generates the canonical.
69 *
70 * @return string The canonical.
71 */
72 public function generate_canonical() {
73 if ( $this->model->canonical ) {
74 return $this->model->canonical;
75 }
76
77 $permalink = $this->permalink;
78
79 // Fix paginated pages canonical, but only if the page is truly paginated.
80 $current_page = $this->pagination->get_current_post_page_number();
81 if ( $current_page > 1 ) {
82 $number_of_pages = $this->model->number_of_pages;
83 if ( $number_of_pages && $current_page <= $number_of_pages ) {
84 $permalink = $this->get_paginated_url( $permalink, $current_page );
85 }
86 }
87
88 return $this->url->ensure_absolute_url( $permalink );
89 }
90
91 /**
92 * Generates the rel prev.
93 *
94 * @return string The rel prev value.
95 */
96 public function generate_rel_prev() {
97 if ( $this->model->number_of_pages === null ) {
98 return '';
99 }
100
101 if ( $this->pagination->is_rel_adjacent_disabled() ) {
102 return '';
103 }
104
105 $current_page = \max( 1, $this->pagination->get_current_post_page_number() );
106
107 // Check if there is a previous page.
108 if ( $current_page < 2 ) {
109 return '';
110 }
111
112 // Check if the previous page is the first page.
113 if ( $current_page === 2 ) {
114 return $this->model->permalink;
115 }
116
117 return $this->get_paginated_url( $this->model->permalink, ( $current_page - 1 ) );
118 }
119
120 /**
121 * Generates the rel next.
122 *
123 * @return string The rel prev next.
124 */
125 public function generate_rel_next() {
126 if ( $this->model->number_of_pages === null ) {
127 return '';
128 }
129
130 if ( $this->pagination->is_rel_adjacent_disabled() ) {
131 return '';
132 }
133
134 $current_page = \max( 1, $this->pagination->get_current_post_page_number() );
135 if ( $this->model->number_of_pages <= $current_page ) {
136 return '';
137 }
138
139 return $this->get_paginated_url( $this->model->permalink, ( $current_page + 1 ) );
140 }
141
142 /**
143 * Generates the open graph title.
144 *
145 * @return string The open graph title.
146 */
147 public function generate_title() {
148 if ( $this->model->title ) {
149 return $this->model->title;
150 }
151
152 // Get SEO title as entered in Search appearance.
153 $post_type = $this->model->object_sub_type;
154 $title = $this->options->get( 'title-' . $this->model->object_sub_type );
155 if ( $title ) {
156 return $title;
157 }
158
159 // Get installation default title.
160 return $this->options->get_title_default( 'title-' . $post_type );
161 }
162
163 /**
164 * Generates the meta description.
165 *
166 * @return string The meta description.
167 */
168 public function generate_meta_description() {
169 if ( $this->model->description ) {
170 return $this->model->description;
171 }
172
173 return $this->options->get( 'metadesc-' . $this->model->object_sub_type );
174 }
175
176 /**
177 * Generates the open graph description.
178 *
179 * @return string The open graph description.
180 */
181 public function generate_open_graph_description() {
182 if ( $this->model->open_graph_description ) {
183 $open_graph_description = $this->model->open_graph_description;
184 }
185
186 if ( empty( $open_graph_description ) ) {
187 // The helper applies a filter, but we don't have a default value at this stage so we pass an empty string.
188 $open_graph_description = $this->values_helper->get_open_graph_description( '', $this->model->object_type, $this->model->object_sub_type );
189 }
190
191 if ( empty( $open_graph_description ) ) {
192 $open_graph_description = $this->meta_description;
193 }
194
195 if ( empty( $open_graph_description ) ) {
196 $open_graph_description = $this->post->get_the_excerpt( $this->model->object_id );
197 $open_graph_description = $this->post->strip_shortcodes( $open_graph_description );
198 }
199
200 return $open_graph_description;
201 }
202
203 /**
204 * Generates the open graph images.
205 *
206 * @return array The open graph images.
207 */
208 public function generate_open_graph_images() {
209 if ( \post_password_required() ) {
210 return [];
211 }
212
213 return parent::generate_open_graph_images();
214 }
215
216 /**
217 * Generates the Open Graph type.
218 *
219 * @return string The Open Graph type.
220 */
221 public function generate_open_graph_type() {
222 return 'article';
223 }
224
225 /**
226 * Generates the open graph article author.
227 *
228 * @return string The open graph article author.
229 */
230 public function generate_open_graph_article_author() {
231 if ( $this->model->object_sub_type !== 'post' ) {
232 return '';
233 }
234
235 $post = $this->source;
236
237 $open_graph_article_author = $this->user->get_the_author_meta( 'facebook', $post->post_author );
238
239 if ( $open_graph_article_author ) {
240 return $open_graph_article_author;
241 }
242
243 return '';
244 }
245
246 /**
247 * Generates the open graph article publisher.
248 *
249 * @return string The open graph article publisher.
250 */
251 public function generate_open_graph_article_publisher() {
252 $open_graph_article_publisher = $this->context->open_graph_publisher;
253
254 if ( $open_graph_article_publisher ) {
255 return $open_graph_article_publisher;
256 }
257
258 return '';
259 }
260
261 /**
262 * Generates the open graph article published time.
263 *
264 * @return string The open graph article published time.
265 */
266 public function generate_open_graph_article_published_time() {
267 if ( $this->model->object_sub_type !== 'post' ) {
268 /**
269 * Filter: 'wpseo_opengraph_show_publish_date' - Allow showing publication date for other post types.
270 *
271 * @param bool $show Whether or not to show publish date.
272 * @param string $post_type The current URL's post type.
273 */
274 if ( ! \apply_filters( 'wpseo_opengraph_show_publish_date', false, $this->post->get_post_type( $this->source ) ) ) {
275 return '';
276 }
277 }
278
279 return $this->date->format( $this->source->post_date_gmt );
280 }
281
282 /**
283 * Generates the open graph article modified time.
284 *
285 * @return string The open graph article modified time.
286 */
287 public function generate_open_graph_article_modified_time() {
288 if ( \strtotime( $this->source->post_modified_gmt ) > \strtotime( $this->source->post_date_gmt ) ) {
289 return $this->date->format( $this->source->post_modified_gmt );
290 }
291
292 return '';
293 }
294
295 /**
296 * Generates the source.
297 *
298 * @return array The source.
299 */
300 public function generate_source() {
301 return \get_post( $this->model->object_id );
302 }
303
304 /**
305 * Generates the robots value.
306 *
307 * @return array The robots value.
308 */
309 public function generate_robots() {
310 $robots = $this->get_base_robots();
311 $robots = \array_merge(
312 $robots,
313 [
314 'imageindex' => ( $this->model->is_robots_noimageindex === true ) ? 'noimageindex' : null,
315 'archive' => ( $this->model->is_robots_noarchive === true ) ? 'noarchive' : null,
316 'snippet' => ( $this->model->is_robots_nosnippet === true ) ? 'nosnippet' : null,
317 ],
318 );
319
320 // No snippet means max snippet can be omitted.
321 if ( $this->model->is_robots_nosnippet === true ) {
322 $robots['max-snippet'] = null;
323 }
324
325 // No image index means max image preview can be omitted.
326 if ( $this->model->is_robots_noimageindex === true ) {
327 $robots['max-image-preview'] = null;
328 }
329
330 // When the post specific index is not set, look to the post status and default of the post type.
331 if ( $this->model->is_robots_noindex === null ) {
332 $post_status_private = \get_post_status( $this->model->object_id ) === 'private';
333 $post_type_noindex = ! $this->post_type->is_indexable( $this->model->object_sub_type );
334
335 if ( $post_status_private || $post_type_noindex ) {
336 $robots['index'] = 'noindex';
337 }
338 }
339
340 return $this->filter_robots( $robots );
341 }
342
343 /**
344 * Generates the Twitter description.
345 *
346 * @return string The Twitter description.
347 */
348 public function generate_twitter_description() {
349 $twitter_description = parent::generate_twitter_description();
350
351 if ( $twitter_description ) {
352 return $twitter_description;
353 }
354
355 if ( $this->open_graph_description && $this->context->open_graph_enabled === true ) {
356 return '';
357 }
358
359 return $this->post->get_the_excerpt( $this->model->object_id );
360 }
361
362 /**
363 * Generates the Twitter image.
364 *
365 * @return string The Twitter image.
366 */
367 public function generate_twitter_image() {
368 if ( \post_password_required() ) {
369 return '';
370 }
371
372 return parent::generate_twitter_image();
373 }
374
375 /**
376 * Generates the Twitter creator.
377 *
378 * @return string The Twitter creator.
379 */
380 public function generate_twitter_creator() {
381 if ( $this->model->object_sub_type !== 'post' ) {
382 return '';
383 }
384
385 $twitter_creator = \ltrim( \trim( \get_the_author_meta( 'twitter', $this->source->post_author ) ), '@' );
386
387 /**
388 * Filter: 'wpseo_twitter_creator_account' - Allow changing the X account as output in the X card by Yoast SEO.
389 *
390 * @param string $twitter The twitter account name string.
391 */
392 $twitter_creator = \apply_filters( 'wpseo_twitter_creator_account', $twitter_creator );
393
394 if ( \is_string( $twitter_creator ) && $twitter_creator !== '' ) {
395 return '@' . $twitter_creator;
396 }
397
398 $site_twitter = $this->options->get( 'twitter_site', '' );
399 if ( \is_string( $site_twitter ) && $site_twitter !== '' ) {
400 return '@' . $site_twitter;
401 }
402
403 return '';
404 }
405
406 /**
407 * Wraps the get_paginated_url pagination helper method.
408 *
409 * @codeCoverageIgnore A wrapper method.
410 *
411 * @param string $url The un-paginated URL of the current archive.
412 * @param string $page The page number to add on to $url for the $link tag.
413 *
414 * @return string The paginated URL.
415 */
416 protected function get_paginated_url( $url, $page ) {
417 return $this->pagination->get_paginated_url( $url, $page, false );
418 }
419 }
420