PluginProbe
Redirection / 4.7.2
Redirection v4.7.2
5.10.0 5.9.0 5.8.1 5.8.0 3.7.2 3.7.3 4.0 4.0.1 4.1 4.1.1 4.2 4.2.1 4.2.2 4.2.3 4.3 4.3.1 4.3.2 4.3.3 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6.2 4.7.1 All 130 releases
redirection / modules / wordpress.php

wordpress.php in Redirection 4.7.2, at modules/wordpress.php

254 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class WordPress_Module extends Red_Module {
4 const MODULE_ID = 1;
5
6 private $matched = false;
7 private $can_log = true;
8
9 public function get_id() {
10 return self::MODULE_ID;
11 }
12
13 public function get_name() {
14 return 'WordPress';
15 }
16
17 public function start() {
18 // Only run redirect rules if we're not disabled
19 if ( ! red_is_disabled() ) {
20 // Canonical site settings - https, www, relocate, and aliases
21 add_action( 'init', [ $this, 'canonical_domain' ] );
22
23 // The main redirect loop
24 add_action( 'init', [ $this, 'init' ] );
25
26 // Send site HTTP headers as well as 410 error codes
27 add_action( 'send_headers', [ $this, 'send_headers' ] );
28
29 // Redirect HTTP headers and server-specific overrides
30 add_filter( 'wp_redirect', [ $this, 'wp_redirect' ], 1, 2 );
31 }
32
33 // Setup the various filters and actions that allow Redirection to happen
34 add_action( 'redirection_visit', [ $this, 'redirection_visit' ], 10, 3 );
35 add_action( 'redirection_do_nothing', [ $this, 'redirection_do_nothing' ] );
36
37 // Prevent WordPress overriding a canonical redirect
38 add_filter( 'redirect_canonical', [ $this, 'redirect_canonical' ], 10, 2 );
39
40 // Log 404s and perform 'URL and WordPress page type' redirects
41 add_action( 'template_redirect', [ $this, 'template_redirect' ] );
42 }
43
44 /*
45 * This ensures that a matched URL is not overriddden by WordPress, if the URL happens to be a WordPress URL of some kind
46 * For example: /?author=1 will be redirected to /author/name unless this returns false
47 */
48 public function redirect_canonical( $redirect_url, $requested_url ) {
49 if ( $this->matched ) {
50 return false;
51 }
52
53 return $redirect_url;
54 }
55
56 public function template_redirect() {
57 if ( ! is_404() || $this->matched ) {
58 return;
59 }
60
61 if ( $this->match_404_type() ) {
62 // Don't log an intentionally redirected 404
63 return;
64 }
65
66 $options = red_get_options();
67
68 if ( isset( $options['expire_404'] ) && $options['expire_404'] >= 0 && apply_filters( 'redirection_log_404', $this->can_log ) ) {
69 RE_404::create( Redirection_Request::get_request_url(), Redirection_Request::get_user_agent(), Redirection_Request::get_ip(), Redirection_Request::get_referrer() );
70 }
71 }
72
73 private function match_404_type() {
74 if ( ! property_exists( $this, 'redirects' ) || count( $this->redirects ) === 0 ) {
75 return false;
76 }
77
78 $page_types = array_values( array_filter( $this->redirects, [ $this, 'only_404' ] ) );
79
80 if ( count( $page_types ) > 0 ) {
81 $url = apply_filters( 'redirection_url_source', Redirection_Request::get_request_url() );
82
83 foreach ( $page_types as $page_type ) {
84 if ( $page_type->is_match( $url ) ) {
85 return true;
86 }
87 }
88 }
89
90 return false;
91 }
92
93 private function only_404( $redirect ) {
94 return $redirect->match->get_type() === 'page';
95 }
96
97 // Return true to stop further processing of the 'do nothing'
98 public function redirection_do_nothing() {
99 $this->can_log = false;
100 return true;
101 }
102
103 public function redirection_visit( $redirect, $url, $target ) {
104 $redirect->visit( $url, $target );
105 }
106
107 public function canonical_domain() {
108 $options = red_get_options();
109 $canonical = new Redirection_Canonical( $options['https'], $options['preferred_domain'], $options['aliases'], get_home_url() );
110
111 // Relocate domain?
112 $target = false;
113 if ( $options['relocate'] ) {
114 $target = $canonical->relocate_request( $options['relocate'], Redirection_Request::get_server_name(), Redirection_Request::get_request_url() );
115 }
116
117 // Force HTTPS or www
118 if ( ! $target ) {
119 $target = $canonical->get_redirect( Redirection_Request::get_server_name(), Redirection_Request::get_request_url() );
120 }
121
122 if ( $target ) {
123 add_filter( 'x_redirect_by', [ $this, 'x_redirect_by' ] );
124 // phpcs:ignore
125 wp_redirect( $target, 301 );
126 die();
127 }
128 }
129
130 public function x_redirect_by() {
131 return 'redirection';
132 }
133
134 /**
135 * This is the key to Redirection and where requests are matched to redirects
136 */
137 public function init() {
138 if ( $this->matched ) {
139 return;
140 }
141
142 $request = new Red_Url_Request( Redirection_Request::get_request_url() );
143
144 // Make sure we don't try and redirect something essential
145 if ( $request->is_valid() && ! $request->is_protected_url() ) {
146 do_action( 'redirection_first', $request->get_decoded_url(), $this );
147
148 // Get all redirects that match the URL
149 $redirects = Red_Item::get_for_url( $request->get_decoded_url() );
150
151 // Redirects will be ordered by position. Run through the list until one fires
152 foreach ( (array) $redirects as $item ) {
153 if ( $item->is_match( $request->get_decoded_url(), $request->get_original_url() ) ) {
154 $this->matched = $item;
155 break;
156 }
157 }
158
159 do_action( 'redirection_last', $request->get_decoded_url(), $this );
160
161 if ( ! $this->matched ) {
162 // Keep them for later
163 $this->redirects = $redirects;
164 }
165 }
166 }
167
168 public function status_header( $status ) {
169 // Fix for incorrect headers sent when using FastCGI/IIS
170 if ( substr( php_sapi_name(), 0, 3 ) === 'cgi' ) {
171 return str_replace( 'HTTP/1.1', 'Status:', $status );
172 }
173
174 return $status;
175 }
176
177 public function send_headers( $obj ) {
178 if ( ! empty( $this->matched ) && $this->matched->action->get_code() === 410 ) {
179 add_filter( 'status_header', [ $this, 'set_header_410' ] );
180 }
181
182 // Add any custom headers
183 $options = red_get_options();
184 $headers = new Red_Http_Headers( $options['headers'] );
185 $headers->run( $headers->get_site_headers() );
186 }
187
188 public function set_header_410() {
189 return 'HTTP/1.1 410 Gone';
190 }
191
192 public function wp_redirect( $url, $status = 302 ) {
193 global $wp_version, $is_IIS;
194
195 $options = red_get_options();
196 $headers = new Red_Http_Headers( $options['headers'] );
197 $headers->run( $headers->get_redirect_headers() );
198
199 if ( $is_IIS ) {
200 header( "Refresh: 0;url=$url" );
201 return $url;
202 }
203
204 if ( $status === 301 && php_sapi_name() === 'cgi-fcgi' ) {
205 $servers_to_check = [ 'lighttpd', 'nginx' ];
206
207 foreach ( $servers_to_check as $name ) {
208 if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stripos( $_SERVER['SERVER_SOFTWARE'], $name ) !== false ) {
209 status_header( $status );
210 header( "Location: $url" );
211 exit( 0 );
212 }
213 }
214 }
215
216 if ( intval( $status, 10 ) === 307 ) {
217 status_header( $status );
218 nocache_headers();
219 return $url;
220 }
221
222 $options = red_get_options();
223
224 // Do we need to set the cache header?
225 if ( ! headers_sent() && isset( $options['redirect_cache'] ) && $options['redirect_cache'] !== 0 && intval( $status, 10 ) === 301 ) {
226 if ( $options['redirect_cache'] === -1 ) {
227 // No cache - just use WP function
228 nocache_headers();
229 } else {
230 // Custom cache
231 header( 'Expires: ' . gmdate( 'D, d M Y H:i:s T', time() + $options['redirect_cache'] * 60 * 60 ) );
232 header( 'Cache-Control: max-age=' . $options['redirect_cache'] * 60 * 60 );
233 }
234 }
235
236 status_header( $status );
237 return $url;
238 }
239
240 public function update( array $data ) {
241 return false;
242 }
243
244 protected function load( $options ) {
245 }
246
247 protected function flush_module() {
248 }
249
250 public function reset() {
251 $this->can_log = true;
252 }
253 }
254