PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.8
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.8
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 / redirects.php

redirects.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.8, at src/integrations/front-end/redirects.php

278 lines 7.0 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\Helpers\Current_Page_Helper;
7 use Yoast\WP\SEO\Helpers\Meta_Helper;
8 use Yoast\WP\SEO\Helpers\Options_Helper;
9 use Yoast\WP\SEO\Helpers\Redirect_Helper;
10 use Yoast\WP\SEO\Helpers\Url_Helper;
11 use Yoast\WP\SEO\Integrations\Integration_Interface;
12
13 /**
14 * Class Redirects.
15 */
16 class Redirects implements Integration_Interface {
17
18 /**
19 * The options helper.
20 *
21 * @var Options_Helper
22 */
23 protected $options;
24
25 /**
26 * The meta helper.
27 *
28 * @var Meta_Helper
29 */
30 protected $meta;
31
32 /**
33 * The current page helper.
34 *
35 * @var Current_Page_Helper
36 */
37 protected $current_page;
38
39 /**
40 * The redirect helper.
41 *
42 * @var Redirect_Helper
43 */
44 private $redirect;
45
46 /**
47 * The URL helper.
48 *
49 * @var Url_Helper
50 */
51 private $url;
52
53 /**
54 * Holds the WP_Query variables we should get rid of.
55 *
56 * @var string[]
57 */
58 private $date_query_variables = [
59 'year',
60 'm',
61 'monthnum',
62 'day',
63 'hour',
64 'minute',
65 'second',
66 ];
67
68 /**
69 * Sets the helpers.
70 *
71 * @codeCoverageIgnore
72 *
73 * @param Options_Helper $options Options helper.
74 * @param Meta_Helper $meta Meta helper.
75 * @param Current_Page_Helper $current_page The current page helper.
76 * @param Redirect_Helper $redirect The redirect helper.
77 * @param Url_Helper $url The URL helper.
78 */
79 public function __construct( Options_Helper $options, Meta_Helper $meta, Current_Page_Helper $current_page, Redirect_Helper $redirect, Url_Helper $url ) {
80 $this->options = $options;
81 $this->meta = $meta;
82 $this->current_page = $current_page;
83 $this->redirect = $redirect;
84 $this->url = $url;
85 }
86
87 /**
88 * Returns the conditionals based in which this loadable should be active.
89 *
90 * @return array
91 */
92 public static function get_conditionals() {
93 return [ Front_End_Conditional::class ];
94 }
95
96 /**
97 * Initializes the integration.
98 *
99 * This is the place to register hooks and filters.
100 *
101 * @return void
102 */
103 public function register_hooks() {
104 \add_action( 'wp', [ $this, 'archive_redirect' ] );
105 \add_action( 'wp', [ $this, 'page_redirect' ], 99 );
106 \add_action( 'wp', [ $this, 'category_redirect' ] );
107 \add_action( 'template_redirect', [ $this, 'attachment_redirect' ], 1 );
108 \add_action( 'template_redirect', [ $this, 'disable_date_queries' ] );
109 }
110
111 /**
112 * Disable date queries, if they're disabled in Yoast SEO settings, to prevent indexing the wrong things.
113 *
114 * @return void
115 */
116 public function disable_date_queries() {
117 if ( $this->options->get( 'disable-date', false ) ) {
118 $exploded_url = \explode( '?', $this->url->recreate_current_url(), 2 );
119 list( $base_url, $query_string ) = \array_pad( $exploded_url, 2, '' );
120 \parse_str( $query_string, $query_vars );
121 foreach ( $this->date_query_variables as $variable ) {
122 if ( \in_array( $variable, \array_keys( $query_vars ), true ) ) {
123 $this->do_date_redirect( $query_vars, $base_url );
124 }
125 }
126 }
127 }
128
129 /**
130 * When certain archives are disabled, this redirects those to the homepage.
131 *
132 * @return void
133 */
134 public function archive_redirect() {
135 if ( $this->need_archive_redirect() ) {
136 $this->redirect->do_safe_redirect( \get_bloginfo( 'url' ), 301 );
137 }
138 }
139
140 /**
141 * Based on the redirect meta value, this function determines whether it should redirect the current post / page.
142 *
143 * @return void
144 */
145 public function page_redirect() {
146 if ( ! $this->current_page->is_simple_page() ) {
147 return;
148 }
149
150 $post = \get_post();
151 if ( ! \is_object( $post ) ) {
152 return;
153 }
154
155 $redirect = $this->meta->get_value( 'redirect', $post->ID );
156 if ( $redirect === '' ) {
157 return;
158 }
159
160 $this->redirect->do_safe_redirect( $redirect, 301 );
161 }
162
163 /**
164 * If the option to disable attachment URLs is checked, this performs the redirect to the attachment.
165 *
166 * @return void
167 */
168 public function attachment_redirect() {
169 if ( ! $this->current_page->is_attachment() ) {
170 return;
171 }
172
173 if ( $this->options->get( 'disable-attachment', false ) === false ) {
174 return;
175 }
176
177 $url = $this->get_attachment_url();
178 if ( empty( $url ) ) {
179 return;
180 }
181
182 $this->redirect->do_unsafe_redirect( $url, 301 );
183 }
184
185 /**
186 * Checks if certain archive pages are disabled to determine if a archive redirect is needed.
187 *
188 * @codeCoverageIgnore
189 *
190 * @return bool Whether or not to redirect an archive page.
191 */
192 protected function need_archive_redirect() {
193 if ( $this->options->get( 'disable-date', false ) && $this->current_page->is_date_archive() ) {
194 return true;
195 }
196
197 if ( $this->options->get( 'disable-author', false ) && $this->current_page->is_author_archive() ) {
198 return true;
199 }
200
201 if ( $this->options->get( 'disable-post_format', false ) && $this->current_page->is_post_format_archive() ) {
202 return true;
203 }
204
205 return false;
206 }
207
208 /**
209 * Retrieves the attachment url for the current page.
210 *
211 * @codeCoverageIgnore It wraps WordPress functions.
212 *
213 * @return string The attachment url.
214 */
215 protected function get_attachment_url() {
216 /**
217 * Allows the developer to change the target redirection URL for attachments.
218 *
219 * @since 7.5.3
220 *
221 * @param string $attachment_url The attachment URL for the queried object.
222 * @param object $queried_object The queried object.
223 */
224 return \apply_filters(
225 'wpseo_attachment_redirect_url',
226 \wp_get_attachment_url( \get_queried_object_id() ),
227 \get_queried_object(),
228 );
229 }
230
231 /**
232 * Redirects away query variables that shouldn't work.
233 *
234 * @param array $query_vars The query variables in the current URL.
235 * @param string $base_url The base URL without query string.
236 *
237 * @return void
238 */
239 private function do_date_redirect( $query_vars, $base_url ) {
240 foreach ( $this->date_query_variables as $variable ) {
241 unset( $query_vars[ $variable ] );
242 }
243 $url = $base_url;
244 if ( \count( $query_vars ) > 0 ) {
245 $url .= '?' . \http_build_query( $query_vars );
246 }
247
248 $this->redirect->do_safe_redirect( $url, 301 );
249 }
250
251 /**
252 * Strips `cat=-1` from the URL and redirects to the resulting URL.
253 *
254 * @return void
255 */
256 public function category_redirect() {
257 /**
258 * Allows the developer to keep cat=-1 GET parameters
259 *
260 * @since 19.9
261 *
262 * @param bool $remove_cat_parameter Whether to remove the `cat=-1` GET parameter. Default true.
263 */
264 $should_remove_parameter = \apply_filters( 'wpseo_remove_cat_parameter', true );
265
266 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Data is not processed or saved.
267 if ( $should_remove_parameter && isset( $_GET['cat'] ) && $_GET['cat'] === '-1' ) {
268 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Data is not processed or saved.
269 unset( $_GET['cat'] );
270 if ( isset( $_SERVER['REQUEST_URI'] ) ) {
271 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is just a replace and the data is never saved.
272 $_SERVER['REQUEST_URI'] = \remove_query_arg( 'cat' );
273 }
274 $this->redirect->do_safe_redirect( $this->url->recreate_current_url(), 301, 'Stripping cat=-1 from the URL' );
275 }
276 }
277 }
278