PluginProbe
Redirection / 4.5
Redirection v4.5
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.5, at modules/wordpress.php

247 lines 6.7 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 add_action( 'init', [ $this, 'init' ] );
21 add_action( 'send_headers', [ $this, 'send_headers' ] );
22 add_action( 'init', [ $this, 'force_https' ] );
23 add_filter( 'wp_redirect', [ $this, 'wp_redirect' ], 2 );
24 }
25
26 // Setup the various filters and actions that allow Redirection to happen
27 add_action( 'redirection_visit', [ $this, 'redirection_visit' ], 10, 3 );
28 add_action( 'redirection_do_nothing', [ $this, 'redirection_do_nothing' ] );
29 add_filter( 'redirect_canonical', [ $this, 'redirect_canonical' ], 10 );
30 add_action( 'template_redirect', [ $this, 'template_redirect' ] );
31
32 // Remove WordPress 2.3 redirection
33 remove_action( 'template_redirect', 'wp_old_slug_redirect' );
34 }
35
36 /**
37 * This ensures that a matched URL is not overriddden by WordPress, if the URL happens to be a WordPress URL of some kind
38 * For example: /?author=1 will be redirected to /author/name unless this returns false
39 */
40 public function redirect_canonical( $redirect_url, $requested_url ) {
41 if ( $this->matched ) {
42 return false;
43 }
44
45 return $redirect_url;
46 }
47
48 public function template_redirect() {
49 if ( ! is_404() || $this->matched ) {
50 return;
51 }
52
53 if ( $this->match_404_type() ) {
54 // Don't log an intentionally redirected 404
55 return;
56 }
57
58 $options = red_get_options();
59
60 if ( isset( $options['expire_404'] ) && $options['expire_404'] >= 0 && apply_filters( 'redirection_log_404', $this->can_log ) ) {
61 RE_404::create( Redirection_Request::get_request_url(), Redirection_Request::get_user_agent(), Redirection_Request::get_ip(), Redirection_Request::get_referrer() );
62 }
63 }
64
65 private function match_404_type() {
66 if ( ! property_exists( $this, 'redirects' ) || count( $this->redirects ) === 0 ) {
67 return false;
68 }
69
70 $page_types = array_values( array_filter( $this->redirects, [ $this, 'only_404' ] ) );
71
72 if ( count( $page_types ) > 0 ) {
73 $url = apply_filters( 'redirection_url_source', Redirection_Request::get_request_url() );
74
75 foreach ( $page_types as $page_type ) {
76 if ( $page_type->is_match( $url ) ) {
77 return true;
78 }
79 }
80 }
81
82 return false;
83 }
84
85 private function only_404( $redirect ) {
86 return $redirect->match->get_type() === 'page';
87 }
88
89 // Return true to stop further processing of the 'do nothing'
90 public function redirection_do_nothing() {
91 $this->can_log = false;
92 return true;
93 }
94
95 public function redirection_visit( $redirect, $url, $target ) {
96 $redirect->visit( $url, $target );
97 }
98
99 public function force_https() {
100 $options = red_get_options();
101
102 if ( $options['https'] && ! is_ssl() ) {
103 $target = rtrim( parse_url( home_url(), PHP_URL_HOST ), '/' ) . esc_url_raw( Redirection_Request::get_request_url() );
104 add_filter( 'x_redirect_by', [ $this, 'x_redirect_by' ] );
105 wp_safe_redirect( 'https://' . $target, 301 );
106 die();
107 }
108 }
109
110 public function x_redirect_by() {
111 return 'redirection';
112 }
113
114 /**
115 * This is the key to Redirection and where requests are matched to redirects
116 */
117 public function init() {
118 $url = Redirection_Request::get_request_url();
119 $url = apply_filters( 'redirection_url_source', $url );
120 $url = rawurldecode( $url );
121
122 // Make sure we don't try and redirect something essential
123 if ( $url && ! $this->protected_url( $url ) && $this->matched === false ) {
124 do_action( 'redirection_first', $url, $this );
125
126 // Get all redirects that match the URL
127 $redirects = Red_Item::get_for_url( $url );
128
129 // Redirects will be ordered by position. Run through the list until one fires
130 foreach ( (array) $redirects as $item ) {
131 if ( $item->is_match( $url ) ) {
132 $this->matched = $item;
133 break;
134 }
135 }
136
137 do_action( 'redirection_last', $url, $this );
138
139 if ( ! $this->matched ) {
140 // Keep them for later
141 $this->redirects = $redirects;
142 }
143 }
144 }
145
146 /**
147 * Protect certain URLs from being redirected. Note we don't need to protect wp-admin, as this code doesn't run there
148 */
149 private function protected_url( $url ) {
150 $rest = wp_parse_url( red_get_rest_api() );
151 $rest_api = $rest['path'] . ( isset( $rest['query'] ) ? '?' . $rest['query'] : '' );
152
153 if ( substr( $url, 0, strlen( $rest_api ) ) === $rest_api ) {
154 // Never redirect the REST API
155 return true;
156 }
157
158 return false;
159 }
160
161 public function status_header( $status ) {
162 // Fix for incorrect headers sent when using FastCGI/IIS
163 if ( substr( php_sapi_name(), 0, 3 ) === 'cgi' ) {
164 return str_replace( 'HTTP/1.1', 'Status:', $status );
165 }
166
167 return $status;
168 }
169
170 public function send_headers( $obj ) {
171 if ( ! empty( $this->matched ) && $this->matched->action->get_code() === 410 ) {
172 add_filter( 'status_header', [ $this, 'set_header_410' ] );
173 }
174
175 // Add any custom headers
176 $options = red_get_options();
177 $headers = new Red_Http_Headers( $options['headers'] );
178 $headers->run( $headers->get_site_headers() );
179 }
180
181 public function set_header_410() {
182 return 'HTTP/1.1 410 Gone';
183 }
184
185 public function wp_redirect( $url, $status = 302 ) {
186 global $wp_version, $is_IIS;
187
188 $options = red_get_options();
189 $headers = new Red_Http_Headers( $options['headers'] );
190 $headers->run( $headers->get_redirect_headers() );
191
192 if ( $is_IIS ) {
193 header( "Refresh: 0;url=$url" );
194 return $url;
195 }
196
197 if ( $status === 301 && php_sapi_name() === 'cgi-fcgi' ) {
198 $servers_to_check = [ 'lighttpd', 'nginx' ];
199
200 foreach ( $servers_to_check as $name ) {
201 if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stripos( $_SERVER['SERVER_SOFTWARE'], $name ) !== false ) {
202 status_header( $status );
203 header( "Location: $url" );
204 exit( 0 );
205 }
206 }
207 }
208
209 if ( intval( $status, 10 ) === 307 ) {
210 status_header( $status );
211 nocache_headers();
212 return $url;
213 }
214
215 $options = red_get_options();
216
217 // Do we need to set the cache header?
218 if ( ! headers_sent() && isset( $options['redirect_cache'] ) && $options['redirect_cache'] !== 0 && intval( $status, 10 ) === 301 ) {
219 if ( $options['redirect_cache'] === -1 ) {
220 // No cache - just use WP function
221 nocache_headers();
222 } else {
223 // Custom cache
224 header( 'Expires: ' . gmdate( 'D, d M Y H:i:s T', time() + $options['redirect_cache'] * 60 * 60 ) );
225 header( 'Cache-Control: max-age=' . $options['redirect_cache'] * 60 * 60 );
226 }
227 }
228
229 status_header( $status );
230 return $url;
231 }
232
233 public function update( array $data ) {
234 return false;
235 }
236
237 protected function load( $options ) {
238 }
239
240 protected function flush_module() {
241 }
242
243 public function reset() {
244 $this->can_log = true;
245 }
246 }
247