WP 404 Auto Redirect to Similar Post - Version 0.7.6

Version Description

  • Added "Custom Redirect URL" as Fallback Behavior (Feature Request)
  • Added "Exclude Post Type" Multi-select to possible redirections (Feature Request)
  • Fixed Typos & added better descriptions
  • Better overall request validation
  • Fixed minor PHP Notice
Download this release

Release Info

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

Code changes from version 0.7.2 to 0.7.6

assets/admin.css ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #wp404arsp_settings #wp404arsp_settings_fallback_url{
2
+ width:330px;
3
+ }
4
+
5
+ #wp404arsp_settings #wp404arsp_settings_fallback_url.disabled{
6
+ pointer-events:none;
7
+ }
8
+
9
+ #wp404arsp_settings #wp404arsp_settings_rules_redirection_exclude_post_types{
10
+ width:300px;
11
+ }
12
+
13
+ #wp404arsp_settings #wp404arsp_settings_redirection_preview .request{
14
+ width:500px;
15
+ }
16
+
17
+ #wp404arsp_settings p.submit{
18
+ padding:0;
19
+ }
20
+
21
+ #wp404arsp_settings p.submit .loading.spinner{
22
+ float:none;
23
+ vertical-align:top;
24
+ }
25
+
26
+ #wp404arsp_settings #postbox-container-1 .logo{
27
+ max-width:100%;
28
+ height:auto;
29
+ margin:20px auto 30px;
30
+ display:block;
31
+ }
assets/admin.js ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($){
2
+ var ajaxurl = '/wp-admin/admin-ajax.php';
3
+
4
+ if($('[name="wp404arsp_settings[fallback][type]"]').length > 0 && $('[name="wp404arsp_settings[fallback][url]"]').length > 0 && $('[name="wp404arsp_settings[fallback][home_url]"]').length > 0){
5
+ $('[name="wp404arsp_settings[fallback][type]"]').change(function(){
6
+
7
+ $('[name="wp404arsp_settings[fallback][url]"]').val($('[name="wp404arsp_settings[fallback][home_url]"]').val());
8
+ $('[name="wp404arsp_settings[fallback][url]"]').prop('readOnly', true);
9
+ $('[name="wp404arsp_settings[fallback][url]"]').removeClass('hidden');
10
+ $('[name="wp404arsp_settings[fallback][url]"]').addClass('disabled');
11
+
12
+ if($(this).val() == 'custom'){
13
+ $('[name="wp404arsp_settings[fallback][url]"]').prop('readOnly', false);
14
+ $('[name="wp404arsp_settings[fallback][url]"]').removeClass('disabled');
15
+
16
+ }else if($(this).val() == 'disabled'){
17
+ $('[name="wp404arsp_settings[fallback][url]"]').addClass('hidden');
18
+
19
+ }
20
+ });
21
+ }
22
+
23
+ if($('#wp404arsp_settings_redirection_preview').length > 0){
24
+ $('#wp404arsp_settings_redirection_preview .button').click(function(){
25
+ $button = $(this);
26
+ $loading = $('#wp404arsp_settings_redirection_preview .loading');
27
+ $button.prop('disabled', true);
28
+ $loading.addClass('is-active');
29
+ $request = $('#wp404arsp_settings_redirection_preview input[type=text]').val();
30
+ if($request.length == 0)
31
+ return;
32
+
33
+ if($request.substring(0,1) != '/'){
34
+ $request = '/' + $request;
35
+ $('#wp404arsp_settings_redirection_preview input[type=text]').val($request)
36
+ }
37
+
38
+ data = {
39
+ action: 'wp404arsp_ajax_test',
40
+ request: $request,
41
+ };
42
+ $.post(ajaxurl, data)
43
+ .done(function(response){
44
+ $button.prop('disabled', false);
45
+ $loading.removeClass('is-active');
46
+ $('#wp404arsp_settings_redirection_preview .results').html(response);
47
+ });
48
+ });
49
+ }
50
+
51
+ });
logo.png → assets/logo.png RENAMED
File without changes
readme.txt CHANGED
@@ -3,8 +3,8 @@ 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
 
@@ -18,17 +18,36 @@ This plugin automatically redirect all your 404 requests to similar posts based
18
 
19
  = Features: =
20
 
 
 
 
 
 
 
 
 
 
 
21
  * Easy to Install / Uninstall.
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
 
29
- = Requirements: =
 
 
 
30
 
31
- * PHP 5
 
 
 
 
 
 
32
 
33
  == Installation ==
34
 
@@ -41,11 +60,18 @@ This plugin automatically redirect all your 404 requests to similar posts based
41
 
42
  == Screenshots ==
43
 
44
- 1. WP 404 Auto Redirect to Similar Post: Settings Page
45
- 2. WP 404 Auto Redirect to Similar Post: Front Debug Console (for administrators)
46
 
47
  == Changelog ==
48
 
 
 
 
 
 
 
 
49
  = 0.7.2 =
50
  * Improved direct match algorythm
51
  * Improved sanitization of requests with an extension
@@ -62,9 +88,9 @@ This plugin automatically redirect all your 404 requests to similar posts based
62
  * Reworked code
63
  * Added settings page
64
  * Added Debug mode for administrators (settings page)
65
- * Added the ability to disable "Redirect to Homepage" if nothing found (settings page)
66
- * Added the ability to choose between 301 or 302 HTTP Headers (settings page)
67
- * Added the ability preview URL Redirections (settings page)
68
 
69
  = 0.4.0.2 =
70
  * Fixed sanitization bug
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.9.1
7
+ Stable tag: 0.7.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
18
 
19
  = Features: =
20
 
21
+ * Automatically detect any 404.
22
+ * Automatically search a similar post based on the Title, Post Type, Category & Taxonomy.
23
+ * If nothing similar is found, choose your Fallback Behavior: Redirection or Default 404.
24
+ * Choose the redirection HTTP header status: 301 / 302.
25
+ * Exclude one or multiple post types from possible redirections.
26
+ * Debug Console for Admin: Display the Debug Console instead of being redirected.
27
+ * Preview similar post found directly from the admin panel.
28
+
29
+ = But Also: =
30
+
31
  * Easy to Install / Uninstall.
32
+ * No useless data saved in Database.
33
+ * Blazing Fast Performance.
34
+
35
+ = Comptibility: =
36
+
37
+ If you missed a manual redirection and a 404 is about to be displayed, the plugin will take action. Yes, WP 404 Auto Redirect to Similar Post is 100% compatible with all popular redirection plugins:
38
 
39
+ * [Redirection](https://wordpress.org/plugins/redirection/)
40
+ * [Simple 301 Redirects](https://wordpress.org/plugins/simple-301-redirects/)
41
+ * [Yoast Redirections](https://yoast.com/wordpress/plugins/seo/redirects-manager/)
42
+ * etc...
43
 
44
+ == Reviews ==
45
+
46
+ They talk about it! :)
47
+
48
+ * [Quels plugins utiliser pour corriger les erreurs 404 sous WordPress ?](https://sebastienpierrepack.com/plugins-corriger-404-wordpress/)
49
+ * [Permalink Finder Plugin is deprecated](http://bhaaratham.com/permalink-finder-plugin-sanitize_url-is-deprecated/)
50
+ * [Membuat halaman Error 404 menjadi SEO friendly](https://www.seosatu.com/optimalkan-seo-dengan-halaman-404/)
51
 
52
  == Installation ==
53
 
60
 
61
  == Screenshots ==
62
 
63
+ 1. Settings Page
64
+ 2. Front Debug Console (for administrators)
65
 
66
  == Changelog ==
67
 
68
+ = 0.7.6 =
69
+ * Added "Custom Redirect URL" as Fallback Behavior (Feature Request)
70
+ * Added "Exclude Post Type" Multi-select to possible redirections (Feature Request)
71
+ * Fixed Typos & added better descriptions
72
+ * Better overall request validation
73
+ * Fixed minor PHP Notice
74
+
75
  = 0.7.2 =
76
  * Improved direct match algorythm
77
  * Improved sanitization of requests with an extension
88
  * Reworked code
89
  * Added settings page
90
  * Added Debug mode for administrators (settings page)
91
+ * Added the ability to disable "Redirect to Homepage" if nothing found (Feature request)
92
+ * Added the ability to choose between 301 or 302 HTTP Headers
93
+ * Added the ability preview URL Redirections
94
 
95
  = 0.4.0.2 =
96
  * Fixed sanitization bug
wp-404-auto-redirect-similar-post.js DELETED
@@ -1,28 +0,0 @@
1
- jQuery(document).ready(function($){
2
- var ajaxurl = '/wp-admin/admin-ajax.php';
3
-
4
- if($('#wp404arsp_settings_test').length > 0){
5
- $('#wp404arsp_settings_test .button').click(function(){
6
- $request = $('#wp404arsp_settings_test input[type=text]').val();
7
- if($request.length == 0)
8
- return;
9
-
10
- if($request.substring(0,1) != '/'){
11
- $request = '/' + $request;
12
- $('#wp404arsp_settings_test input[type=text]').val($request)
13
- }
14
-
15
- data = {
16
- action: 'wp404arsp_ajax_test',
17
- request: $request,
18
- };
19
- $.post(ajaxurl, data)
20
- .done(
21
- function(response){
22
- $('#wp404arsp_settings_test .results').html(response);
23
- }
24
- );
25
- });
26
- }
27
-
28
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.2
7
  * Author URI: http://hwk.fr
8
  */
9
 
@@ -15,7 +15,8 @@ function wp404arsp_admin_menu(){
15
  $menu = add_submenu_page('options-general.php', 'WP 404 Auto Redirect', 'WP 404 Auto Redirect', 'manage_options', 'wp-404-auto-redirect', 'wp404arsp_admin_page_html');
16
 
17
  add_action('admin_print_scripts-' . $menu, function(){
18
- wp_enqueue_script('wp404arsp_admin_js', plugins_url('wp-404-auto-redirect-similar-post.js', __FILE__), array('jquery'));
 
19
  });
20
 
21
  }
@@ -32,7 +33,7 @@ function wp404arsp_admin_settings(){
32
 
33
  function wp404arsp_admin_page_html(){
34
  ?>
35
- <div class="wrap">
36
  <h1 class="wp-heading-inline">WP 404 Auto Redirect to Similar Post</h1>
37
  <hr class="wp-header-end">
38
 
@@ -48,7 +49,7 @@ function wp404arsp_admin_page_html(){
48
  <?php
49
  settings_fields('wp404arsp_settings');
50
  do_settings_sections('wp404arsp_settings');
51
- $wp404arsp_settings = wp404arsp_get_settings();
52
  ?>
53
 
54
  <div class="inside">
@@ -60,51 +61,110 @@ function wp404arsp_admin_page_html(){
60
  <td>
61
  <fieldset>
62
  <legend class="screen-reader-text"><span>Debug</span></legend>
63
- <label for="wp404arsp_settings[debug]">
64
- <input name="wp404arsp_settings[debug]" id="wp404arsp_settings[debug]" value="1" type="checkbox" <?php if($wp404arsp_settings['debug'] == "1") echo "checked"; ?>>
65
  Activate
66
  </label>
67
  </fieldset>
68
- <p class="description" id="tagline-description">Administrators will get the debug console instead of being redirected.</p>
69
  </td>
70
  </tr>
71
 
72
  <tr>
73
- <th scope="row">Redirect to Home</th>
74
  <td>
75
  <fieldset>
76
- <legend class="screen-reader-text"><span>Do not redirect to Home</span></legend>
77
- <label for="wp404arsp_settings[home]">
78
- <input name="wp404arsp_settings[home]" id="wp404arsp_settings[home]" value="1" type="checkbox" <?php if($wp404arsp_settings['home'] == "1") echo "checked"; ?>>
79
- Disable
80
- </label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </fieldset>
82
- <p class="description" id="tagline-description">Do not redirect to <a href="<?php echo home_url(); ?>"><?php echo home_url(); ?></a> if no similar post is found.</p>
83
  </td>
84
  </tr>
85
 
86
  <tr>
87
  <th scope="row">Redirect Headers</th>
88
  <td>
89
- <select name="wp404arsp_settings[method]" id="wp404arsp_settings[method]">
90
- <option value="" <?php if(!$wp404arsp_settings['method']) echo "selected"; ?>>301 method</option>
91
- <option value="302" <?php if($wp404arsp_settings['method'] == "302") echo "selected"; ?>>302 method</option>
92
- </select>
93
- <p class="description" id="tagline-description">Learn more about <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank">HTTP headers & redirections</a>.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  </td>
95
  </tr>
96
 
97
  </tbody>
98
  </table>
99
 
100
- <p class="submit" style="padding:0;">
101
  <?php submit_button('Save Settings', 'primary', '', false); ?>
102
  </p>
103
  </div>
104
  </form>
105
  </div>
106
 
107
- <div id="wp404arsp_settings_test">
108
  <div class="postbox">
109
  <h2 class="hndle"><span>Redirection Preview</span></h2>
110
  <div class="inside">
@@ -114,15 +174,16 @@ function wp404arsp_admin_page_html(){
114
  <tr>
115
  <th scope="row"><?php echo home_url(); ?></th>
116
  <td>
117
- <input class="request" type="text" value="/example-url" style="width:500px;" />
118
- <p class="description" id="tagline-description">Enter the URL you would like to test, starting with <code>/</code></p>
119
  </td>
120
  </tr>
121
  </tbody>
122
  </table>
123
 
124
- <p class="submit" style="padding:0;">
125
  <?php submit_button('Preview URL', 'secondary', '', false); ?>
 
126
  </p>
127
 
128
  <div class="results"></div>
@@ -140,10 +201,8 @@ function wp404arsp_admin_page_html(){
140
  <div class="postbox">
141
 
142
  <div class="inside">
143
- <img src="<?php echo plugins_url('logo.png', __FILE__); ?>" style="max-width:100%; height:auto; margin:20px auto 30px; display:block;" />
144
-
145
-
146
-
147
  <p>Found a bug? Need help? Head over the <a href="https://wordpress.org/plugins/wp-404-auto-redirect-to-similar-post/" target="_blank">official plugin page</a>.</p>
148
 
149
  <hr />
@@ -167,12 +226,17 @@ function wp404arsp_admin_page_html(){
167
 
168
  add_action('template_redirect', 'wp404arsp_init');
169
  function wp404arsp_init(){
170
-
171
- if( !is_404() || wp_doing_ajax() || is_admin() || $_SERVER['SCRIPT_URI'] == admin_url('admin-ajax.php') || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') )
172
- return;
 
 
 
 
 
 
173
 
174
  wp404arsp_request($_SERVER['REQUEST_URI']);
175
-
176
  }
177
 
178
  function wp404arsp_request($request, $preview = false){
@@ -206,7 +270,7 @@ function wp404arsp_request($request, $preview = false){
206
  if(!empty($query['request']['pagination']))
207
  return wp404arsp_redirect(array_merge( $query, array(
208
  'url' => home_url() . $request_no_pagination,
209
- 'why' => "Pagination found in the requested url. Trying to reach same url without pagination."
210
  ))
211
  );
212
 
@@ -253,16 +317,17 @@ function wp404arsp_setup($query){
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']);
@@ -274,7 +339,7 @@ function wp404arsp_search($query){
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
 
@@ -322,36 +387,41 @@ function wp404arsp_search($query){
322
 
323
  function wp404arsp_redirect($args){
324
 
325
- $wp404arsp_settings = wp404arsp_get_settings();
326
- $method = (!$wp404arsp_settings['method']) ? 301 : $wp404arsp_settings['method'];
327
- $home_url = (!$wp404arsp_settings['home']) ? home_url() : false;
328
 
329
- if( is_user_logged_in() && current_user_can('manage_options') && ($wp404arsp_settings['debug'] || (isset($args['preview']) && $args['preview'])) )
330
  return wp404arsp_debug($args);
331
 
332
- if(isset($args['url']) && !empty($args['url']))
333
- return wp_redirect($args['url'], $method);
 
 
334
 
335
- if($home_url)
336
- return wp_redirect($home_url, $method);
 
 
337
 
338
  return;
339
 
340
  }
341
 
342
  function wp404arsp_debug($args){
343
- $wp404arsp_settings = wp404arsp_get_settings();
344
- $method = (!$wp404arsp_settings['method']) ? 301 : $wp404arsp_settings['method'];
 
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
 
@@ -383,7 +453,8 @@ Details: <?php echo $args['why']; ?></pre>
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,
@@ -405,12 +476,14 @@ function wp404arsp_search_sql($args = array()){
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
 
@@ -455,10 +528,21 @@ function wp404arsp_sanitize($input){
455
  function wp404arsp_get_settings(){
456
  return wp_parse_args(get_option('wp404arsp_settings'),
457
  array(
458
- 'debug' => null,
459
- 'logs' => null,
460
- 'home' => null,
461
- 'method' => null
 
 
 
 
 
 
 
 
 
 
 
462
  )
463
  );
464
  }
@@ -483,10 +567,26 @@ function wp404arsp_remove_stop_words($input){
483
  }
484
  }
485
 
486
- function wp404arsp_search_array($array, $key, $value) {
487
- foreach($array as $k => $v){
488
- if ($v[$key] === $value)
489
- return $k;
490
- }
491
- return null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
  }
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.6
7
  * Author URI: http://hwk.fr
8
  */
9
 
15
  $menu = add_submenu_page('options-general.php', 'WP 404 Auto Redirect', 'WP 404 Auto Redirect', 'manage_options', 'wp-404-auto-redirect', 'wp404arsp_admin_page_html');
16
 
17
  add_action('admin_print_scripts-' . $menu, function(){
18
+ wp_enqueue_script('wp404arsp_admin_js', plugins_url('assets/admin.js', __FILE__), array('jquery'));
19
+ wp_enqueue_style('wp404arsp_admin_css', plugins_url('assets/admin.css', __FILE__));
20
  });
21
 
22
  }
33
 
34
  function wp404arsp_admin_page_html(){
35
  ?>
36
+ <div class="wrap" id="wp404arsp_settings">
37
  <h1 class="wp-heading-inline">WP 404 Auto Redirect to Similar Post</h1>
38
  <hr class="wp-header-end">
39
 
49
  <?php
50
  settings_fields('wp404arsp_settings');
51
  do_settings_sections('wp404arsp_settings');
52
+ $settings = wp404arsp_get_settings();
53
  ?>
54
 
55
  <div class="inside">
61
  <td>
62
  <fieldset>
63
  <legend class="screen-reader-text"><span>Debug</span></legend>
64
+ <label for="wp404arsp_settings_debug">
65
+ <input name="wp404arsp_settings[debug]" id="wp404arsp_settings_debug" value="1" type="checkbox" <?php if($settings['debug'] == "1") echo "checked"; ?>>
66
  Activate
67
  </label>
68
  </fieldset>
69
+ <p class="description">Display the Debug Console instead of being redirected. <code>Administrators</code> only.</p>
70
  </td>
71
  </tr>
72
 
73
  <tr>
74
+ <th scope="row">Fallback Behavior</th>
75
  <td>
76
  <fieldset>
77
+ <legend class="screen-reader-text"><span>Default Redirection if nothing similar is found.</span></legend>
78
+ <label for="wp404arsp_settings_fallback_type">
79
+ <select name="wp404arsp_settings[fallback][type]" id="wp404arsp_settings_fallback_type">
80
+ <option value="home" <?php if($settings['fallback']['type'] == 'home') echo "selected"; ?>>Redirect to Homepage</option>
81
+ <option value="custom" <?php if($settings['fallback']['type'] == 'custom') echo "selected"; ?>>Custom Redirection</option>
82
+ <option value="disabled" <?php if($settings['fallback']['type'] == 'disabled') echo "selected"; ?>>Default 404</option>
83
+ </select>
84
+ </label>
85
+
86
+ <?php
87
+ $fallback = array(
88
+ 'value' => home_url(),
89
+ 'class' => 'disabled',
90
+ 'attr' => 'readonly="readonly"',
91
+ );
92
+
93
+ if($settings['fallback']['type'] == 'custom'){
94
+ $fallback['value'] = $settings['fallback']['url'];
95
+ $fallback['attr'] = '';
96
+ $fallback['class'] = '';
97
+ }
98
+
99
+ if($settings['fallback']['type'] == 'disabled'){
100
+ $fallback['value'] = '';
101
+ $fallback['attr'] = '';
102
+ $fallback['class'] = 'hidden';
103
+ }
104
+ ?>
105
+
106
+ <input name="wp404arsp_settings[fallback][home_url]" id="wp404arsp_settings_fallback_home_url" type="hidden" value="<?php echo home_url(); ?>" />
107
+ <input name="wp404arsp_settings[fallback][url]" id="wp404arsp_settings_fallback_url" type="text" value="<?php echo $fallback['value']; ?>" class="<?php echo $fallback['class']; ?>" <?php echo $fallback['attr']; ?> />
108
+
109
  </fieldset>
110
+ <p class="description">If nothing similar is found, this behavior will be applied.</p>
111
  </td>
112
  </tr>
113
 
114
  <tr>
115
  <th scope="row">Redirect Headers</th>
116
  <td>
117
+ <fieldset>
118
+ <legend class="screen-reader-text"><span>Redirection Headers.</span></legend>
119
+ <label for="wp404arsp_settings_method">
120
+ <select name="wp404arsp_settings[method]" id="wp404arsp_settings_method">
121
+ <option value="301" <?php if($settings['method'] == '301') echo "selected"; ?>>301 method</option>
122
+ <option value="302" <?php if($settings['method'] == "302") echo "selected"; ?>>302 method</option>
123
+ </select>
124
+ </label>
125
+ </fieldset>
126
+ <p class="description">Learn more about <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank">HTTP headers & redirections</a>.</p>
127
+ </td>
128
+ </tr>
129
+
130
+ <tr>
131
+ <th scope="row">Exclude Post Type(s)</th>
132
+ <td>
133
+ <fieldset>
134
+ <legend class="screen-reader-text"><span>Exclude one or multiple post types from possible redirections.</span></legend>
135
+ <label for="wp404arsp_settings_rules_redirection_exclude_post_types">
136
+ <select multiple="multiple" name="wp404arsp_settings[rules][redirection][exclude][post_types][]" id="wp404arsp_settings_rules_redirection_exclude_post_types">
137
+ <?php foreach(get_post_types(array('public' => true), 'objects') as $post_type) { ?>
138
+ <?php
139
+ $selected = '';
140
+ if(
141
+ isset($settings['rules']['redirection']['exclude']['post_types']) &&
142
+ is_array($settings['rules']['redirection']['exclude']['post_types']) &&
143
+ in_array($post_type->name, $settings['rules']['redirection']['exclude']['post_types'])
144
+ )
145
+ $selected = 'selected="selected"'; ?>
146
+ <option value="<?php echo $post_type->name; ?>" <?php echo $selected; ?>>
147
+ <?php echo $post_type->label; ?>
148
+ </option>
149
+ <?php } ?>
150
+ </select>
151
+ </label>
152
+ </fieldset>
153
+ <p class="description">Exclude one or multiple post types from possible redirections.</p>
154
  </td>
155
  </tr>
156
 
157
  </tbody>
158
  </table>
159
 
160
+ <p class="submit">
161
  <?php submit_button('Save Settings', 'primary', '', false); ?>
162
  </p>
163
  </div>
164
  </form>
165
  </div>
166
 
167
+ <div id="wp404arsp_settings_redirection_preview">
168
  <div class="postbox">
169
  <h2 class="hndle"><span>Redirection Preview</span></h2>
170
  <div class="inside">
174
  <tr>
175
  <th scope="row"><?php echo home_url(); ?></th>
176
  <td>
177
+ <input class="request" type="text" value="/example-url" />
178
+ <p class="description">Enter the URL you would like to test, starting with <code>/</code>.</p>
179
  </td>
180
  </tr>
181
  </tbody>
182
  </table>
183
 
184
+ <p class="submit">
185
  <?php submit_button('Preview URL', 'secondary', '', false); ?>
186
+ <span class="loading spinner"></span>
187
  </p>
188
 
189
  <div class="results"></div>
201
  <div class="postbox">
202
 
203
  <div class="inside">
204
+ <img src="<?php echo plugins_url('assets/logo.png', __FILE__); ?>" class="logo" />
205
+
 
 
206
  <p>Found a bug? Need help? Head over the <a href="https://wordpress.org/plugins/wp-404-auto-redirect-to-similar-post/" target="_blank">official plugin page</a>.</p>
207
 
208
  <hr />
226
 
227
  add_action('template_redirect', 'wp404arsp_init');
228
  function wp404arsp_init(){
229
+ if(
230
+ !is_404() ||
231
+ wp_doing_ajax() ||
232
+ is_admin() ||
233
+ ( !isset($_SERVER['REQUEST_URI']) || empty($_SERVER['REQUEST_URI']) ) ||
234
+ ( isset($_SERVER['SCRIPT_URI']) && !empty($_SERVER['SCRIPT_URI']) && $_SERVER['SCRIPT_URI'] == admin_url('admin-ajax.php') ) ||
235
+ ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' )
236
+ )
237
+ return;
238
 
239
  wp404arsp_request($_SERVER['REQUEST_URI']);
 
240
  }
241
 
242
  function wp404arsp_request($request, $preview = false){
270
  if(!empty($query['request']['pagination']))
271
  return wp404arsp_redirect(array_merge( $query, array(
272
  'url' => home_url() . $request_no_pagination,
273
+ 'why' => "Pagination found in the requested URL. Trying to reach same URL without pagination."
274
  ))
275
  );
276
 
317
  function wp404arsp_search($query){
318
 
319
  // Direct
320
+ if( ($get_post_types = wp404arsp_get_post_types('names')) && !empty($get_post_types) ){
321
+ foreach($get_post_types as $post_type){
322
+ if($post = get_page_by_path($query['process']['keywords']['explode'][0], 'object', $post_type))
323
+ return array_merge( $query, array(
324
+ 'score' => 'direct',
325
+ 'id' => (int)$post->ID,
326
+ 'url' => get_permalink((int)$post->ID),
327
+ 'why' => "Part of the requested URL already exist as post of the post_type <strong>" . get_post_type((int)$post->ID) . "</strong>"
328
+ ));
329
+ }
330
+ }
331
 
332
  // Search
333
  $keywords = explode('-', $query['process']['keywords']['sanitized']);
339
 
340
  if(empty($sql['result']) || $sql['result']['score'] < 1)
341
  return array_merge( $query, array(
342
+ 'why' => "Nothing similar found matching the requested URL."
343
  )
344
  );
345
 
387
 
388
  function wp404arsp_redirect($args){
389
 
390
+ $settings = wp404arsp_get_settings();
391
+ $method = $settings['method'];
392
+ $fallback = $settings['fallback']['type'] != 'disabled' ? $settings['fallback']['url'] : false;
393
 
394
+ if( is_user_logged_in() && current_user_can('manage_options') && ($settings['debug'] || (isset($args['preview']) && $args['preview'])) )
395
  return wp404arsp_debug($args);
396
 
397
+ if(isset($args['url']) && !empty($args['url'])){
398
+ wp_redirect($args['url'], $method);
399
+ exit;
400
+ }
401
 
402
+ if($fallback){
403
+ wp_redirect($fallback, $method);
404
+ exit;
405
+ }
406
 
407
  return;
408
 
409
  }
410
 
411
  function wp404arsp_debug($args){
412
+ $settings = wp404arsp_get_settings();
413
+ $method = $settings['method'];
414
+ $fallback = $settings['fallback']['type'] != 'disabled' ? $settings['fallback']['url'] : false;
415
 
416
  $title = '';
417
  if(isset($args['url']) && !empty($args['url'])){
418
+ $title = 'Automatic Redirection: ' . "<a href='" . $args['url'] . "'>" . $args['url'] . "</a>" . ' (' . $method . ' Headers)';
419
 
420
+ }elseif(!$fallback){
421
+ $title = 'Fallback Redirection disabled. Displaying 404.';
422
 
423
  }else{
424
+ $title = 'Fallback Redirection: ' . "<a href='" . $fallback . "'>" . $fallback . "</a>" . ' (' . $method . ' Headers)';
425
 
426
  }
427
 
453
  function wp404arsp_search_sql($args = array()){
454
 
455
  global $wpdb;
456
+ $settings = wp404arsp_get_settings();
457
+ $args = wp_parse_args($args, array(
458
  'keywords' => null,
459
  'mode' => null,
460
  'post_type' => null,
476
  p.post_type = '" . $args['post_type'] . "'";
477
 
478
  }else{
479
+
480
+ if( ($get_post_types = wp404arsp_get_post_types('names')) && !empty($get_post_types) ){
481
+ foreach($get_post_types as $pt){
482
+ $post_types[] = "
483
+ p.post_type = '" . $pt . "'";
484
+ }
485
+ $sql .= '(' . implode(' OR ', $post_types) . ')';
486
+ }
487
 
488
  }
489
 
528
  function wp404arsp_get_settings(){
529
  return wp_parse_args(get_option('wp404arsp_settings'),
530
  array(
531
+ 'debug' => null,
532
+ 'logs' => null,
533
+ 'fallback' => array(
534
+ 'type' => 'home',
535
+ 'url' => home_url(),
536
+ 'home_url' => home_url(),
537
+ ),
538
+ 'rules' => array(
539
+ 'redirection' => array(
540
+ 'exclude' => array(
541
+ 'post_types' => array(),
542
+ ),
543
+ ),
544
+ ),
545
+ 'method' => 301
546
  )
547
  );
548
  }
567
  }
568
  }
569
 
570
+ function wp404arsp_get_post_types($type = 'names'){
571
+ $settings = wp404arsp_get_settings();
572
+ $get_post_types = get_post_types(array('public' => true), $type);
573
+
574
+ // No exclude
575
+ if( !isset($settings['rules']['redirection']['exclude']['post_types']) || !is_array($settings['rules']['redirection']['exclude']['post_types']) || empty($settings['rules']['redirection']['exclude']['post_types']) )
576
+ return $get_post_types;
577
+
578
+ // Exclude
579
+ $filtered_post_types = array();
580
+ foreach($get_post_types as $post_type){
581
+ $search = $post_type;
582
+ if($type == 'objects')
583
+ $search = $post_type->name;
584
+
585
+ if(in_array($search, $settings['rules']['redirection']['exclude']['post_types']))
586
+ continue;
587
+
588
+ $filtered_post_types[] = $post_type;
589
+ }
590
+
591
+ return $filtered_post_types;
592
  }