WP 404 Auto Redirect to Similar Post - Version 0.7.2

Version Description

  • Improved direct match algorythm
  • Improved sanitization of requests with an extension
  • Improved post_type matching to only search "active" post_types
  • Re-introduced Term search as fallback (if no similar post found)
Download this release

Release Info

Developer hwk-fr
Plugin Icon 128x128 WP 404 Auto Redirect to Similar Post
Version 0.7.2
Comparing to
See all releases

Code changes from version 0.7.1 to 0.7.2

Files changed (2) hide show
  1. readme.txt +12 -6
  2. wp-404-auto-redirect-similar-post.php +118 -72
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === WP 404 Auto Redirect to Similar Post ===
2
  Contributors: hwk-fr
3
  Donate link: http://hwk.fr/
4
- Tags: 404, Redirect, 301, Similar Post, SEO, Broken Link, Webmaster Tools
5
  Requires at least: 4.0
6
  Tested up to: 4.8.2
7
- Stable tag: 0.7.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -14,7 +14,7 @@ Automatically Redirect any 404 to a Similar Post based on the Requested URL Titl
14
 
15
  Welcome to WP 404 Auto Redirect to Similar Post!
16
 
17
- This plugin will automatically redirect all your 404 to a similar post based on Title & Post Types. If nothing similar is found, the plugin will redirect the 404 to the homepage.
18
 
19
  = Features: =
20
 
@@ -22,7 +22,7 @@ This plugin will automatically redirect all your 404 to a similar post based on
22
  * Automatically detect any 404
23
  * Automatically search a similar post based on the Title, Post Type, Category & Taxonomy
24
  * **NEW** Choose to Redirect to Homepage if no similar post is found
25
- * **NEW** Choose the redirection HTTP header code: 301 or 302
26
  * **NEW** Debug console for administrators
27
  * **NEW** Preview URL directly from the admin panel
28
 
@@ -46,9 +46,15 @@ This plugin will automatically redirect all your 404 to a similar post based on
46
 
47
  == Changelog ==
48
 
 
 
 
 
 
 
49
  = 0.7.1 =
50
- * Enhanced Post Types handle
51
- * Enhanced Paginated request handle
52
  * Fixed bug while displaying legacy 404
53
  * Fixed PHP notice on preview mode
54
 
1
  === WP 404 Auto Redirect to Similar Post ===
2
  Contributors: hwk-fr
3
  Donate link: http://hwk.fr/
4
+ Tags: SEO, 404, Redirect, 301, Similar, Related, Search, Broken Link, Webmaster Tools, Google
5
  Requires at least: 4.0
6
  Tested up to: 4.8.2
7
+ Stable tag: 0.7.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
14
 
15
  Welcome to WP 404 Auto Redirect to Similar Post!
16
 
17
+ This plugin automatically redirect all your 404 requests to similar posts based on Title & Post Types. If nothing similar is found, it will redirect to the homepage.
18
 
19
  = Features: =
20
 
22
  * Automatically detect any 404
23
  * Automatically search a similar post based on the Title, Post Type, Category & Taxonomy
24
  * **NEW** Choose to Redirect to Homepage if no similar post is found
25
+ * **NEW** Choose the redirection HTTP header status: 301 or 302
26
  * **NEW** Debug console for administrators
27
  * **NEW** Preview URL directly from the admin panel
28
 
46
 
47
  == Changelog ==
48
 
49
+ = 0.7.2 =
50
+ * Improved direct match algorythm
51
+ * Improved sanitization of requests with an extension
52
+ * Improved post_type matching to only search "active" post_types
53
+ * Re-introduced Term search as fallback (if no similar post found)
54
+
55
  = 0.7.1 =
56
+ * Improved Post Types handle
57
+ * Improved paged request handle
58
  * Fixed bug while displaying legacy 404
59
  * Fixed PHP notice on preview mode
60
 
wp-404-auto-redirect-similar-post.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WP 404 Auto Redirect to Similar Post
4
  * Description: Automatically Redirect any 404 to a Similar Post based on the Title, Post Type, Category & Taxonomy using 301 Redirects!
5
  * Author: hwk-fr
6
- * Version: 0.7.1
7
  * Author URI: http://hwk.fr
8
  */
9
 
@@ -222,12 +222,12 @@ function wp404arsp_setup($query){
222
  $query['process']['request'] = $query['request']['full'];
223
 
224
  global $wp_query;
225
- $the_query = $wp_query->query;
226
 
227
- if(isset($the_query['post_type'])){
228
 
229
- $query['process']['post_type'] = $the_query['post_type'];
230
- $post_type = get_post_type_object($the_query['post_type']);
231
  if( stripos($query['request']['full'], $post_type->rewrite['slug']) !== false )
232
  $query['process']['request'] = str_replace('//', '/', substr_replace($query['request']['full'], '', stripos($query['request']['full'], $post_type->rewrite['slug']), strlen($post_type->rewrite['slug'])));
233
 
@@ -239,24 +239,12 @@ function wp404arsp_setup($query){
239
 
240
  $keywords = explode('/', trim($query['process']['request'], '/'));
241
  foreach($keywords as $keyword){
242
- $query['process']['keywords']['explode'][] = str_replace('.' . $query['request']['extension'], '', $keyword);
 
 
 
243
  }
244
  $query['process']['keywords']['explode'] = array_reverse($query['process']['keywords']['explode']);
245
-
246
-
247
- foreach($query['process']['keywords']['explode'] as $keyword){
248
- $get_posts_types = get_post_types(array('public' => true), 'names');
249
- foreach($get_posts_types as $post_type){
250
- if($post = get_page_by_path($keyword, 'object', $post_type))
251
- return wp404arsp_redirect(array_merge( $query, array(
252
- 'score' => 'direct',
253
- 'id' => (int)$post->ID,
254
- 'url' => get_permalink((int)$post->ID),
255
- 'why' => "The request url already exist as post of the post type " . get_post_type((int)$post->ID)
256
- ))
257
- );
258
- }
259
- }
260
 
261
  return wp404arsp_redirect(wp404arsp_search($query));
262
 
@@ -264,43 +252,69 @@ function wp404arsp_setup($query){
264
 
265
  function wp404arsp_search($query){
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  $keywords = explode('-', $query['process']['keywords']['sanitized']);
268
- $post_type = (isset($query['process']['post_type']) && !empty($query['process']['post_type'])) ? $query['process']['post_type'] : '';
269
 
270
- $sql = wp404arsp_search_sql($keywords, '');
271
- if(empty($sql['post']) || $sql['post']['score'] < 1)
272
- return array_merge( $query, array(
273
- 'why' => "Nothing found in DB matching the request url"
274
- )
275
- );
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
- $return = array_merge( $query, array(
278
- 'score' => $sql['post']['score'],
279
- 'id' => (int)$sql['post']['ID'],
280
- 'url' => get_permalink((int)$sql['post']['ID']),
281
- 'why' => "Highest score based on the requested url was found"
282
- )
283
- );
 
284
 
285
- // If Post Type found, check other post types & compare score
286
- if(!empty($post_type)){
287
-
288
- $sql = wp404arsp_search_sql($keywords, $post_type);
289
- if(!empty($sql['post']) && $sql['post']['score'] >= 1 && $sql['post']['score'] >= $return['score']){
290
- $return = array_merge( $query, array(
291
- 'score' => $sql['post']['score'],
292
- 'id' => (int)$sql['post']['ID'],
293
- 'url' => get_permalink((int)$sql['post']['ID']),
294
- 'why' => "Highest score based on the requested url was found"
295
- )
296
- );
297
 
298
- }else{
299
- $return['why'] = "Post type " . $query['process']['post_type'] . " found, but the highest score based on the requested url was found within the post type " . get_post_type($return['id']);
 
 
 
 
 
 
 
 
 
 
 
 
300
 
301
  }
302
-
303
- }
304
 
305
  return $return;
306
 
@@ -331,13 +345,13 @@ function wp404arsp_debug($args){
331
 
332
  $title = '';
333
  if(isset($args['url']) && !empty($args['url'])){
334
- $title = 'Redirection to: ' . "<a href='" . $args['url'] . "'>" . $args['url'] . "</a>" . ' (' . $method . ' Headers)';
335
 
336
  }elseif($wp404arsp_settings['home'] == "1"){
337
  $title = 'Redirect to Home disabled. Displaying 404.';
338
 
339
  }else{
340
- $title = 'Redirection to: ' . "<a href='" . home_url() . "'>" . home_url() . "</a>" . ' (' . $method . ' Headers)';
341
 
342
  }
343
 
@@ -354,40 +368,72 @@ function wp404arsp_debug($args){
354
  <div class="wp404arsp_debug_page">
355
  <?php if(!isset($args['preview'])){ ?>
356
  <h2>WP 404 Auto Redirect to Similar Post</h2>
357
- <p>This is the <strong>debug console</strong> of WP 404 Auto redirect to Similar Post Plugin which is only visible to administrators. If you would like to to disable the Debug mode, please head over your <a href="<?php echo admin_url('options-general.php?page=wp-404-auto-redirect'); ?>">Settings page</a>.</p>
358
  <hr />
359
  <?php } ?>
360
  <pre>Requested URL: <a href="<?php echo home_url(); ?><?php echo $args['request']['full']; ?>"><?php echo home_url(); ?><?php echo $args['request']['full']; ?></a><br />
361
  <?php echo $title; ?><br />
362
- Details: <?php echo $args['why']; ?>
363
- </pre>
364
  <pre><?php print_r($args); ?></pre>
365
  </div>
366
 
367
  <?php echo ob_get_clean(); exit;
368
  }
369
 
370
- function wp404arsp_search_sql($keywords, $post_type = ''){
 
371
  global $wpdb;
 
 
 
 
 
 
 
372
 
373
- $sql = "SELECT p.ID, ";
374
- foreach($keywords as $k){
375
- $sql .= "if(INSTR(LCASE(p.post_name),'" . $k . "'), 1, 0) + ";
376
- }
377
- $sql .= "0 as score FROM " . $wpdb->posts . " AS p
378
- WHERE p.post_status = 'publish' AND ";
379
-
380
- if(!empty($post_type))
381
- $sql .= "p.post_type = '" . $post_type . "'";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
- else
384
- $sql .= "p.post_type <> 'attachment' AND p.post_type <> 'nav_menu_item'";
385
-
386
- $sql .= " ORDER BY score DESC, post_modified DESC LIMIT 1";
 
 
 
 
 
 
 
387
 
388
  return array(
389
- 'post' => $wpdb->get_row($sql, 'ARRAY_A'),
390
- 'dump' => $sql
391
  );
392
  }
393
 
3
  * Plugin Name: WP 404 Auto Redirect to Similar Post
4
  * Description: Automatically Redirect any 404 to a Similar Post based on the Title, Post Type, Category & Taxonomy using 301 Redirects!
5
  * Author: hwk-fr
6
+ * Version: 0.7.2
7
  * Author URI: http://hwk.fr
8
  */
9
 
222
  $query['process']['request'] = $query['request']['full'];
223
 
224
  global $wp_query;
225
+ $current_wp_query = $wp_query->query;
226
 
227
+ if(isset($current_wp_query['post_type'])){
228
 
229
+ $query['process']['post_type'] = $current_wp_query['post_type'];
230
+ $post_type = get_post_type_object($current_wp_query['post_type']);
231
  if( stripos($query['request']['full'], $post_type->rewrite['slug']) !== false )
232
  $query['process']['request'] = str_replace('//', '/', substr_replace($query['request']['full'], '', stripos($query['request']['full'], $post_type->rewrite['slug']), strlen($post_type->rewrite['slug'])));
233
 
239
 
240
  $keywords = explode('/', trim($query['process']['request'], '/'));
241
  foreach($keywords as $keyword){
242
+ if(isset($query['request']['extension']) && !empty($query['request']['extension']))
243
+ $keyword = str_replace('.' . $query['request']['extension'], '', $keyword);
244
+
245
+ $query['process']['keywords']['explode'][] = $keyword;
246
  }
247
  $query['process']['keywords']['explode'] = array_reverse($query['process']['keywords']['explode']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
  return wp404arsp_redirect(wp404arsp_search($query));
250
 
252
 
253
  function wp404arsp_search($query){
254
 
255
+ // Direct
256
+ $get_post_types = get_post_types(array('public' => true), 'names');
257
+ foreach($get_post_types as $post_type){
258
+ if($post = get_page_by_path($query['process']['keywords']['explode'][0], 'object', $post_type))
259
+ return array_merge( $query, array(
260
+ 'score' => 'direct',
261
+ 'id' => (int)$post->ID,
262
+ 'url' => get_permalink((int)$post->ID),
263
+ 'why' => "Part of the requested URL already exist as post of the post_type <strong>" . get_post_type((int)$post->ID) . "</strong>"
264
+ ));
265
+ }
266
+
267
+ // Search
268
  $keywords = explode('-', $query['process']['keywords']['sanitized']);
269
+ $sql = wp404arsp_search_sql(array('keywords' => $keywords));
270
 
271
+ // Term
272
+ if(empty($sql['result']) || $sql['result']['score'] < 1){
273
+ $sql = wp404arsp_search_sql(array('keywords' => $keywords, 'mode' => 'term'));
274
+
275
+ if(empty($sql['result']) || $sql['result']['score'] < 1)
276
+ return array_merge( $query, array(
277
+ 'why' => "Nothing found in DB matching the request url."
278
+ )
279
+ );
280
+
281
+ return array_merge( $query, array(
282
+ 'score' => $sql['result']['score'],
283
+ 'id' => (int)$sql['result']['term_id'],
284
+ 'url' => get_term_link((int)$sql['result']['term_id']),
285
+ 'why' => "No similar post found, but a similar <strong>term</strong> was found."
286
+ )
287
+ );
288
+ }
289
 
290
+ // Post
291
+ $return = array_merge( $query, array(
292
+ 'score' => $sql['result']['score'],
293
+ 'id' => (int)$sql['result']['ID'],
294
+ 'url' => get_permalink((int)$sql['result']['ID']),
295
+ 'why' => "Similar post of post_type <strong>" . get_post_type((int)$sql['result']['ID']) . "</strong> was found."
296
+ )
297
+ );
298
 
299
+ // Post: If Post Type found, check other post types & compare score
300
+ if(isset($query['process']['post_type']) && !empty($query['process']['post_type'])){
 
 
 
 
 
 
 
 
 
 
301
 
302
+ $sql = wp404arsp_search_sql(array('keywords' => $keywords, 'post_type' => $query['process']['post_type']));
303
+ if(!empty($sql['result']) && $sql['result']['score'] >= 1 && $sql['result']['score'] >= $return['score']){
304
+ $return = array_merge( $query, array(
305
+ 'score' => $sql['result']['score'],
306
+ 'id' => (int)$sql['result']['ID'],
307
+ 'url' => get_permalink((int)$sql['result']['ID']),
308
+ 'why' => "Similar post of post_type <strong>" . $query['process']['post_type'] . "</strong> was found."
309
+ )
310
+ );
311
+
312
+ }else{
313
+ $return['why'] = "Post of post_type <strong>" . $query['process']['post_type'] . "</strong> was found, but the highest score was found within the post_type <strong>" . get_post_type($return['id']) . "</strong>";
314
+
315
+ }
316
 
317
  }
 
 
318
 
319
  return $return;
320
 
345
 
346
  $title = '';
347
  if(isset($args['url']) && !empty($args['url'])){
348
+ $title = 'Redirect to: ' . "<a href='" . $args['url'] . "'>" . $args['url'] . "</a>" . ' (' . $method . ' Headers)';
349
 
350
  }elseif($wp404arsp_settings['home'] == "1"){
351
  $title = 'Redirect to Home disabled. Displaying 404.';
352
 
353
  }else{
354
+ $title = 'Redirect to: ' . "<a href='" . home_url() . "'>" . home_url() . "</a>" . ' (' . $method . ' Headers)';
355
 
356
  }
357
 
368
  <div class="wp404arsp_debug_page">
369
  <?php if(!isset($args['preview'])){ ?>
370
  <h2>WP 404 Auto Redirect to Similar Post</h2>
371
+ <p>This is the <strong>debug console</strong> of WP 404 Auto redirect to Similar Post Plugin which is only visible to administrators. Head over your <a href="<?php echo admin_url('options-general.php?page=wp-404-auto-redirect'); ?>">settings page</a> if you would like to disable it.</p>
372
  <hr />
373
  <?php } ?>
374
  <pre>Requested URL: <a href="<?php echo home_url(); ?><?php echo $args['request']['full']; ?>"><?php echo home_url(); ?><?php echo $args['request']['full']; ?></a><br />
375
  <?php echo $title; ?><br />
376
+ Details: <?php echo $args['why']; ?></pre>
 
377
  <pre><?php print_r($args); ?></pre>
378
  </div>
379
 
380
  <?php echo ob_get_clean(); exit;
381
  }
382
 
383
+ function wp404arsp_search_sql($args = array()){
384
+
385
  global $wpdb;
386
+ $args = wp_parse_args($args, array(
387
+ 'keywords' => null,
388
+ 'mode' => null,
389
+ 'post_type' => null,
390
+ ));
391
+
392
+ if(empty($args['mode']) || !empty($args['post_type'])){
393
 
394
+ $sql = "SELECT p.ID, ";
395
+ foreach($args['keywords'] as $k){
396
+ $sql .= "
397
+ if(INSTR(LCASE(p.post_name), '" . $k . "'), 1, 0) + ";
398
+ }
399
+
400
+ $sql .= "0 as score FROM " . $wpdb->posts . " AS p
401
+ WHERE p.post_status = 'publish' AND ";
402
+
403
+ if(!empty($args['post_type'])){
404
+ $sql .= "
405
+ p.post_type = '" . $args['post_type'] . "'";
406
+
407
+ }else{
408
+ $get_post_types = get_post_types(array('public' => true), 'names');
409
+ foreach($get_post_types as $pt){
410
+ $post_types[] = "
411
+ p.post_type = '" . $pt . "'";
412
+ }
413
+ $sql .= '(' . implode(' OR ', $post_types) . ')';
414
+
415
+ }
416
+
417
+ $sql .= "
418
+ ORDER BY score DESC, post_modified DESC LIMIT 1";
419
+
420
+ }elseif($args['mode'] == 'term'){
421
 
422
+ $sql = "SELECT t.term_id, ";
423
+
424
+ foreach($args['keywords'] as $k){
425
+ $sql .= "
426
+ if(INSTR(LCASE(t.slug), '" . $k . "'), 1, 0) + ";
427
+ }
428
+
429
+ $sql .= "
430
+ 0 as score FROM " . $wpdb->terms . " AS t ORDER BY score DESC LIMIT 1";
431
+
432
+ }
433
 
434
  return array(
435
+ 'result' => $wpdb->get_row($sql, 'ARRAY_A'),
436
+ 'dump' => $sql
437
  );
438
  }
439