PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.2
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.2
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 / presenters / breadcrumbs-presenter.php

breadcrumbs-presenter.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 18.2, at src/presenters/breadcrumbs-presenter.php

266 lines 6.5 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\Presenters;
4
5 use Yoast\WP\SEO\Presentations\Indexable_Presentation;
6
7 /**
8 * Presenter class for the breadcrumbs.
9 */
10 class Breadcrumbs_Presenter extends Abstract_Indexable_Presenter {
11
12 /**
13 * The id attribute.
14 *
15 * @var string
16 */
17 private $id;
18
19 /**
20 * The class name attribute.
21 *
22 * @var string
23 */
24 private $class;
25
26 /**
27 * The wrapper element name.
28 *
29 * @var string
30 */
31 private $wrapper;
32
33 /**
34 * Separator to use.
35 *
36 * @var string
37 */
38 private $separator;
39
40 /**
41 * The element.
42 *
43 * @var string
44 */
45 private $element;
46
47 /**
48 * Presents the breadcrumbs.
49 *
50 * @return string The breadcrumbs HTML.
51 */
52 public function present() {
53 $breadcrumbs = $this->get();
54 if ( ! \is_array( $breadcrumbs ) || empty( $breadcrumbs ) ) {
55 return '';
56 }
57
58 $links = [];
59 $total = \count( $breadcrumbs );
60 foreach ( $breadcrumbs as $index => $breadcrumb ) {
61 $links[ $index ] = $this->crumb_to_link( $breadcrumb, $index, $total );
62 }
63
64 // Removes any effectively empty links.
65 $links = \array_map( 'trim', $links );
66 $links = \array_filter( $links );
67 $output = \implode( $this->get_separator(), $links );
68
69 if ( empty( $output ) ) {
70 return '';
71 }
72
73 $output = '<' . $this->get_wrapper() . $this->get_id() . $this->get_class() . '>' . $output . '</' . $this->get_wrapper() . '>';
74 $output = $this->filter( $output );
75
76 $prefix = $this->helpers->options->get( 'breadcrumbs-prefix' );
77 if ( $prefix !== '' ) {
78 $output = "\t" . $prefix . "\n" . $output;
79 }
80
81 return $output;
82 }
83
84 /**
85 * Gets the raw value of a presentation.
86 *
87 * @return array The raw value.
88 */
89 public function get() {
90 return $this->presentation->breadcrumbs;
91 }
92
93 /**
94 * Filters the output.
95 *
96 * @param string $output The HTML output.
97 *
98 * @return string The filtered output.
99 */
100 protected function filter( $output ) {
101 /**
102 * Filter: 'wpseo_breadcrumb_output' - Allow changing the HTML output of the Yoast SEO breadcrumbs class.
103 *
104 * @param Indexable_Presentation $presentation The presentation of an indexable.
105 *
106 * @api string $output The HTML output.
107 */
108 return \apply_filters( 'wpseo_breadcrumb_output', $output, $this->presentation );
109 }
110
111 /**
112 * Create a breadcrumb element string.
113 *
114 * @param array $breadcrumb Link info array containing the keys:
115 * 'text' => (string) link text.
116 * 'url' => (string) link url.
117 * (optional) 'title' => (string) link title attribute text.
118 * @param int $index Index for the current breadcrumb.
119 * @param int $total The total number of breadcrumbs.
120 *
121 * @return string The breadcrumb link.
122 */
123 protected function crumb_to_link( $breadcrumb, $index, $total ) {
124 $link = '';
125
126 if ( ! isset( $breadcrumb['text'] ) || ! \is_string( $breadcrumb['text'] ) || empty( $breadcrumb['text'] ) ) {
127 return $link;
128 }
129
130 $text = \trim( $breadcrumb['text'] );
131
132 if (
133 $index < ( $total - 1 )
134 && isset( $breadcrumb['url'] )
135 && \is_string( $breadcrumb['url'] )
136 && ! empty( $breadcrumb['url'] )
137 ) {
138 // If it's not the last element and we have a url.
139 $link .= '<' . $this->get_element() . '>';
140 $title_attr = isset( $breadcrumb['title'] ) ? ' title="' . \esc_attr( $breadcrumb['title'] ) . '"' : '';
141 $link .= '<a href="' . \esc_url( $breadcrumb['url'] ) . '"' . $title_attr . '>' . $text . '</a>';
142 }
143 elseif ( $index === ( $total - 1 ) ) {
144 // If it's the last element.
145 $inner_elm = 'span';
146 if ( $this->helpers->options->get( 'breadcrumbs-boldlast' ) === true ) {
147 $inner_elm = 'strong';
148 }
149
150 $link .= '<' . $inner_elm . ' class="breadcrumb_last" aria-current="page">' . $text . '</' . $inner_elm . '>';
151 // This is the last element, now close all previous elements.
152 while ( $index > 0 ) {
153 $link .= '</' . $this->get_element() . '>';
154 --$index;
155 }
156 }
157 else {
158 // It's not the last element and has no url.
159 $link .= '<span>' . $text . '</span>';
160 }
161
162 /**
163 * Filter: 'wpseo_breadcrumb_single_link' - Allow changing of each link being put out by the Yoast SEO breadcrumbs class.
164 *
165 * @param array $link The link array.
166 *
167 * @api string $link_output The output string.
168 */
169 return \apply_filters( 'wpseo_breadcrumb_single_link', $link, $breadcrumb );
170 }
171
172 /**
173 * Retrieves HTML ID attribute.
174 *
175 * @return string The id attribute.
176 */
177 protected function get_id() {
178 if ( ! $this->id ) {
179 /**
180 * Filter: 'wpseo_breadcrumb_output_id' - Allow changing the HTML ID on the Yoast SEO breadcrumbs wrapper element.
181 *
182 * @api string $unsigned ID to add to the wrapper element.
183 */
184 $this->id = \apply_filters( 'wpseo_breadcrumb_output_id', '' );
185 if ( ! \is_string( $this->id ) ) {
186 return '';
187 }
188
189 if ( $this->id !== '' ) {
190 $this->id = ' id="' . \esc_attr( $this->id ) . '"';
191 }
192 }
193
194 return $this->id;
195 }
196
197 /**
198 * Retrieves HTML Class attribute.
199 *
200 * @return string The class attribute.
201 */
202 protected function get_class() {
203 if ( ! $this->class ) {
204 /**
205 * Filter: 'wpseo_breadcrumb_output_class' - Allow changing the HTML class on the Yoast SEO breadcrumbs wrapper element.
206 *
207 * @api string $unsigned Class to add to the wrapper element.
208 */
209 $this->class = \apply_filters( 'wpseo_breadcrumb_output_class', '' );
210 if ( ! \is_string( $this->class ) ) {
211 return '';
212 }
213
214 if ( $this->class !== '' ) {
215 $this->class = ' class="' . \esc_attr( $this->class ) . '"';
216 }
217 }
218
219 return $this->class;
220 }
221
222 /**
223 * Retrieves the wrapper element name.
224 *
225 * @return string The wrapper element name.
226 */
227 protected function get_wrapper() {
228 if ( ! $this->wrapper ) {
229 $this->wrapper = \apply_filters( 'wpseo_breadcrumb_output_wrapper', 'span' );
230 $this->wrapper = \tag_escape( $this->wrapper );
231 if ( ! \is_string( $this->wrapper ) || $this->wrapper === '' ) {
232 $this->wrapper = 'span';
233 }
234 }
235
236 return $this->wrapper;
237 }
238
239 /**
240 * Retrieves the separator.
241 *
242 * @return string The separator.
243 */
244 protected function get_separator() {
245 if ( ! $this->separator ) {
246 $this->separator = \apply_filters( 'wpseo_breadcrumb_separator', $this->helpers->options->get( 'breadcrumbs-sep' ) );
247 $this->separator = ' ' . $this->separator . ' ';
248 }
249
250 return $this->separator;
251 }
252
253 /**
254 * Retrieves the crumb element name.
255 *
256 * @return string The element to use.
257 */
258 protected function get_element() {
259 if ( ! $this->element ) {
260 $this->element = \esc_attr( \apply_filters( 'wpseo_breadcrumb_single_link_wrapper', 'span' ) );
261 }
262
263 return $this->element;
264 }
265 }
266