PluginProbe
WPSSO Core – Complete Schema Markup and Meta Tags / 22.7.0
WPSSO Core – Complete Schema Markup and Meta Tags v22.7.0
22.7.0 22.6.1 22.6.0 22.5.3 22.5.2 22.5.1 22.4.0 22.3.0 22.2.1 22.2.0 22.1.3 22.1.2 22.1.1 22.1.0 22.0.0 21.13.3 21.13.2 trunk 21.13.1
wpsso / lib / integ / seo / wpseo.php

wpseo.php in WPSSO Core – Complete Schema Markup and Meta Tags 22.7.0, at lib/integ/seo/wpseo.php

667 lines 15.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * License: GPLv3
4 * License URI: https://www.gnu.org/licenses/gpl.txt
5 * Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/)
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9
10 die( 'These aren\'t the droids you\'re looking for.' );
11 }
12
13 /*
14 * Integration module for the Yoast SEO plugin.
15 *
16 * See https://wordpress.org/plugins/wordpress-seo/.
17 */
18 if ( ! class_exists( 'WpssoIntegSeoWpseo' ) ) {
19
20 class WpssoIntegSeoWpseo {
21
22 private $p; // Wpsso class object.
23
24 private $wpseo_opts = array();
25
26 public function __construct( &$plugin ) {
27
28 $this->p =& $plugin;
29
30 if ( $this->p->debug->enabled ) {
31
32 $this->p->debug->mark();
33 }
34
35 if ( ! method_exists( 'WPSEO_Options', 'get_all' ) ) {
36
37 if ( $this->p->debug->enabled ) {
38
39 $this->p->debug->log( 'exitinge early: WPSEO_Options::get_all not found' );
40 }
41
42 if ( is_admin() ) {
43
44 // translators: %1$s is the class::method name.
45 $this->p->notice->err( sprintf( __( 'The Yoast SEO <code>%1$s</code> method is missing &ndash; if you are using an older version of Yoast SEO, please update now.', 'wpsso' ), 'WPSEO_Options::get_all()' ) );
46 }
47
48 return;
49 }
50
51 $this->wpseo_opts = WPSEO_Options::get_all();
52
53 $this->p->util->add_plugin_filters( $this, array(
54 'robots_is_noindex' => 2,
55 'primary_term_id' => 4,
56 'title_seed' => 5,
57 'description_seed' => 4,
58 'post_url' => 2,
59 'term_url' => 2,
60 ), 100 );
61
62 if ( is_admin() ) {
63
64 $this->p->util->add_plugin_filters( $this, array( 'admin_page_style_css' => 1 ), 100 );
65
66 add_action( 'admin_init', array( $this, 'cleanup_wpseo_notifications' ), 15 );
67
68 } else {
69
70 add_filter( 'wpseo_frontend_presenters', array( $this, 'cleanup_wpseo_frontend_presenters' ), 1000, 1 );
71 add_filter( 'wpseo_schema_graph', array( $this, 'cleanup_wpseo_schema_graph' ), 1000, 2 );
72 }
73 }
74
75 public function filter_robots_is_noindex( $value, $mod ) {
76
77 $meta_val = null;
78
79 if ( $mod[ 'id' ] ) {
80
81 if ( $mod[ 'is_post' ] ) {
82
83 $meta_val = $this->get_post_meta_value( $mod[ 'id' ], $meta_key = 'meta-robots-noindex' );
84
85 $meta_val = $meta_val ? true : false; // 1 or 0.
86
87 } elseif ( $mod[ 'is_term' ] ) {
88
89 $meta_val = $this->get_term_meta_value( $mod[ 'id' ], $meta_key = 'noindex' );
90
91 $meta_val = 'noindex' === $meta_val ? true : false;
92
93 } elseif ( $mod[ 'is_user' ] ) {
94
95 $meta_val = $this->get_user_meta_value( $mod[ 'id' ], $meta_key = 'noindex_author' );
96
97 $meta_val = 'on' === $meta_val ? true : false;
98 }
99 }
100
101 return null === $meta_val ? $value : $meta_val;
102 }
103
104 public function filter_primary_term_id( $primary_term_id, $mod, $tax_slug, $is_custom ) {
105
106 if ( $this->p->debug->enabled ) {
107
108 $this->p->debug->mark();
109 }
110
111 if ( $is_custom ) {
112
113 if ( $this->p->debug->enabled ) {
114
115 $this->p->debug->log( 'exiting early: $is_custom is true' );
116 }
117
118 return $primary_term_id;
119
120 } elseif ( empty( $mod[ 'is_post' ] ) || empty( $mod[ 'id' ] ) ) {
121
122 if ( $this->p->debug->enabled ) {
123
124 $this->p->debug->log( 'exiting early: not post object or no post ID' );
125 }
126
127 return $primary_term_id;
128
129 } elseif ( empty( $tax_slug ) ) {
130
131 if ( $this->p->debug->enabled ) {
132
133 $this->p->debug->log( 'exiting early: $tax_slug is empty' );
134 }
135
136 return $primary_term_id;
137
138 } else {
139
140 $meta_key = 'primary_' . $tax_slug;
141
142 if ( $this->p->debug->enabled ) {
143
144 $this->p->debug->log( 'calling WpssoIntegSeoWpseo->get_post_meta_value() for ' . $meta_key );
145 }
146
147 if ( $ret = $this->get_post_meta_value( $mod[ 'id' ], $meta_key ) ) {
148
149 return $ret;
150 }
151 }
152
153 return $primary_term_id;
154 }
155
156 public function filter_title_seed( $title_text, $mod, $num_hashtags, $md_key, $title_sep ) {
157
158 if ( $this->p->debug->enabled ) {
159
160 $this->p->debug->mark();
161 }
162
163 $meta_val = '';
164
165 if ( $mod[ 'id' ] ) {
166
167 if ( $mod[ 'is_post' ] ) {
168
169 $meta_val = $this->get_post_meta_value( $mod[ 'id' ], $meta_key = 'title' );
170
171 } elseif ( $mod[ 'is_term' ] ) {
172
173 $meta_val = $this->get_term_meta_value( $mod[ 'id' ], $meta_key = 'title' );
174
175 } elseif ( $mod[ 'is_user' ] ) {
176
177 $meta_val = $this->get_user_meta_value( $mod[ 'id' ], $meta_key = 'title' );
178 }
179 }
180
181 return $meta_val ? $meta_val : $title_text;
182 }
183
184 public function filter_description_seed( $desc_text, $mod, $num_hashtags, $md_key ) {
185
186 if ( $this->p->debug->enabled ) {
187
188 $this->p->debug->mark();
189 }
190
191 $meta_val = '';
192
193 if ( $mod[ 'id' ] ) {
194
195 if ( $mod[ 'is_post' ] ) {
196
197 $meta_val = $this->get_post_meta_value( $mod[ 'id' ], $meta_key = 'metadesc' );
198
199 } elseif ( $mod[ 'is_term' ] ) {
200
201 $meta_val = $this->get_term_meta_value( $mod[ 'id' ], $meta_key = 'metadesc' );
202
203 } elseif ( $mod[ 'is_user' ] ) {
204
205 $meta_val = $this->get_user_meta_value( $mod[ 'id' ], $meta_key = 'metadesc' );
206 }
207 }
208
209 return $meta_val ? $meta_val : $desc_text;
210 }
211
212 public function filter_post_url( $url, $mod ) {
213
214 if ( $this->p->debug->enabled ) {
215
216 $this->p->debug->mark();
217 }
218
219 $meta_val = '';
220
221 if ( $mod[ 'id' ] ) {
222
223 if ( class_exists( 'WPSEO_Meta' ) && method_exists( 'WPSEO_Meta', 'get_value' ) ) {
224
225 $meta_val = WPSEO_Meta::get_value( 'canonical', $mod[ 'id' ] );
226
227 } elseif ( $this->p->debug->enabled ) {
228
229 $this->p->debug->log( 'WPSEO_Meta::get_value not found' );
230 }
231 }
232
233 return $meta_val ? $meta_val : $url;
234 }
235
236 public function filter_term_url( $url, $mod ) {
237
238 if ( $this->p->debug->enabled ) {
239
240 $this->p->debug->mark();
241 }
242
243 $meta_val = '';
244
245 if ( $mod[ 'id' ] ) {
246
247 if ( class_exists( 'WPSEO_Taxonomy_Meta' ) && method_exists( 'WPSEO_Taxonomy_Meta', 'get_term_meta' ) ) {
248
249 $meta_val = WPSEO_Taxonomy_Meta::get_term_meta( $mod[ 'id' ], $mod[ 'tax_slug' ], 'canonical' );
250
251 } elseif ( $this->p->debug->enabled ) {
252
253 $this->p->debug->log( 'WPSEO_Taxonomy_Meta::get_term_meta not found' );
254 }
255 }
256
257 return $meta_val ? $meta_val : $url;
258 }
259
260 private function get_post_meta_value( $post_id, $meta_key ) {
261
262 if ( $this->p->debug->enabled ) {
263
264 $this->p->debug->mark();
265 }
266
267 $meta_val = '';
268 $post_obj = SucomUtilWP::get_post_object( $post_id );
269
270 if ( empty( $post_obj->ID ) ) { // Just in case.
271
272 if ( $this->p->debug->enabled ) {
273
274 $this->p->debug->log( 'exiting early: post object id is empty' );
275 }
276
277 return $meta_val;
278
279 } elseif ( empty( $post_obj->post_type ) ) { // Just in case.
280
281 if ( $this->p->debug->enabled ) {
282
283 $this->p->debug->log( 'exiting early: post object post_type is empty' );
284 }
285
286 return $meta_val;
287 }
288
289 if ( class_exists( 'WPSEO_Meta' ) && method_exists( 'WPSEO_Meta', 'get_value' ) ) {
290
291 if ( $this->p->debug->enabled ) {
292
293 $this->p->debug->log( 'calling WPSEO_Meta::get_value() for ' . $meta_key );
294 }
295
296 if ( $meta_val = WPSEO_Meta::get_value( $meta_key, $post_obj->ID ) ) {
297
298 if ( $this->p->debug->enabled ) {
299
300 $this->p->debug->log( 'WPSEO_Meta::get_value ' . $meta_key . ' = ' . $meta_val );
301 }
302 }
303
304 } elseif ( $this->p->debug->enabled ) {
305
306 $this->p->debug->log( 'WPSEO_Meta::get_value not found' );
307 }
308
309 if ( empty( $meta_val ) ) { // Fallback to the value from the Yoast SEO settings.
310
311 $opts_key = $meta_key . '-' . $post_obj->post_type;
312
313 if ( $this->p->debug->enabled ) {
314
315 $this->p->debug->log( 'Checking for ' . $opts_key . ' in wpseo options (aka settings)' );
316 }
317
318 if ( empty( $this->wpseo_opts[ $opts_key ] ) ) {
319
320 if ( $this->p->debug->enabled ) {
321
322 $this->p->debug->log( 'wpseo options ' . $opts_key . ' is empty' );
323 }
324
325 } else {
326
327 $meta_val = $this->wpseo_opts[ $opts_key ];
328
329 if ( $this->p->debug->enabled ) {
330
331 $this->p->debug->log( 'wpseo options ' . $opts_key . ' = ' . $meta_val );
332 }
333 }
334 }
335
336 return $meta_val;
337 }
338
339 private function get_term_meta_value( $term_id, $meta_key ) {
340
341 if ( $this->p->debug->enabled ) {
342
343 $this->p->debug->mark();
344 }
345
346 $meta_val = '';
347 $term_obj = SucomUtilWP::get_term_object( $term_id );
348
349 if ( empty( $term_obj->term_id ) ) { // Just in case.
350
351 if ( $this->p->debug->enabled ) {
352
353 $this->p->debug->log( 'exiting early: term object id is empty' );
354 }
355
356 return $meta_val;
357
358 } elseif ( empty( $term_obj->taxonomy ) ) { // Just in case.
359
360 if ( $this->p->debug->enabled ) {
361
362 $this->p->debug->log( 'exiting early: term object taxonomy is empty' );
363 }
364
365 return $meta_val;
366 }
367
368 if ( class_exists( 'WPSEO_Taxonomy_Meta' ) && method_exists( 'WPSEO_Taxonomy_Meta', 'get_term_meta' ) ) {
369
370 if ( $meta_val = WPSEO_Taxonomy_Meta::get_term_meta( $term_obj, $term_obj->taxonomy, $meta_key ) ) {
371
372 if ( $this->p->debug->enabled ) {
373
374 $this->p->debug->log( 'WPSEO_Taxonomy_Meta::get_term_meta ' . $meta_key . ' = ' . $meta_val );
375 }
376 }
377
378 } elseif ( $this->p->debug->enabled ) {
379
380 $this->p->debug->log( 'WPSEO_Taxonomy_Meta::get_term_meta not found' );
381 }
382
383 if ( empty( $meta_val ) ) { // Fallback to the value from the Yoast SEO settings.
384
385 $opts_key = $meta_key . '-tax-' . $term_obj->taxonomy;
386
387 if ( empty( $this->wpseo_opts[ $opts_key ] ) ) {
388
389 if ( $this->p->debug->enabled ) {
390
391 $this->p->debug->log( 'wpseo options ' . $opts_key . ' is empty' );
392 }
393
394 } else {
395
396 $meta_val = $this->wpseo_opts[ $opts_key ];
397
398 if ( $this->p->debug->enabled ) {
399
400 $this->p->debug->log( 'wpseo options ' . $opts_key . ' = ' . $meta_val );
401 }
402 }
403 }
404
405 return $meta_val;
406 }
407
408 private function get_user_meta_value( $user_id, $meta_key ) {
409
410 if ( $this->p->debug->enabled ) {
411
412 $this->p->debug->mark();
413 }
414
415 $meta_val = '';
416 $user_obj = SucomUtilWP::get_user_object( $user_id );
417
418 if ( empty( $user_obj->ID ) ) {
419
420 if ( $this->p->debug->enabled ) {
421
422 $this->p->debug->log( 'exiting early: user object id is empty' );
423 }
424
425 return $meta_val;
426 }
427
428 if ( $meta_val = get_the_author_meta( 'wpseo_' . $meta_key, $user_obj->ID ) ) {
429
430 if ( $this->p->debug->enabled ) {
431
432 $this->p->debug->log( 'get_the_author_meta wpseo_' . $meta_key . ' = ' . $meta_val );
433 }
434 }
435
436 if ( empty( $meta_val ) ) { // Fallback to the value from the Yoast SEO settings.
437
438 $opts_key = $meta_key . '-author-wpseo';
439
440 if ( empty( $this->wpseo_opts[ $opts_key ] ) ) {
441
442 if ( $this->p->debug->enabled ) {
443
444 $this->p->debug->log( 'wpseo options ' . $opts_key . ' is empty' );
445 }
446
447 } else {
448
449 $meta_val = $this->wpseo_opts[ $opts_key ];
450
451 if ( $this->p->debug->enabled ) {
452
453 $this->p->debug->log( 'wpseo options ' . $opts_key . ' = ' . $meta_val );
454 }
455 }
456 }
457
458 return $meta_val;
459 }
460
461 /*
462 * Fix Yoast SEO CSS on back-end pages.
463 */
464 public function filter_admin_page_style_css( $custom_style_css ) {
465
466 if ( $this->p->debug->enabled ) {
467
468 $this->p->debug->mark();
469 }
470
471 /*
472 * Fix the width of Yoast SEO list table columns.
473 */
474 $custom_style_css .= '
475 table.wp-list-table > thead > tr > th.column-wpseo-links,
476 table.wp-list-table > tbody > tr > td.column-wpseo-links,
477 table.wp-list-table > thead > tr > th.column-wpseo-linked,
478 table.wp-list-table > tbody > tr > td.column-wpseo-linked,
479 table.wp-list-table > thead > tr > th.column-wpseo-score,
480 table.wp-list-table > tbody > tr > td.column-wpseo-score,
481 table.wp-list-table > thead > tr > th.column-wpseo-score-readability,
482 table.wp-list-table > tbody > tr > td.column-wpseo-score-readability {
483 width:40px;
484 }
485 table.wp-list-table > thead > tr > th.column-wpseo-title,
486 table.wp-list-table > tbody > tr > td.column-wpseo-title,
487 table.wp-list-table > thead > tr > th.column-wpseo-metadesc,
488 table.wp-list-table > tbody > tr > td.column-wpseo-metadesc {
489 width:20%;
490 }
491 table.wp-list-table > thead > tr > th.column-wpseo-focuskw,
492 table.wp-list-table > tbody > tr > td.column-wpseo-focuskw {
493 width:8em; /* Leave room for the sort arrow. */
494 }
495 ';
496
497 /*
498 * The "Schema" metabox tab and its options cannot be disabled, so hide them instead.
499 */
500 if ( ! empty( $this->p->avail[ 'p' ][ 'schema' ] ) ) {
501
502 $custom_style_css .= '
503 #wpseo-meta-tab-schema { display: none; }
504 #wpseo-meta-section-schema { display: none; }
505 ';
506 }
507
508 return $custom_style_css;
509 }
510
511 /*
512 * Cleanup incorrect Yoast SEO notifications.
513 */
514 public function cleanup_wpseo_notifications() {
515
516 if ( $this->p->debug->enabled ) {
517
518 $this->p->debug->mark();
519 }
520
521 /*
522 * Yoast SEO only checks for a conflict with WPSSO if the Open Graph option is enabled.
523 */
524 if ( method_exists( 'WPSEO_Options', 'get' ) ) {
525
526 if ( ! WPSEO_Options::get( 'opengraph' ) ) {
527
528 return;
529 }
530 }
531
532 if ( class_exists( 'Yoast_Notification_Center' ) ) {
533
534 $info = $this->p->cf[ 'plugin' ][ $this->p->id ];
535 $name = $this->p->cf[ 'plugin' ][ $this->p->id ][ 'name' ];
536
537 if ( method_exists( 'Yoast_Notification_Center', 'get_notification_by_id' ) ) {
538
539 $notif_id = 'wpseo-conflict-' . md5( $info[ 'base' ] );
540 $notif_msg = '<style type="text/css">#' . $notif_id . '{display:none;}</style>'; // Hide our empty notification.
541 $notif_center = Yoast_Notification_Center::get();
542 $notif_obj = $notif_center->get_notification_by_id( $notif_id );
543
544 if ( empty( $notif_obj ) ) {
545
546 return;
547 }
548
549 /*
550 * Note that Yoast_Notification::render() wraps the notification message with
551 * '<div class="yoast-alert"></div>'.
552 */
553 if ( method_exists( 'Yoast_Notification', 'render' ) ) {
554
555 $notif_html = $notif_obj->render();
556
557 } else $notif_html = $notif_obj->message;
558
559 if ( false === strpos( $notif_html, $notif_msg ) ) {
560
561 update_metadata( 'user', get_current_user_id(), $notif_obj->get_dismissal_key(), 'seen' );
562
563 $notif_obj = new Yoast_Notification( $notif_msg, array( 'id' => $notif_id ) );
564
565 $notif_center->add_notification( $notif_obj );
566 }
567
568 } elseif ( defined( 'Yoast_Notification_Center::TRANSIENT_KEY' ) ) {
569
570 if ( false !== ( $wpseo_notif = get_transient( Yoast_Notification_Center::TRANSIENT_KEY ) ) ) {
571
572 $wpseo_notif = json_decode( $wpseo_notif, $assoc = false );
573
574 if ( ! empty( $wpseo_notif ) ) {
575
576 foreach ( $wpseo_notif as $num => $notif_msgs ) {
577
578 if ( isset( $notif_msgs->options->type ) && $notif_msgs->options->type == 'error' ) {
579
580 if ( false !== strpos( $notif_msgs->message, $name ) ) {
581
582 unset( $wpseo_notif[ $num ] );
583
584 set_transient( Yoast_Notification_Center::TRANSIENT_KEY, wp_json_encode( $wpseo_notif ) );
585 }
586 }
587 }
588 }
589 }
590 }
591 }
592 }
593
594 /*
595 * Since Yoast SEO v14.0.
596 *
597 * Disable Yoast SEO social meta tags.
598 *
599 * Yoast SEO provides two arguments to this filter, but older versions only provided one.
600 */
601 public function cleanup_wpseo_frontend_presenters( $presenters ) {
602
603 if ( $this->p->debug->enabled ) {
604
605 $this->p->debug->mark();
606 }
607
608 $remove = array( 'Open_Graph', 'Slack', 'Twitter', 'WooCommerce' );
609
610 $remove_preg = '/(' . implode( '|', $remove ) . ')/';
611
612 foreach ( $presenters as $num => $obj ) {
613
614 $class_name = get_class( $obj );
615
616 if ( preg_match( $remove_preg, $class_name ) ) {
617
618 if ( $this->p->debug->enabled ) {
619
620 $this->p->debug->log( 'removing presenter: ' . $class_name );
621 }
622
623 unset( $presenters[ $num ] );
624
625 } elseif ( $this->p->debug->enabled ) {
626
627 $this->p->debug->log( 'skipping presenter: ' . $class_name );
628 }
629 }
630
631 return $presenters;
632 }
633
634 public function cleanup_wpseo_schema_graph( $graph, $context ) {
635
636 if ( $this->p->debug->enabled ) {
637
638 $this->p->debug->mark();
639 }
640
641 if ( ! empty( $this->p->avail[ 'p' ][ 'schema' ] ) ) {
642
643 /*
644 * Remove everything except for the BreadcrumbList markup.
645 *
646 * The WPSSO BC add-on removes the BreadcrumbList markup.
647 */
648 foreach ( $graph as $num => $piece ) {
649
650 if ( ! empty( $piece[ '@type' ] ) ) {
651
652 if ( 'BreadcrumbList' === $piece[ '@type' ] ) { // Keep breadcrumbs.
653
654 continue;
655 }
656
657 }
658
659 unset( $graph[ $num ] ); // Remove everything else.
660 }
661 }
662
663 return array_values( $graph );
664 }
665 }
666 }
667