PluginProbe
Redirection / 2.6.3
Redirection v2.6.3
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 / models / redirect.php

redirect.php in Redirection 2.6.3, at models/redirect.php

448 lines 13.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Red_Item {
4 private $id = null;
5 private $created;
6 private $referrer;
7 private $url = null;
8 private $regex = false;
9 private $action_data = null;
10 private $action_code = 0;
11 private $action_type;
12 private $match_type;
13 private $title;
14 private $last_access = null;
15 private $last_count = 0;
16 private $tracking = true;
17 private $status;
18 private $position;
19 private $group_id;
20
21 function __construct( $values, $type = '', $match = '' ) {
22 if ( is_object( $values ) ) {
23 foreach ( $values as $key => $value ) {
24 $this->$key = $value;
25 }
26
27 if ( $this->match_type === '' ) {
28 $this->match_type = 'url';
29 }
30
31 $this->regex = (bool)$this->regex;
32 $this->match = Red_Match::create( $this->match_type, $this->action_data );
33 $this->match->id = $this->id;
34 $this->match->action_code = $this->action_code;
35
36 $action = false;
37
38 if ( $this->action_type ) {
39 $action = Red_Action::create( $this->action_type, $this->action_code );
40 }
41
42 if ( $action ) {
43 $this->action = $action;
44 $this->match->action = $this->action;
45 }
46 else
47 $this->action = Red_Action::create( 'nothing', 0 );
48
49 if ( $this->last_access === '0000-00-00 00:00:00' )
50 $this->last_access = 0;
51 else
52 $this->last_access = mysql2date( 'U', $this->last_access );
53 }
54 else {
55 $this->url = $values;
56 $this->type = $type;
57 $this->match = $match;
58 }
59 }
60
61 static function get_all_for_module( $module ) {
62 global $wpdb;
63
64 $sql = $wpdb->prepare( "SELECT {$wpdb->prefix}redirection_items.*,{$wpdb->prefix}redirection_groups.tracking FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id AND {$wpdb->prefix}redirection_groups.status='enabled' AND {$wpdb->prefix}redirection_groups.module_id=%d WHERE {$wpdb->prefix}redirection_items.status='enabled' ORDER BY {$wpdb->prefix}redirection_groups.position,{$wpdb->prefix}redirection_items.position", $module );
65
66 $rows = $wpdb->get_results( $sql );
67 $items = array();
68 if ( count( $rows ) > 0 ) {
69 foreach ( $rows as $row ) {
70 $items[] = new Red_Item( $row );
71 }
72 }
73
74 return $items;
75 }
76
77 static function get_for_url( $url, $type ) {
78 global $wpdb;
79
80 $sql = $wpdb->prepare( "SELECT {$wpdb->prefix}redirection_items.*,{$wpdb->prefix}redirection_groups.position AS group_pos FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id AND {$wpdb->prefix}redirection_groups.status='enabled' AND {$wpdb->prefix}redirection_groups.module_id=%d WHERE ({$wpdb->prefix}redirection_items.regex=1 OR {$wpdb->prefix}redirection_items.url=%s)", WordPress_Module::MODULE_ID, $url );
81
82 $rows = $wpdb->get_results( $sql );
83 $items = array();
84 if ( count( $rows ) > 0 ) {
85 foreach ( $rows as $row ) {
86 $items[] = array( 'position' => ( $row->group_pos * 1000 ) + $row->position, 'item' => new Red_Item( $row ) );
87 }
88 }
89
90 usort( $items, array( 'Red_Item', 'sort_urls' ) );
91 $items = array_map( array( 'Red_Item', 'reduce_sorted_items' ), $items );
92
93 // Sort it in PHP
94 ksort( $items );
95 $items = array_values( $items );
96 return $items;
97 }
98
99 static function sort_urls( $first, $second ) {
100 if ( $first['position'] === $second['position'] )
101 return 0;
102
103 return ($first['position'] < $second['position']) ? -1 : 1;
104 }
105
106 static function reduce_sorted_items( $item ) {
107 return $item['item'];
108 }
109
110 static function get_by_module( $module ) {
111 global $wpdb;
112
113 $sql = "SELECT {$wpdb->prefix}redirection_items.* FROM {$wpdb->prefix}redirection_items INNER JOIN {$wpdb->prefix}redirection_groups ON {$wpdb->prefix}redirection_groups.id={$wpdb->prefix}redirection_items.group_id";
114 $sql .= $wpdb->prepare( " WHERE {$wpdb->prefix}redirection_groups.module_id=%d", $module );
115
116 $rows = $wpdb->get_results( $sql );
117 $items = array();
118
119 foreach ( (array) $rows as $row ) {
120 $items[] = new Red_Item( $row );
121 }
122
123 return $items;
124 }
125
126 static function get_by_id( $id ) {
127 global $wpdb;
128
129 $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}redirection_items WHERE id=%d", $id ) );
130 if ( $row )
131 return new Red_Item( $row );
132 return false;
133 }
134
135 static function auto_generate() {
136 $options = red_get_options();
137 $id = time();
138
139 $url = $options['auto_target'];
140 $url = str_replace( '$dec$', $id, $url );
141 $url = str_replace( '$hex$', sprintf( '%x', $id ), $url );
142 return $url;
143 }
144
145 static function create( array $details ) {
146 global $wpdb;
147
148 $details = array_map( 'trim', $details );
149 $details = array_map( 'stripslashes', $details );
150
151 // Auto generate URLs
152 if ( empty( $details['source'] ) )
153 $details['source'] = self::auto_generate();
154
155 if ( empty( $details['target'] ) )
156 $details['target'] = self::auto_generate();
157
158 // Make sure we don't redirect to ourself
159 if ( $details['source'] === $details['target'] )
160 return new WP_Error( 'redirect-add', __( 'Source and target URL must be different', 'redirection' ) );
161
162 $parsed_url = parse_url( $details['source'] );
163 $parsed_domain = parse_url( site_url() );
164
165 if ( isset( $parsed_url['scheme'] ) && ( $parsed_url['scheme'] === 'http' || $parsed_url['scheme'] === 'https' ) && $parsed_url['host'] !== $parsed_domain['host'] ) {
166 return new WP_Error( 'redirect-add', sprintf( __( 'You can only redirect from a relative URL (<code>%s</code>) on this domain (<code>%s</code>).', 'redirection' ), isset( $parsed_url['path'] ) ? $parsed_url['path'] : '', $parsed_domain['host'] ) );
167 }
168
169 $matcher = Red_Match::create( $details['match'] );
170 $group_id = intval( $details['group_id'] );
171 $group = Red_Group::get( $group_id );
172
173 if ( $group_id <= 0 || ! $group )
174 return new WP_Error( 'redirect-add', __( 'Invalid group when creating redirect', 'redirection' ) );
175
176 if ( ! $matcher )
177 return new WP_Error( 'redirect-add', __( 'Invalid source URL when creating redirect for given match type', 'redirection' ) );
178
179 $regex = ( isset( $details['regex'] ) && (bool) $details['regex'] !== false ) ? 1 : 0;
180 $position = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}redirection_items WHERE group_id=%d", $group_id ) );
181
182 $action = $details['red_action'];
183 $action_code = 0;
184 if ( $action === 'url' || $action === 'random' )
185 $action_code = 301;
186 elseif ( $action === 'error' )
187 $action_code = 404;
188
189 if ( isset( $details['action_code'] ) && get_status_header_desc( $details['action_code'] ) !== '' ) {
190 $action_code = intval( $details['action_code'] );
191 }
192
193 $data = array(
194 'url' => self::sanitize_url( $details['source'], $regex ),
195 'action_type' => $details['red_action'],
196 'regex' => $regex,
197 'position' => $position,
198 'match_type' => $details['match'],
199 'action_data' => $matcher->data( $details ),
200 'action_code' => $action_code,
201 'last_access' => '0000-00-00 00:00:00',
202 'group_id' => $group_id,
203 );
204
205 $data = apply_filters( 'redirection_create_redirect', $data );
206
207 $wpdb->delete( $wpdb->prefix.'redirection_items', array( 'url' => $data['action_data'], 'action_type' => $data['action_type'], 'action_data' => $data['url'] ) );
208
209 if ( $wpdb->insert( $wpdb->prefix.'redirection_items', $data ) ) {
210 Red_Module::flush( $group_id );
211 return self::get_by_id( $wpdb->insert_id );
212 }
213
214 return new WP_Error( 'redirect-add', __( 'Unable to add new redirect - delete Redirection from the options page and re-install' ) );
215 }
216
217 public static function disable_where_matches( $url ) {
218 global $wpdb;
219
220 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => 'disabled' ), array( 'url' => $url ) );
221 }
222
223 public function delete() {
224 global $wpdb;
225
226 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}redirection_items WHERE id=%d", $this->id ) );
227
228 RE_Log::delete_for_id( $this->id );
229
230 // Reorder all elements
231 $rows = $wpdb->get_results( "SELECT id FROM {$wpdb->prefix}redirection_items ORDER BY position" );
232 if ( count( $rows ) > 0 ) {
233 foreach ( $rows as $pos => $row ) {
234 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'position' => $pos ), array( 'id' => $row->id ) );
235 }
236 }
237
238 Red_Module::flush( $this->group_id );
239 }
240
241 static function sanitize_url( $url, $regex = false ) {
242 // Make sure that the old URL is relative
243 $url = preg_replace( '@^https?://(.*?)/@', '/', $url );
244 $url = preg_replace( '@^https?://(.*?)$@', '/', $url );
245
246 // No hash
247 $url = preg_replace( '/#.*$/', '', $url );
248
249 // No new lines
250 $url = preg_replace( "/[\r\n\t].*?$/s", '', $url );
251
252 // Clean control codes
253 $url = preg_replace( '/[^\PC\s]/u', '', $url );
254
255 // Ensure a slash at start
256 if ( substr( $url, 0, 1 ) !== '/' && $regex === false )
257 $url = '/'.$url;
258
259 return $url;
260 }
261
262 function update( $details ) {
263 if ( strlen( $details['old'] ) > 0 ) {
264 global $wpdb;
265
266 $details = array_map( 'stripslashes', $details );
267
268 $this->regex = isset( $details['regex'] ) ? 1 : 0;
269 $this->url = self::sanitize_url( $details['old'], $this->regex );
270 $this->title = $details['title'];
271
272 $data = $this->match->data( $details );
273
274 $this->action_code = 0;
275 if ( isset( $details['action_code'] ) )
276 $this->action_code = intval( $details['action_code'] );
277
278 $old_group = false;
279 if ( isset( $details['group_id'] ) ) {
280 $old_group = intval( $this->group_id );
281 $this->group_id = intval( $details['group_id'] );
282 }
283
284 // Save this
285 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'url' => $this->url, 'regex' => $this->regex, 'action_code' => $this->action_code, 'action_data' => $data, 'group_id' => $this->group_id, 'title' => $this->title ), array( 'id' => $this->id ) );
286
287 Red_Module::flush( $this->group_id );
288
289 if ( $old_group !== $this->group_id ) {
290 Red_Module::flush( $old_group );
291 }
292 }
293 }
294
295 static function save_order( $items, $start ) {
296 global $wpdb;
297
298 foreach ( $items as $pos => $id ) {
299 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'position' => $pos + $start ), array( 'id' => $id ) );
300 }
301
302 Red_Module::flush( $this->group_id );
303 }
304
305 function matches( $url ) {
306 $this->url = str_replace( ' ', '%20', $this->url );
307 $matches = false;
308
309 // Check if we match the URL
310 if ( ( $this->regex === false && ( $this->url === $url || $this->url === rtrim( $url, '/' ) || $this->url === urldecode( $url ) ) ) || ( $this->regex === true && @preg_match( '@'.str_replace( '@', '\\@', $this->url ).'@', $url, $matches ) > 0) || ( $this->regex === true && @preg_match( '@'.str_replace( '@', '\\@', $this->url ).'@', urldecode( $url ), $matches ) > 0) ) {
311 // Check if our match wants this URL
312 $target = $this->match->get_target( $url, $this->url, $this->regex );
313 $target = apply_filters( 'redirection_url_target', $target, $this->url );
314
315 if ( $target && $this->is_enabled() ) {
316 $this->visit( $url, $target );
317 return $this->action->process_before( $this->action_code, $target );
318 }
319 }
320
321 return false;
322 }
323
324 function visit( $url, $target ) {
325 if ( $this->tracking && $this->id ) {
326 global $wpdb;
327
328 // Update the counters
329 $count = $this->last_count + 1;
330 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}redirection_items SET last_count=%d, last_access=NOW() WHERE id=%d", $count, $this->id ) );
331
332 $options = red_get_options();
333 if ( isset( $options['expire_redirect'] ) && $options['expire_redirect'] >= 0 ) {
334 $log = RE_Log::create( $url, $target, Redirection_Request::get_user_agent(), Redirection_Request::get_ip(), Redirection_Request::get_referrer(), array( 'redirect_id' => $this->id, 'group_id' => $this->group_id ) );
335 }
336 }
337 }
338
339 public function is_enabled() {
340 return $this->status === 'enabled';
341 }
342
343 function reset() {
344 global $wpdb;
345
346 $this->last_count = 0;
347 $this->last_access = '0000-00-00 00:00:00';
348
349 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'last_count' => 0, 'last_access' => $this->last_access ), array( 'id' => $this->id ) );
350
351 RE_Log::delete_for_id( $this->id );
352 }
353
354 function move_to( $group ) {
355 global $wpdb;
356
357 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'group_id' => $group ), array( 'id' => $this->id ) );
358 }
359
360 public function enable() {
361 global $wpdb;
362
363 $this->status = 'enabled';
364 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
365 }
366
367 public function disable() {
368 global $wpdb;
369
370 $this->status = 'disabled';
371 $wpdb->update( $wpdb->prefix.'redirection_items', array( 'status' => $this->status ), array( 'id' => $this->id ) );
372 }
373
374 static function actions( $action = '' ) {
375 $actions = array(
376 'url' => __( 'Redirect to URL', 'redirection' ),
377 'random' => __( 'Redirect to random post', 'redirection' ),
378 'pass' => __( 'Pass-through', 'redirection' ),
379 'error' => __( 'Error (404)', 'redirection' ),
380 'nothing' => __( 'Do nothing', 'redirection' ),
381 );
382
383 if ( $action )
384 return $actions[ $action ];
385 return $actions;
386 }
387
388 function match_name() {
389 return $this->match->match_name();
390 }
391
392 function type() {
393 if ( ( $this->action_type === 'url' || $this->action_type === 'error' || $this->action_type === 'random' ) && $this->action_code > 0 )
394 return $this->action_code;
395 else if ( $this->action_type === 'pass' )
396 return 'pass';
397 return '&mdash;';
398 }
399
400 public function get_id() {
401 return $this->id;
402 }
403
404 public function get_position() {
405 return $this->position;
406 }
407
408 public function get_group_id() {
409 return $this->group_id;
410 }
411
412 public function get_url() {
413 return $this->url;
414 }
415
416 public function get_title() {
417 return $this->title;
418 }
419
420 public function get_hits() {
421 return $this->last_count;
422 }
423
424 public function get_last_hit() {
425 return $this->last_access;
426 }
427
428 public function is_regex() {
429 return $this->regex ? true : false;
430 }
431
432 public function get_match_type() {
433 return $this->match_type;
434 }
435
436 public function get_action_type() {
437 return $this->action_type;
438 }
439
440 public function get_action_code() {
441 return intval( $this->action_code );
442 }
443
444 public function get_action_data() {
445 return $this->action_data;
446 }
447 }
448