PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.7
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.7
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 / integrations / front-end / wp-robots-integration.php

wp-robots-integration.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 18.7, at src/integrations/front-end/wp-robots-integration.php

204 lines 5.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\Integrations\Front_End;
4
5 use Yoast\WP\SEO\Conditionals\Front_End_Conditional;
6 use Yoast\WP\SEO\Conditionals\WP_Robots_Conditional;
7 use Yoast\WP\SEO\Integrations\Integration_Interface;
8 use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
9 use Yoast\WP\SEO\Presenters\Robots_Presenter;
10
11 /**
12 * Class WP_Robots_Integration
13 *
14 * @package Yoast\WP\SEO\Integrations\Front_End
15 */
16 class WP_Robots_Integration implements Integration_Interface {
17
18 /**
19 * The meta tags context memoizer.
20 *
21 * @var Meta_Tags_Context_Memoizer
22 */
23 protected $context_memoizer;
24
25 /**
26 * Sets the dependencies for this integration.
27 *
28 * @param Meta_Tags_Context_Memoizer $context_memoizer The meta tags context memoizer.
29 */
30 public function __construct( Meta_Tags_Context_Memoizer $context_memoizer ) {
31 $this->context_memoizer = $context_memoizer;
32 }
33
34 /**
35 * Initializes the integration.
36 *
37 * This is the place to register hooks and filters.
38 *
39 * @return void
40 */
41 public function register_hooks() {
42 /**
43 * Allow control of the `wp_robots` filter by prioritizing our hook 10 less than max.
44 * Use the `wpseo_robots` filter to filter the Yoast robots output, instead of WordPress core.
45 */
46 \add_filter( 'wp_robots', [ $this, 'add_robots' ], ( \PHP_INT_MAX - 10 ) );
47 }
48
49 /**
50 * Returns the conditionals based on which this loadable should be active.
51 *
52 * @return array The conditionals.
53 */
54 public static function get_conditionals() {
55 return [
56 Front_End_Conditional::class,
57 WP_Robots_Conditional::class,
58 ];
59 }
60
61 /**
62 * Adds our robots tag value to the WordPress robots tag output.
63 *
64 * @param array $robots The current robots data.
65 *
66 * @return array The robots data.
67 */
68 public function add_robots( $robots ) {
69 if ( ! \is_array( $robots ) ) {
70 return $this->get_robots_value();
71 }
72
73 $merged_robots = \array_merge( $robots, $this->get_robots_value() );
74 $filtered_robots = $this->enforce_robots_congruence( $merged_robots );
75 $sorted_robots = $this->sort_robots( $filtered_robots );
76
77 // Filter all falsy-null robot values.
78 return \array_filter( $sorted_robots );
79 }
80
81 /**
82 * Retrieves the robots key-value pairs.
83 *
84 * @return array The robots key-value pairs.
85 */
86 protected function get_robots_value() {
87 $context = $this->context_memoizer->for_current_page();
88
89 $robots_presenter = new Robots_Presenter();
90 $robots_presenter->presentation = $context->presentation;
91 return $this->format_robots( $robots_presenter->get() );
92 }
93
94 /**
95 * Formats our robots fields, to match the pattern WordPress is using.
96 *
97 * Our format: `[ 'index' => 'noindex', 'max-image-preview' => 'max-image-preview:large', ... ]`
98 * WordPress format: `[ 'noindex' => true, 'max-image-preview' => 'large', ... ]`
99 *
100 * @param array $robots Our robots value.
101 *
102 * @return array The formatted robots.
103 */
104 protected function format_robots( $robots ) {
105 foreach ( $robots as $key => $value ) {
106 // When the entry represents for example: max-image-preview:large.
107 $colon_position = \strpos( $value, ':' );
108 if ( $colon_position !== false ) {
109 $robots[ $key ] = \substr( $value, ( $colon_position + 1 ) );
110
111 continue;
112 }
113
114 // When index => noindex, we want a separate noindex as entry in array.
115 if ( \strpos( $value, 'no' ) === 0 ) {
116 $robots[ $key ] = false;
117 $robots[ $value ] = true;
118
119 continue;
120 }
121
122 // When the key is equal to the value, just make its value a boolean.
123 if ( $key === $value ) {
124 $robots[ $key ] = true;
125 }
126 }
127
128 return $robots;
129 }
130
131 /**
132 * Ensures all other possible robots values are congruent with nofollow and or noindex.
133 *
134 * WordPress might add some robot values again.
135 * When the page is set to noindex we want to filter out these values.
136 *
137 * @param array $robots The robots.
138 *
139 * @return array The filtered robots.
140 */
141 protected function enforce_robots_congruence( $robots ) {
142 if ( ! empty( $robots['nofollow'] ) ) {
143 $robots['follow'] = null;
144 }
145 if ( ! empty( $robots['noarchive'] ) ) {
146 $robots['archive'] = null;
147 }
148 if ( ! empty( $robots['noimageindex'] ) ) {
149 $robots['imageindex'] = null;
150
151 // `max-image-preview` should set be to `none` when `noimageindex` is present.
152 // Using `isset` rather than `! empty` here so that in the rare case of `max-image-preview`
153 // being equal to an empty string due to filtering, its value would still be set to `none`.
154 if ( isset( $robots['max-image-preview'] ) ) {
155 $robots['max-image-preview'] = 'none';
156 }
157 }
158 if ( ! empty( $robots['nosnippet'] ) ) {
159 $robots['snippet'] = null;
160 }
161 if ( ! empty( $robots['noindex'] ) ) {
162 $robots['index'] = null;
163 $robots['imageindex'] = null;
164 $robots['noimageindex'] = null;
165 $robots['archive'] = null;
166 $robots['noarchive'] = null;
167 $robots['snippet'] = null;
168 $robots['nosnippet'] = null;
169 $robots['max-snippet'] = null;
170 $robots['max-image-preview'] = null;
171 $robots['max-video-preview'] = null;
172 }
173
174 return $robots;
175 }
176
177 /**
178 * Sorts the robots array.
179 *
180 * @param array $robots The robots array.
181 *
182 * @return array The sorted robots array.
183 */
184 protected function sort_robots( $robots ) {
185 \uksort(
186 $robots,
187 static function ( $a, $b ) {
188 $order = [
189 'index' => 0,
190 'noindex' => 1,
191 'follow' => 2,
192 'nofollow' => 3,
193 ];
194 $ai = isset( $order[ $a ] ) ? $order[ $a ] : 4;
195 $bi = isset( $order[ $b ] ) ? $order[ $b ] : 4;
196
197 return ( $ai - $bi );
198 }
199 );
200
201 return $robots;
202 }
203 }
204