PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 19.0
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v19.0
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 / handle-404.php

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

123 lines 2.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\Integrations\Front_End;
4
5 use Yoast\WP\SEO\Conditionals\Front_End_Conditional;
6 use Yoast\WP\SEO\Integrations\Integration_Interface;
7 use Yoast\WP\SEO\Wrappers\WP_Query_Wrapper;
8
9 /**
10 * Handles intercepting requests.
11 */
12 class Handle_404 implements Integration_Interface {
13
14 /**
15 * The WP Query wrapper.
16 *
17 * @var WP_Query_Wrapper
18 */
19 private $query_wrapper;
20
21 /**
22 * Returns the conditionals based in which this loadable should be active.
23 *
24 * @return array
25 */
26 public static function get_conditionals() {
27 return [ Front_End_Conditional::class ];
28 }
29
30 /**
31 * Initializes the integration.
32 *
33 * This is the place to register hooks and filters.
34 *
35 * @return void
36 */
37 public function register_hooks() {
38 \add_filter( 'pre_handle_404', [ $this, 'handle_404' ] );
39 }
40
41 /**
42 * Handle_404 constructor.
43 *
44 * @codeCoverageIgnore Handles dependencies.
45 *
46 * @param WP_Query_Wrapper $query_wrapper The query wrapper.
47 */
48 public function __construct( WP_Query_Wrapper $query_wrapper ) {
49 $this->query_wrapper = $query_wrapper;
50 }
51
52 /**
53 * Handles the 404 status code.
54 *
55 * @param bool $handled Whether we've handled the request.
56 *
57 * @return bool True if it's 404.
58 */
59 public function handle_404( $handled ) {
60 if ( ! $this->is_feed_404() ) {
61 return $handled;
62 }
63
64 $this->set_404();
65 $this->set_headers();
66
67 \add_filter( 'old_slug_redirect_url', '__return_false' );
68 \add_filter( 'redirect_canonical', '__return_false' );
69
70 return true;
71 }
72
73 /**
74 * If there are no posts in a feed, make it 404 instead of sending an empty RSS feed.
75 *
76 * @return bool True if it's 404.
77 */
78 protected function is_feed_404() {
79 if ( ! \is_feed() ) {
80 return false;
81 }
82
83 $wp_query = $this->query_wrapper->get_query();
84
85 // Don't 404 if the query contains post(s) or an object.
86 if ( $wp_query->posts || $wp_query->get_queried_object() ) {
87 return false;
88 }
89
90 // Don't 404 if it isn't archive or singular.
91 if ( ! $wp_query->is_archive() && ! $wp_query->is_singular() ) {
92 return false;
93 }
94
95 return true;
96 }
97
98 /**
99 * Sets the 404 status code.
100 */
101 protected function set_404() {
102 $wp_query = $this->query_wrapper->get_query();
103 $wp_query->is_feed = false;
104 $wp_query->set_404();
105 $this->query_wrapper->set_query( $wp_query );
106 }
107
108 /**
109 * Sets the headers for http.
110 *
111 * @codeCoverageIgnore
112 */
113 protected function set_headers() {
114 // Overwrite Content-Type header.
115 if ( ! \headers_sent() ) {
116 \header( 'Content-Type: ' . \get_option( 'html_type' ) . '; charset=' . \get_option( 'blog_charset' ) );
117 }
118
119 \status_header( 404 );
120 \nocache_headers();
121 }
122 }
123