PluginProbe
Redirection / 4.6.2
Redirection v4.6.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.6.2, at modules/wordpress.php

255 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 // The main redirect loop
21 add_action( 'init', [ $this, 'init' ] );
22
23 // Force HTTPs code
24 add_action( 'init', [ $this, 'force_https' ] );
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 force_https() {
108 $options = red_get_options();
109
110 if ( $options['https'] && ! is_ssl() ) {
111 $target = rtrim( parse_url( home_url(), PHP_URL_HOST ), '/' ) . esc_url_raw( Redirection_Request::get_request_url() );
112 add_filter( 'x_redirect_by', [ $this, 'x_redirect_by' ] );
113 wp_safe_redirect( 'https://' . $target, 301 );
114 die();
115 }
116 }
117
118 public function x_redirect_by() {
119 return 'redirection';
120 }
121
122 /**
123 * This is the key to Redirection and where requests are matched to redirects
124 */
125 public function init() {
126 $url = Redirection_Request::get_request_url();
127 $url = apply_filters( 'redirection_url_source', $url );
128 $url = rawurldecode( $url );
129
130 // Make sure we don't try and redirect something essential
131 if ( $url && ! $this->protected_url( $url ) && $this->matched === false ) {
132 do_action( 'redirection_first', $url, $this );
133
134 // Get all redirects that match the URL
135 $redirects = Red_Item::get_for_url( $url );
136
137 // Redirects will be ordered by position. Run through the list until one fires
138 foreach ( (array) $redirects as $item ) {
139 if ( $item->is_match( $url ) ) {
140 $this->matched = $item;
141 break;
142 }
143 }
144
145 do_action( 'redirection_last', $url, $this );
146
147 if ( ! $this->matched ) {
148 // Keep them for later
149 $this->redirects = $redirects;
150 }
151 }
152 }
153
154 /*
155 * Protect certain URLs from being redirected. Note we don't need to protect wp-admin, as this code doesn't run there
156 */
157 private function protected_url( $url ) {
158 $rest = wp_parse_url( red_get_rest_api() );
159 $rest_api = $rest['path'] . ( isset( $rest['query'] ) ? '?' . $rest['query'] : '' );
160
161 if ( substr( $url, 0, strlen( $rest_api ) ) === $rest_api ) {
162 // Never redirect the REST API
163 return true;
164 }
165
166 return false;
167 }
168
169 public function status_header( $status ) {
170 // Fix for incorrect headers sent when using FastCGI/IIS
171 if ( substr( php_sapi_name(), 0, 3 ) === 'cgi' ) {
172 return str_replace( 'HTTP/1.1', 'Status:', $status );
173 }
174
175 return $status;
176 }
177
178 public function send_headers( $obj ) {
179 if ( ! empty( $this->matched ) && $this->matched->action->get_code() === 410 ) {
180 add_filter( 'status_header', [ $this, 'set_header_410' ] );
181 }
182
183 // Add any custom headers
184 $options = red_get_options();
185 $headers = new Red_Http_Headers( $options['headers'] );
186 $headers->run( $headers->get_site_headers() );
187 }
188
189 public function set_header_410() {
190 return 'HTTP/1.1 410 Gone';
191 }
192
193 public function wp_redirect( $url, $status = 302 ) {
194 global $wp_version, $is_IIS;
195
196 $options = red_get_options();
197 $headers = new Red_Http_Headers( $options['headers'] );
198 $headers->run( $headers->get_redirect_headers() );
199
200 if ( $is_IIS ) {
201 header( "Refresh: 0;url=$url" );
202 return $url;
203 }
204
205 if ( $status === 301 && php_sapi_name() === 'cgi-fcgi' ) {
206 $servers_to_check = [ 'lighttpd', 'nginx' ];
207
208 foreach ( $servers_to_check as $name ) {
209 if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stripos( $_SERVER['SERVER_SOFTWARE'], $name ) !== false ) {
210 status_header( $status );
211 header( "Location: $url" );
212 exit( 0 );
213 }
214 }
215 }
216
217 if ( intval( $status, 10 ) === 307 ) {
218 status_header( $status );
219 nocache_headers();
220 return $url;
221 }
222
223 $options = red_get_options();
224
225 // Do we need to set the cache header?
226 if ( ! headers_sent() && isset( $options['redirect_cache'] ) && $options['redirect_cache'] !== 0 && intval( $status, 10 ) === 301 ) {
227 if ( $options['redirect_cache'] === -1 ) {
228 // No cache - just use WP function
229 nocache_headers();
230 } else {
231 // Custom cache
232 header( 'Expires: ' . gmdate( 'D, d M Y H:i:s T', time() + $options['redirect_cache'] * 60 * 60 ) );
233 header( 'Cache-Control: max-age=' . $options['redirect_cache'] * 60 * 60 );
234 }
235 }
236
237 status_header( $status );
238 return $url;
239 }
240
241 public function update( array $data ) {
242 return false;
243 }
244
245 protected function load( $options ) {
246 }
247
248 protected function flush_module() {
249 }
250
251 public function reset() {
252 $this->can_log = true;
253 }
254 }
255