PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.3
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.3
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 / generators / schema / breadcrumb.php

breadcrumb.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 18.3, at src/generators/schema/breadcrumb.php

169 lines 4.6 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\Generators\Schema;
4
5 use Yoast\WP\SEO\Config\Schema_IDs;
6
7 /**
8 * Returns schema Breadcrumb data.
9 */
10 class Breadcrumb extends Abstract_Schema_Piece {
11
12 /**
13 * Determine if we should add a breadcrumb attribute.
14 *
15 * @return bool
16 */
17 public function is_needed() {
18 if ( $this->context->indexable->object_type === 'system-page' && $this->context->indexable->object_sub_type === '404' ) {
19 return false;
20 }
21
22 return true;
23 }
24
25 /**
26 * Returns Schema breadcrumb data to allow recognition of page's position in the site hierarchy.
27 *
28 * @link https://developers.google.com/search/docs/data-types/breadcrumb
29 *
30 * @return bool|array Array on success, false on failure.
31 */
32 public function generate() {
33 $breadcrumbs = $this->context->presentation->breadcrumbs;
34 $list_elements = [];
35
36 // In case of pagination, replace the last breadcrumb, because it only contains "Page [number]" and has no URL.
37 if (
38 (
39 $this->helpers->current_page->is_paged()
40 || $this->context->indexable->number_of_pages > 1
41 ) && (
42 // Do not replace the last breadcrumb on static post pages.
43 ! $this->helpers->current_page->is_static_posts_page()
44 // Do not remove the last breadcrumb if only one exists (bugfix for custom paginated frontpages).
45 && \count( $breadcrumbs ) > 1
46 )
47 ) {
48 \array_pop( $breadcrumbs );
49 }
50
51 // Only output breadcrumbs that are not hidden.
52 $breadcrumbs = \array_filter( $breadcrumbs, [ $this, 'not_hidden' ] );
53
54 \reset( $breadcrumbs );
55
56 /*
57 * Check whether at least one of the breadcrumbs is broken.
58 * If so, do not output anything.
59 */
60 foreach ( $breadcrumbs as $breadcrumb ) {
61 if ( $this->is_broken( $breadcrumb ) ) {
62 return false;
63 }
64 }
65
66 // Create the last breadcrumb.
67 $last_breadcrumb = \array_pop( $breadcrumbs );
68 $breadcrumbs[] = $this->format_last_breadcrumb( $last_breadcrumb );
69
70 // If this is a static front page, prevent nested pages from creating a trail.
71 if ( $this->helpers->current_page->is_home_static_page() ) {
72
73 // Check if we're dealing with a nested page.
74 if ( \count( $breadcrumbs ) > 1 ) {
75
76 // Store the breadcrumbs home variable before dropping the parent page from the Schema.
77 $breadcrumbs_home = $breadcrumbs[0]['text'];
78 $breadcrumbs = [ \array_pop( $breadcrumbs ) ];
79
80 // Make the child page show the breadcrumbs home variable rather than its own title.
81 $breadcrumbs[0]['text'] = $breadcrumbs_home;
82 }
83 }
84
85 // Create intermediate breadcrumbs.
86 foreach ( $breadcrumbs as $index => $breadcrumb ) {
87 $list_elements[] = $this->create_breadcrumb( $index, $breadcrumb );
88 }
89
90 return [
91 '@type' => 'BreadcrumbList',
92 '@id' => $this->context->canonical . Schema_IDs::BREADCRUMB_HASH,
93 'itemListElement' => $list_elements,
94 ];
95 }
96
97 /**
98 * Returns a breadcrumb array.
99 *
100 * @param int $index The position in the list.
101 * @param array $breadcrumb The position in the list.
102 *
103 * @return array A breadcrumb listItem.
104 */
105 private function create_breadcrumb( $index, $breadcrumb ) {
106 $crumb = [
107 '@type' => 'ListItem',
108 'position' => ( $index + 1 ),
109 'name' => $this->helpers->schema->html->smart_strip_tags( $breadcrumb['text'] ),
110 ];
111
112 if ( ! empty( $breadcrumb['url'] ) ) {
113 $crumb['item'] = $breadcrumb['url'];
114 }
115
116 return $crumb;
117 }
118
119 /**
120 * Creates the last breadcrumb in the breadcrumb list, omitting the URL per Google's spec.
121 *
122 * @link https://developers.google.com/search/docs/data-types/breadcrumb
123 *
124 * @param array $breadcrumb The position in the list.
125 *
126 * @return array The last of the breadcrumbs.
127 */
128 private function format_last_breadcrumb( $breadcrumb ) {
129 unset( $breadcrumb['url'] );
130
131 return $breadcrumb;
132 }
133
134 /**
135 * Tests if the breadcrumb is broken.
136 * A breadcrumb is considered broken:
137 * - when it is not an array.
138 * - when it has no URL or text.
139 *
140 * @param array $breadcrumb The breadcrumb to test.
141 *
142 * @return bool `true` if the breadcrumb is broken.
143 */
144 private function is_broken( $breadcrumb ) {
145 // A breadcrumb is broken if it is not an array.
146 if ( ! \is_array( $breadcrumb ) ) {
147 return true;
148 }
149
150 // A breadcrumb is broken if it does not contain a URL or text.
151 if ( ! \array_key_exists( 'url', $breadcrumb ) || ! \array_key_exists( 'text', $breadcrumb ) ) {
152 return true;
153 }
154
155 return false;
156 }
157
158 /**
159 * Checks whether the breadcrumb is not set to be hidden.
160 *
161 * @param array $breadcrumb The breadcrumb array.
162 *
163 * @return bool If the breadcrumb should not be hidden.
164 */
165 private function not_hidden( $breadcrumb ) {
166 return empty( $breadcrumb['hide_in_schema'] );
167 }
168 }
169