PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.1
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.1
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
metasync / breadcrumbs / class-metasync-breadcrumbs-schema.php

class-metasync-breadcrumbs-schema.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.7.1, at breadcrumbs/class-metasync-breadcrumbs-schema.php

135 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MetaSync Breadcrumbs Schema — BreadcrumbList JSON-LD output via wp_head.
4 *
5 * @package Metasync
6 * @subpackage Metasync/breadcrumbs
7 */
8
9 if (!defined('ABSPATH')) {
10 exit;
11 }
12
13 class Metasync_Breadcrumbs_Schema {
14
15 /**
16 * Flag indicating whether this class has already injected BreadcrumbList JSON-LD.
17 *
18 * Checked by Metasync_Schema_Markup to avoid duplicate output.
19 *
20 * @var bool
21 */
22 public static $breadcrumb_list_injected = false;
23
24 /**
25 * Plugin name.
26 *
27 * @var string
28 */
29 private $plugin_name;
30
31 /**
32 * Plugin version.
33 *
34 * @var string
35 */
36 private $version;
37
38 /**
39 * Constructor.
40 *
41 * @param string $plugin_name Plugin slug.
42 * @param string $version Plugin version.
43 */
44 public function __construct($plugin_name = 'metasync', $version = '1.0.0') {
45 $this->plugin_name = $plugin_name;
46 $this->version = $version;
47
48 // Priority 5 — before the schema-markup module which runs at default (10).
49 add_action('wp_head', array($this, 'output_breadcrumb_schema'), 5);
50 }
51
52 /**
53 * Output BreadcrumbList JSON-LD in <head>.
54 */
55 public function output_breadcrumb_schema() {
56 // Check if breadcrumbs are enabled.
57 $settings = Metasync::get_option('breadcrumbs', array());
58 if (isset($settings['enabled']) && empty($settings['enabled'])) {
59 return;
60 }
61
62 // Check if schema output is disabled.
63 if (!empty($settings['disable_schema'])) {
64 return;
65 }
66
67 // Skip on admin, feeds, robots.
68 if (is_admin() || is_feed() || is_robots()) {
69 return;
70 }
71
72 // Skip on search results and 404 — BreadcrumbList is not meaningful there.
73 if (is_search() || is_404()) {
74 return;
75 }
76
77 // Resolve the trail.
78 $breadcrumbs = new Metasync_Breadcrumbs();
79 $trail = $breadcrumbs->resolve_breadcrumb_trail();
80
81 if (count($trail) < 2) {
82 return;
83 }
84
85 // Build ListItem entries.
86 $list_items = array();
87 $position = 1;
88
89 $trail_total = count($trail);
90
91 foreach ($trail as $trail_index => $item) {
92 // Google allows only the FINAL ListItem to omit `item`. Drop any
93 // earlier crumb whose URL could not be resolved rather than emit
94 // structured data that fails validation.
95 if ($trail_index !== $trail_total - 1 && empty($item['url'])) {
96 continue;
97 }
98
99 $list_item = array(
100 '@type' => 'ListItem',
101 'position' => $position,
102 'name' => html_entity_decode($item['label'], ENT_QUOTES | ENT_HTML5, 'UTF-8'),
103 );
104
105 if (!empty($item['url'])) {
106 $list_item['item'] = $item['url'];
107 }
108
109 $list_items[] = $list_item;
110 $position++;
111 }
112
113 $json_ld = array(
114 '@context' => 'https://schema.org',
115 '@graph' => array(
116 array(
117 '@type' => 'BreadcrumbList',
118 'itemListElement' => $list_items,
119 ),
120 ),
121 );
122
123 $json = metasync_safe_json_ld_encode($json_ld, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
124 if (!is_string($json) || $json === '') {
125 return;
126 }
127
128 echo '<script type="application/ld+json" class="metasync-breadcrumb-schema">' . "\n";
129 echo $json;
130 echo "\n" . '</script>' . "\n";
131
132 self::$breadcrumb_list_injected = true;
133 }
134 }
135