Simple 301 Redirects - Version 2.0.1

Version Description

  • 07/04/2021 =
  • Few minor bug fix and improvements
Download this release

Release Info

Developer re_enter_rupok
Plugin Icon 128x128 Simple 301 Redirects
Version 2.0.1
Comparing to
See all releases

Code changes from version 2.0.0 to 2.0.1

includes/Admin.php CHANGED
@@ -8,6 +8,7 @@ class Admin {
8
  $this->load_assets();
9
  $this->init_ajax();
10
  $this->init_tools();
 
11
  add_filter('Simple301Redirects/Admin/skip_no_conflict', [$this, 'skip_no_conflict']);
12
  }
13
  public function add_menu()
@@ -33,5 +34,21 @@ class Admin {
33
  return true;
34
  }
35
  return false;
36
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
8
  $this->load_assets();
9
  $this->init_ajax();
10
  $this->init_tools();
11
+ $this->usage_tracker();
12
  add_filter('Simple301Redirects/Admin/skip_no_conflict', [$this, 'skip_no_conflict']);
13
  }
14
  public function add_menu()
34
  return true;
35
  }
36
  return false;
37
+ }
38
+ public function usage_tracker()
39
+ {
40
+ $tracker = Admin\WPDev\PluginUsageTracker::get_instance( SIMPLE301REDIRECTS_PLUGIN_FILE, [
41
+ 'opt_in' => true,
42
+ 'goodbye_form' => true,
43
+ 'item_id' => 'c1e613119bf3e9188767'
44
+ ] );
45
+ $tracker->set_notice_options(array(
46
+ 'notice' => __( 'Want to help make <strong>Simple 301 Redirects</strong> even more awesome? You can get a <strong>10% discount</strong> coupon on our Premium products if you allow us to track the non-sensitive usage data.', 'simple-301-redirects' ),
47
+ 'extra_notice' => __( 'We collect non-sensitive diagnostic data and plugin usage information.
48
+ Your site URL, WordPress & PHP version, plugins & themes and email address to send you the
49
+ discount coupon. This data lets us make sure this plugin always stays compatible with the most
50
+ popular plugins and themes. No spam, I promise.', 'simple-301-redirects' ),
51
+ ));
52
+ $tracker->init();
53
+ }
54
  }
includes/Admin/WPDev/PluginUsageTracker.php ADDED
@@ -0,0 +1,899 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Simple301Redirects\Admin\WPDev;
3
+
4
+ /**
5
+ * WPInsights_Betterlinks
6
+ * This class is responsible for data sending to insights.
7
+ * @version 3.0.0
8
+ */
9
+
10
+ class PluginUsageTracker {
11
+ /**
12
+ * WP Insights Version
13
+ */
14
+ const WPINS_VERSION = '3.0.2';
15
+ /**
16
+ * API URL
17
+ */
18
+ const API_URL = 'https://send.wpinsight.com/process-plugin-data';
19
+ /**
20
+ * Installed Plugin File
21
+ *
22
+ * @var string
23
+ */
24
+ private $plugin_file = null;
25
+ /**
26
+ * Installed Plugin Name
27
+ *
28
+ * @var string
29
+ */
30
+ private $plugin_name = null;
31
+ /**
32
+ * How often the event should subsequently
33
+ * @var string
34
+ */
35
+ public $recurrence = 'daily';
36
+ private $event_hook = null;
37
+ /**
38
+ * Instace of WPInsights_Betterlinks
39
+ * @var WPInsights_Betterlinks
40
+ */
41
+ private static $_instance = null;
42
+ /**
43
+ * Get Instance of WPInsights_Betterlinks
44
+ * @return WPInsights_Betterlinks
45
+ */
46
+ public static function get_instance( $plugin_file, $args = [] ){
47
+ if( is_null( static::$_instance ) ) {
48
+ static::$_instance = new static( $plugin_file, $args );
49
+ }
50
+ return static::$_instance;
51
+ }
52
+ /**
53
+ * Automatically Invoked when initialized.
54
+ *
55
+ * @param array $args
56
+ */
57
+ public function __construct( $plugin_file, $args = [] ){
58
+ $this->plugin_file = $plugin_file;
59
+ $this->plugin_name = 'simple-301-redirects';
60
+ $this->disabled_wp_cron = defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true;
61
+ $this->enable_self_cron = $this->disabled_wp_cron == true ? true : false;
62
+
63
+ $this->event_hook = 'put_do_weekly_action';
64
+
65
+ $this->require_optin = isset( $args['opt_in'] ) ? $args['opt_in'] : true;
66
+ $this->include_goodbye_form = isset( $args['goodbye_form'] ) ? $args['goodbye_form'] : true;
67
+ $this->marketing = isset( $args['email_marketing'] ) ? $args['email_marketing'] : true;
68
+ $this->options = isset( $args['options'] ) ? $args['options'] : [];
69
+ $this->item_id = isset( $args['item_id'] ) ? $args['item_id'] : false;
70
+ /**
71
+ * Activation Hook
72
+ */
73
+ register_activation_hook( $this->plugin_file, array( $this, 'activate_this_plugin' ) );
74
+ /**
75
+ * Deactivation Hook
76
+ */
77
+ register_deactivation_hook( $this->plugin_file, array( $this, 'deactivate_this_plugin' ) );
78
+ }
79
+ /**
80
+ * When user agreed to opt-in tracking schedule is enabled.
81
+ * @since 3.0.0
82
+ */
83
+ public function schedule_tracking() {
84
+ if( $this->disabled_wp_cron ) {
85
+ return;
86
+ }
87
+ if ( ! wp_next_scheduled( $this->event_hook ) ) {
88
+ wp_schedule_event( time(), $this->recurrence, $this->event_hook );
89
+ }
90
+ }
91
+ /**
92
+ * Add the schedule event if the plugin is tracked.
93
+ *
94
+ * @return void
95
+ */
96
+ public function activate_this_plugin(){
97
+ $allow_tracking = $this->is_tracking_allowed();
98
+ if( ! $allow_tracking ) {
99
+ return;
100
+ }
101
+ $this->schedule_tracking();
102
+ }
103
+ /**
104
+ * Remove the schedule event when plugin is deactivated and send the deactivated reason to inishghts if user submitted.
105
+ * @since 3.0.0
106
+ */
107
+ public function deactivate_this_plugin() {
108
+ /**
109
+ * Check tracking is allowed or not.
110
+ */
111
+ $allow_tracking = $this->is_tracking_allowed();
112
+ if( ! $allow_tracking ) {
113
+ return;
114
+ }
115
+ $body = $this->get_data();
116
+ $body['status'] = 'Deactivated';
117
+ $body['deactivated_date'] = time();
118
+
119
+ // Check deactivation reason and add for insights data.
120
+ if( false !== get_option( 'wpins_deactivation_reason_' . $this->plugin_name ) ) {
121
+ $body['deactivation_reason'] = get_option( 'wpins_deactivation_reason_' . $this->plugin_name );
122
+ }
123
+ if( false !== get_option( 'wpins_deactivation_details_' . $this->plugin_name ) ) {
124
+ $body['deactivation_details'] = get_option( 'wpins_deactivation_details_' . $this->plugin_name );
125
+ }
126
+
127
+ $this->send_data( $body );
128
+ delete_option( 'wpins_deactivation_reason_' . $this->plugin_name );
129
+ delete_option( 'wpins_deactivation_details_' . $this->plugin_name );
130
+ /**
131
+ * Clear the event schedule.
132
+ */
133
+ if( ! $this->disabled_wp_cron ) {
134
+ wp_clear_scheduled_hook( $this->event_hook );
135
+ }
136
+ }
137
+ /**
138
+ * Initial Method to Hook Everything.
139
+ * @return void
140
+ */
141
+ public function init(){
142
+ $this->clicked();
143
+ add_action( $this->event_hook, array( $this, 'do_tracking' ) );
144
+ // For Test
145
+ // add_action( 'admin_init', array( $this, 'force_tracking' ) );
146
+ add_action( 'admin_notices', array( $this, 'notice' ) );
147
+ /**
148
+ * Deactivation Reason Form and Submit Data to Insights.
149
+ */
150
+ add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array( $this, 'deactivate_action_links' ) );
151
+ add_action( 'admin_footer-plugins.php', array( $this, 'deactivate_reasons_form' ) );
152
+ add_action( 'wp_ajax_deactivation_form_' . esc_attr( $this->plugin_name ), array( $this, 'deactivate_reasons_form_submit' ) );
153
+ }
154
+ /**
155
+ * For Redirecting Current Page without Arguments!
156
+ *
157
+ * @return void
158
+ */
159
+ private function redirect_to(){
160
+ $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
161
+ $query_string = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY );
162
+ parse_str( $query_string, $current_url );
163
+
164
+ $unset_array = array( 'dismiss', 'plugin', '_wpnonce', 'later', 'plugin_action', 'marketing_optin' );
165
+
166
+ foreach( $unset_array as $value ) {
167
+ if( isset( $current_url[ $value ] ) ) {
168
+ unset( $current_url[ $value ] );
169
+ }
170
+ }
171
+
172
+ $current_url = http_build_query($current_url);
173
+ $redirect_url = $request_uri . '?' . $current_url;
174
+ return $redirect_url;
175
+ }
176
+ /**
177
+ * This method forcing the do_tracking method to execute instant.
178
+ * @return void
179
+ */
180
+ public function force_tracking(){
181
+ $this->do_tracking( true );
182
+ }
183
+ /**
184
+ * This method is responsible for all the magic from the front of the plugin.
185
+ * @since 3.0.0
186
+ * @param $force Force tracking if it's not the correct time to track/
187
+ */
188
+ public function do_tracking( $force = false ) {
189
+ /**
190
+ * Check URL is set or not.
191
+ */
192
+ if ( empty( self::API_URL ) ) {
193
+ return;
194
+ }
195
+ /**
196
+ * Check is tracking allowed or not.
197
+ */
198
+ if( ! $this->is_tracking_allowed() ) {
199
+ return;
200
+ }
201
+ /**
202
+ * Check is this the correct time to track or not.
203
+ * or Force to track.
204
+ */
205
+ if( ! $this->is_time_to_track() && ! $force ) {
206
+ return;
207
+ }
208
+ /**
209
+ * Get All Data.
210
+ */
211
+ $body = $this->get_data();
212
+ /**
213
+ * Send all data.
214
+ */
215
+ return $this->send_data( $body );
216
+ }
217
+ /**
218
+ * Is tracking allowed?
219
+ * @since 1.0.0
220
+ */
221
+ private function is_tracking_allowed() {
222
+ // First, check if the user has changed their mind and opted out of tracking
223
+ if( $this->has_user_opted_out() ) {
224
+ $this->set_is_tracking_allowed( false, $this->plugin_name );
225
+ return false;
226
+ }
227
+ // The wpins_allow_tracking option is an array of plugins that are being tracked
228
+ $allow_tracking = get_option( 'wpins_allow_tracking' );
229
+ // If this plugin is in the array, then tracking is allowed
230
+ if( isset( $allow_tracking[$this->plugin_name] ) ) {
231
+ return true;
232
+ }
233
+ return false;
234
+ }
235
+ /**
236
+ * Set a flag in DB If tracking is allowed.
237
+ *
238
+ * @since 3.0.0
239
+ * @param $is_allowed Boolean true if is allowed.
240
+ */
241
+ protected function set_is_tracking_allowed( $is_allowed, $plugin = null ) {
242
+ if( empty( $plugin ) ) {
243
+ $plugin = $this->plugin_name;
244
+ }
245
+ /**
246
+ * Get All Tracked Plugin List using this Tracker.
247
+ */
248
+ $allow_tracking = get_option( 'wpins_allow_tracking' );
249
+ /**
250
+ * Check user is opted out for tracking or not.
251
+ */
252
+ if( $this->has_user_opted_out() ) {
253
+ if( isset( $allow_tracking[$plugin] ) ) {
254
+ unset( $allow_tracking[$plugin] );
255
+ }
256
+ } else if( $is_allowed || ! $this->require_optin ) {
257
+ /**
258
+ * If user has agreed to allow tracking
259
+ */
260
+ if( empty( $allow_tracking ) || ! is_array( $allow_tracking ) ) {
261
+ $allow_tracking = array( $plugin => $plugin );
262
+ } else {
263
+ $allow_tracking[$plugin] = $plugin;
264
+ }
265
+ } else {
266
+ if( isset( $allow_tracking[$plugin] ) ) {
267
+ unset( $allow_tracking[$plugin] );
268
+ }
269
+ }
270
+ update_option( 'wpins_allow_tracking', $allow_tracking );
271
+ }
272
+
273
+ /**
274
+ * Check the user has opted out or not.
275
+ *
276
+ * @since 3.0.0
277
+ * @return Boolean
278
+ */
279
+ protected function has_user_opted_out() {
280
+ if( ! empty( $this->options ) ) {
281
+ foreach( $this->options as $option_name ) {
282
+ $options = get_option( $option_name );
283
+ if( ! empty( $options['wpins_opt_out'] ) ) {
284
+ return true;
285
+ }
286
+ }
287
+ }
288
+ return false;
289
+ }
290
+ /**
291
+ * Check if it's time to track
292
+ *
293
+ * @since 3.0.0
294
+ */
295
+ public function is_time_to_track() {
296
+ $track_times = get_option( 'wpins_last_track_time', array() );
297
+ return ! isset( $track_times[$this->plugin_name] ) ? true :
298
+ ( ( isset( $track_times[$this->plugin_name] ) && $track_times[$this->plugin_name] ) < strtotime( '-1 day' ) ? true : false );
299
+ }
300
+ /**
301
+ * Set tracking time.
302
+ *
303
+ * @since 3.0.0
304
+ */
305
+ public function set_track_time() {
306
+ $track_times = get_option( 'wpins_last_track_time', array() );
307
+ $track_times[ $this->plugin_name ] = time();
308
+ update_option( 'wpins_last_track_time', $track_times );
309
+ }
310
+ /**
311
+ * This method is responsible for collecting all data.
312
+ *
313
+ * @since 3.0.0
314
+ */
315
+ public function get_data() {
316
+ $body = array(
317
+ 'plugin_slug' => sanitize_text_field( $this->plugin_name ),
318
+ 'url' => get_bloginfo( 'url' ),
319
+ 'site_name' => get_bloginfo( 'name' ),
320
+ 'site_version' => get_bloginfo( 'version' ),
321
+ 'site_language' => get_bloginfo( 'language' ),
322
+ 'charset' => get_bloginfo( 'charset' ),
323
+ 'wpins_version' => self::WPINS_VERSION,
324
+ 'php_version' => phpversion(),
325
+ 'multisite' => is_multisite(),
326
+ 'file_location' => __FILE__
327
+ );
328
+
329
+ // Collect the email if the correct option has been set
330
+ if( $this->marketing ) {
331
+ if( ! function_exists( 'wp_get_current_user' ) ) {
332
+ include ABSPATH . 'wp-includes/pluggable.php';
333
+ }
334
+ $current_user = wp_get_current_user();
335
+ $email = $current_user->user_email;
336
+ if( is_email( $email ) ) {
337
+ $body['email'] = $email;
338
+ }
339
+ }
340
+ $body['marketing_method'] = $this->marketing;
341
+ $body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
342
+
343
+ /**
344
+ * Collect all active and inactive plugins
345
+ */
346
+ if( ! function_exists( 'get_plugins' ) ) {
347
+ include ABSPATH . '/wp-admin/includes/plugin.php';
348
+ }
349
+ $plugins = array_keys( get_plugins() );
350
+ $active_plugins = is_network_admin() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : get_option( 'active_plugins', array() );
351
+ foreach ( $plugins as $key => $plugin ) {
352
+ if ( in_array( $plugin, $active_plugins ) ) {
353
+ unset( $plugins[$key] );
354
+ }
355
+ }
356
+ $body['active_plugins'] = $active_plugins;
357
+ $body['inactive_plugins'] = $plugins;
358
+
359
+ /**
360
+ * Text Direction.
361
+ */
362
+ $body['text_direction'] = ( function_exists( 'is_rtl' ) ? ( is_rtl() ? 'RTL' : 'LTR' ) : 'NOT SET' );
363
+ /**
364
+ * Get Our Plugin Data.
365
+ * @since 3.0.0
366
+ */
367
+ $plugin = $this->plugin_data();
368
+ if( empty( $plugin ) ) {
369
+ $body['message'] .= __( 'We can\'t detect any plugin information. This is most probably because you have not included the code in the plugin main file.', 'disable-comments' );
370
+ $body['status'] = 'NOT FOUND';
371
+ } else {
372
+ if( isset( $plugin['Name'] ) ) {
373
+ $body['plugin'] = sanitize_text_field( $plugin['Name'] );
374
+ }
375
+ if( isset( $plugin['Version'] ) ) {
376
+ $body['version'] = sanitize_text_field( $plugin['Version'] );
377
+ }
378
+ $body['status'] = 'Active';
379
+ }
380
+
381
+ /**
382
+ * Get our plugin options
383
+ * @since 1.0.0
384
+ */
385
+ // $options = $this->options;
386
+ // $plugin_options = array();
387
+ // if( ! empty( $options ) && is_array( $options ) ) {
388
+ // foreach( $options as $option ) {
389
+ // $fields = get_option( $option );
390
+ // // Check for permission to send this option
391
+ // if( isset( $fields['wpins_registered_setting'] ) ) {
392
+ // foreach( $fields as $key=>$value ) {
393
+ // $plugin_options[$key] = $value;
394
+ // }
395
+ // }
396
+ // }
397
+ // }
398
+ // $body['plugin_options'] = $this->options; // Returns array
399
+ // $body['plugin_options_fields'] = $plugin_options; // Returns object
400
+
401
+ /**
402
+ * Get active theme name and version
403
+ * @since 3.0.0
404
+ */
405
+ $theme = wp_get_theme();
406
+ if( $theme->Name ) {
407
+ $body['theme'] = sanitize_text_field( $theme->Name );
408
+ }
409
+ if( $theme->Version ) {
410
+ $body['theme_version'] = sanitize_text_field( $theme->Version );
411
+ }
412
+ return $body;
413
+ }
414
+
415
+ /**
416
+ * Collect plugin data,
417
+ * Retrieve current plugin information
418
+ *
419
+ * @since 3.0.0
420
+ */
421
+ public function plugin_data() {
422
+ if( ! function_exists( 'get_plugin_data' ) ) {
423
+ include ABSPATH . '/wp-admin/includes/plugin.php';
424
+ }
425
+ $plugin = get_plugin_data( $this->plugin_file );
426
+ return $plugin;
427
+ }
428
+ /**
429
+ * Send the data to insights.
430
+ * @since 3.0.0
431
+ */
432
+ public function send_data( $body ) {
433
+ /**
434
+ * Get SITE ID
435
+ */
436
+ $site_id_key = "wpins_{$this->plugin_name}_site_id";
437
+ $site_id = get_option( $site_id_key, false );
438
+ $failed_data = [];
439
+ $site_url = get_bloginfo( 'url' );
440
+ $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
441
+
442
+ if( ( $original_site_url === false || $original_site_url != $site_url ) && version_compare( $body['wpins_version'], '3.0.1', '>=' ) ) {
443
+ $site_id = false;
444
+ }
445
+ /**
446
+ * Send Initial Data to API
447
+ */
448
+ if( $site_id == false && $this->item_id !== false ) {
449
+ if( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) {
450
+ $country_request = wp_remote_get( 'http://ip-api.com/json/'. $_SERVER['REMOTE_ADDR'] .'?fields=country');
451
+ if( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
452
+ $ip_data = json_decode( $country_request["body"] );
453
+ $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
454
+ }
455
+ }
456
+
457
+ $body['plugin_slug'] = $this->plugin_name;
458
+ $body['url'] = $site_url;
459
+ $body['item_id'] = $this->item_id;
460
+
461
+ $request = $this->remote_post( $body );
462
+ if( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
463
+ $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
464
+ if( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
465
+ update_option( $site_id_key, $retrieved_body['siteId'] );
466
+ update_option( "wpins_{$this->plugin_name}_original_url", $site_url );
467
+ update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body );
468
+ }
469
+ } else {
470
+ $failed_data = $body;
471
+ }
472
+ }
473
+
474
+ $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
475
+ $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
476
+
477
+ if( $site_id != false ) {
478
+ $old_sent_data = get_option( $site_id_data_key, [] );
479
+ $diff_data = $this->diff( $body, $old_sent_data );
480
+ $failed_data = get_option( $site_id_data_failed_key, [] );
481
+ if( ! empty( $failed_data ) && $diff_data != $failed_data ) {
482
+ $failed_data = array_merge( $failed_data, $diff_data );
483
+ }
484
+ }
485
+
486
+ if( ! empty( $failed_data ) && $site_id != false ) {
487
+ $failed_data['plugin_slug'] = $this->plugin_name;
488
+ $failed_data['url'] = $site_url;
489
+ $failed_data['site_id'] = $site_id;
490
+ if( $original_site_url != false ) {
491
+ $failed_data['original_url'] = $original_site_url;
492
+ }
493
+
494
+ $request = $this->remote_post( $failed_data );
495
+ if( ! is_wp_error( $request ) ) {
496
+ delete_option( $site_id_data_failed_key );
497
+ $replaced_data = array_merge( $old_sent_data, $failed_data );
498
+ update_option( $site_id_data_key, $replaced_data );
499
+ }
500
+ }
501
+
502
+ if( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
503
+ $diff_data['plugin_slug'] = $this->plugin_name;
504
+ $diff_data['url'] = $site_url;
505
+ $diff_data['site_id'] = $site_id;
506
+ if( $original_site_url != false ) {
507
+ $diff_data['original_url'] = $original_site_url;
508
+ }
509
+
510
+ $request = $this->remote_post( $diff_data );
511
+ if( is_wp_error( $request ) ) {
512
+ update_option( $site_id_data_failed_key, $diff_data );
513
+ } else {
514
+ $replaced_data = array_merge( $old_sent_data, $diff_data );
515
+ update_option( $site_id_data_key, $replaced_data );
516
+ }
517
+ }
518
+
519
+ $this->set_track_time();
520
+
521
+ if( isset( $request ) && is_wp_error( $request ) ) {
522
+ return $request;
523
+ }
524
+
525
+ if( isset( $request ) ) {
526
+ return true;
527
+ }
528
+ return false;
529
+ }
530
+ /**
531
+ * WP_REMOTE_POST method responsible for send data to the API_URL
532
+ *
533
+ * @param array $data
534
+ * @param array $args
535
+ * @return void
536
+ */
537
+ protected function remote_post( $data = array(), $args = array() ){
538
+ if( empty( $data ) ) {
539
+ return;
540
+ }
541
+
542
+ $args = wp_parse_args( $args, array(
543
+ 'method' => 'POST',
544
+ 'timeout' => 30,
545
+ 'redirection' => 5,
546
+ 'httpversion' => '1.1',
547
+ 'blocking' => true,
548
+ 'body' => $data,
549
+ 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo( 'url' )
550
+ ));
551
+ $request = wp_remote_post( esc_url( self::API_URL ), $args );
552
+ if( is_wp_error( $request ) || ( isset( $request['response'], $request['response']['code'] ) && $request['response']['code'] != 200 ) ) {
553
+ return new \WP_Error( 500, 'Something went wrong.' );
554
+ }
555
+ return $request;
556
+ }
557
+ /**
558
+ * Difference between old and new data
559
+ *
560
+ * @param array $new_data
561
+ * @param array $old_data
562
+ * @return void
563
+ */
564
+ protected function diff( $new_data, $old_data ){
565
+ $data = [];
566
+ if( ! empty( $new_data ) ) {
567
+ foreach( $new_data as $key => $value ) {
568
+ if( isset( $old_data[ $key ] ) ) {
569
+ if( $old_data[ $key ] == $value ) {
570
+ continue;
571
+ }
572
+ }
573
+ $data[ $key ] = $value;
574
+ }
575
+ }
576
+ return $data;
577
+ }
578
+ /**
579
+ * Display the admin notice to users to allow them to opt in
580
+ *
581
+ * @since 3.0.0
582
+ */
583
+ public function notice() {
584
+ /**
585
+ * Return if notice is not set.
586
+ */
587
+ if( ! isset( $this->notice_options['notice'] ) ) {
588
+ return;
589
+ }
590
+ /**
591
+ * Check is allowed or blocked for notice.
592
+ */
593
+ $block_notice = get_option( 'wpins_block_notice' );
594
+ if( isset( $block_notice[$this->plugin_name] ) ) {
595
+ return;
596
+ }
597
+ if ( ! current_user_can( 'manage_options' ) ) {
598
+ return;
599
+ }
600
+
601
+ $url_yes = add_query_arg( [
602
+ 'plugin' => $this->plugin_name,
603
+ 'plugin_action' => 'yes',
604
+ ] );
605
+ $url_no = add_query_arg( array(
606
+ 'plugin' => $this->plugin_name,
607
+ 'plugin_action' => 'no'
608
+ ) );
609
+
610
+ // Decide on notice text
611
+ $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-'. $this->plugin_name .'-collect">'. $this->notice_options['consent_button_text'] .'</a>';
612
+ $extra_notice_text = $this->notice_options['extra_notice'];
613
+
614
+ $output = '';
615
+ $output .= '<div class="notice notice-info updated put-dismiss-notice">';
616
+ $output .= '<p>'. $notice_text .'</p>';
617
+ $output .= '<div class="wpinsights-data" style="display: none;">';
618
+ $output .= '<p>'. $extra_notice_text .'</p>';
619
+ $output .= '</div>';
620
+ $output .= '<p>';
621
+ $output .= '<a href="'. esc_url( $url_yes ) .'" class="button-primary">'. $this->notice_options['yes'] .'</a>&nbsp;';
622
+ $output .= '<a href="'. esc_url( $url_no ) .'" class="button-secondary">'. $this->notice_options['no'] .'</a>';
623
+ $output .= '</p>';
624
+ $output .= "<script type='text/javascript'>jQuery('.wpinsights-". $this->plugin_name ."-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
625
+ $output .= '</div>';
626
+
627
+ echo $output;
628
+ }
629
+ /**
630
+ * Set all notice options to customized notice.
631
+ *
632
+ * @since 3.0.0
633
+ * @param array $options
634
+ * @return void
635
+ */
636
+ public function set_notice_options( $options = [] ){
637
+ $default_options = [
638
+ 'consent_button_text' => __( 'What we collect.', 'disable-comments' ),
639
+ 'yes' => __( 'Sure, I\'d like to help', 'disable-comments' ),
640
+ 'no' => __( 'No Thanks.', 'disable-comments' ),
641
+ ];
642
+ $options = wp_parse_args( $options, $default_options );
643
+ $this->notice_options = $options;
644
+ }
645
+ /**
646
+ * Responsible for track the click from Notice.
647
+ * @return void
648
+ */
649
+ public function clicked(){
650
+ if( isset( $_GET['plugin'] ) && trim($_GET['plugin']) === $this->plugin_name && isset( $_GET['plugin_action'] ) ) {
651
+ if( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
652
+ return;
653
+ }
654
+ $plugin = sanitize_text_field( $_GET['plugin'] );
655
+ $action = sanitize_text_field( $_GET['plugin_action'] );
656
+ if( $action == 'yes' ) {
657
+ $this->schedule_tracking();
658
+ $this->set_is_tracking_allowed( true, $plugin );
659
+ if( $this->do_tracking( true ) ) {
660
+ $this->update_block_notice( $plugin );
661
+ }
662
+ /**
663
+ * Redirect User To the Current URL, but without set query arguments.
664
+ */
665
+ wp_safe_redirect( $this->redirect_to() );
666
+ } else {
667
+ $this->set_is_tracking_allowed( false, $plugin );
668
+ $this->update_block_notice( $plugin );
669
+ }
670
+ }
671
+ }
672
+ /**
673
+ * Set if we should block the opt-in notice for this plugin
674
+ *
675
+ * @since 3.0.0
676
+ */
677
+ public function update_block_notice( $plugin = null ) {
678
+ if( empty( $plugin ) ) {
679
+ $plugin = $this->plugin_name;
680
+ }
681
+ $block_notice = get_option( 'wpins_block_notice' );
682
+ if( empty( $block_notice ) || ! is_array( $block_notice ) ) {
683
+ $block_notice = array( $plugin => $plugin );
684
+ } else {
685
+ $block_notice[$plugin] = $plugin;
686
+ }
687
+ update_option( 'wpins_block_notice', $block_notice );
688
+ }
689
+ /**
690
+ * AJAX callback when the deactivated form is submitted.
691
+ * @since 3.0.0
692
+ */
693
+ public function deactivate_reasons_form_submit() {
694
+ check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
695
+ if( isset( $_POST['values'] ) ) {
696
+ $values = $_POST['values'];
697
+ update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values );
698
+ }
699
+ if( isset( $_POST['details'] ) ) {
700
+ $details = sanitize_text_field( $_POST['details'] );
701
+ update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details );
702
+ }
703
+ echo 'success';
704
+ wp_die();
705
+ }
706
+ /**
707
+ * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
708
+ * @since 3.0.0
709
+ */
710
+ public function deactivate_action_links( $links ) {
711
+ /**
712
+ * Check is tracking allowed or not.
713
+ */
714
+ if( ! $this->is_tracking_allowed() ) {
715
+ return $links;
716
+ }
717
+ if( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
718
+ $deactivation_link = $links['deactivate'];
719
+ /**
720
+ * Change the default deactivate button link.
721
+ */
722
+ $deactivation_link = str_replace( '<a ', '<div class="wpinsights-goodbye-form-wrapper-'. esc_attr( $this->plugin_name ) .'"><div class="wpinsights-goodbye-form-bg"></div><span class="wpinsights-goodbye-form" id="wpinsights-goodbye-form"></span></div><a onclick="javascript:event.preventDefault();" id="wpinsights-goodbye-link-' . esc_attr( $this->plugin_name ) . '" ', $deactivation_link );
723
+ $links['deactivate'] = $deactivation_link;
724
+ }
725
+ return $links;
726
+ }
727
+ /**
728
+ * ALL Deactivate Reasons.
729
+ * @since 3.0.0
730
+ */
731
+ public function deactivation_reasons() {
732
+ $form = array();
733
+ $form['heading'] = __( 'Sorry to see you go', 'disable-comments' );
734
+ $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'disable-comments' );
735
+
736
+ $form['options'] = array(
737
+ __( 'I no longer need the plugin', 'disable-comments' ),
738
+ [
739
+ 'label' => __( 'I found a better plugin', 'disable-comments' ),
740
+ 'extra_field' => __( 'Please share which plugin', 'disable-comments' )
741
+ ],
742
+ __( "I couldn't get the plugin to work", 'disable-comments' ),
743
+ __( 'It\'s a temporary deactivation', 'disable-comments' ),
744
+ [
745
+ 'label' => __( 'Other', 'disable-comments' ),
746
+ 'extra_field' => __( 'Please share the reason', 'disable-comments' ),
747
+ 'type' => 'textarea'
748
+ ]
749
+ );
750
+ return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
751
+ }
752
+ /**
753
+ * Deactivate Reasons Form.
754
+ * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
755
+ *
756
+ * @since 3.0.0
757
+ */
758
+ public function deactivate_reasons_form() {
759
+ $form = $this->deactivation_reasons();
760
+ $class_plugin_name = esc_attr( $this->plugin_name );
761
+ $html = '<div class="wpinsights-goodbye-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
762
+ $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
763
+ if( is_array( $form['options'] ) ) {
764
+ $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
765
+ foreach( $form['options'] as $option ) {
766
+ if( is_array( $option ) ) {
767
+ $id = strtolower( str_replace( " ", "_", esc_attr( $option['label'] ) ) );
768
+ $id = $id . '_' . $class_plugin_name;
769
+ $html .= '<li class="has-goodbye-extra">';
770
+ $html .= '<input type="radio" name="wpinsights-'. $class_plugin_name .'-goodbye-options" id="' . $id . '" value="' . esc_attr( $option['label'] ) . '">';
771
+ $html .= '<div><label for="' . $id . '">' . esc_attr( $option['label'] ) . '</label>';
772
+ if( isset( $option[ 'extra_field' ] ) && ! isset( $option['type'] )) {
773
+ $html .= '<input type="text" style="display: none" name="'. $id .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '">';
774
+ }
775
+ if( isset( $option[ 'extra_field' ] ) && isset( $option['type'] )) {
776
+ $html .= '<'. $option['type'] .' style="display: none" type="text" name="'. $id .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '"></' . $option['type'] . '>';
777
+ }
778
+ $html .= '</div></li>';
779
+ } else {
780
+ $id = strtolower( str_replace( " ", "_", esc_attr( $option ) ) );
781
+ $id = $id . '_' . $class_plugin_name;
782
+ $html .= '<li><input type="radio" name="wpinsights-'. $class_plugin_name .'-goodbye-options" id="' . $id . '" value="' . esc_attr( $option ) . '"> <label for="' . $id . '">' . esc_attr( $option ) . '</label></li>';
783
+ }
784
+ }
785
+ $html .= '</ul></div><!-- .wpinsights-'. $class_plugin_name .'-goodbye-options -->';
786
+ }
787
+ $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
788
+ $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'disable-comments' ) . '</p>';
789
+
790
+ $wrapper_class = '.wpinsights-goodbye-form-wrapper-'. $class_plugin_name;
791
+
792
+ $styles = '';
793
+ $styles .= '<style type="text/css">';
794
+ $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form-bg {';
795
+ $styles .= 'background: rgba( 0, 0, 0, .8 );position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9;';
796
+ $styles .= '}';
797
+ $styles .= $wrapper_class . '{';
798
+ $styles .= 'position: relative; display: none;';
799
+ $styles .= '}';
800
+ $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' ' . $wrapper_class . '{';
801
+ $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center;';
802
+ $styles .= '}';
803
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
804
+ $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form {';
805
+ $styles .= 'position: relative !important; width: 550px; max-width: 80%; background: #fff; box-shadow: 2px 8px 23px 3px rgba(0,0,0,.2); border-radius: 3px; white-space: normal; overflow: hidden; display: block; z-index: 999999;';
806
+ $styles .= '}';
807
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-head {';
808
+ $styles .= 'background: #fff; color: #495157; padding: 18px; box-shadow: 0 0 8px rgba(0,0,0,.1); font-size: 15px;';
809
+ $styles .= '}';
810
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong { font-size: 15px; }';
811
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body { padding: 8px 18px; color: #333; }';
812
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body label { padding-left: 5px; color: #6d7882; }';
813
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {';
814
+ $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
815
+ $styles .= '}';
816
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
817
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
818
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
819
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input, '. $wrapper_class .' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea {';
820
+ $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
821
+ $styles .= '}';
822
+ $styles .= $wrapper_class . ' .deactivating-spinner { display: none; padding-bottom: 20px !important; }';
823
+ $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
824
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
825
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
826
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
827
+ $styles .= 'background-color: #d30c5c; -webkit-border-radius: 3px; border-radius: 3px; color: #fff; line-height: 1; padding: 15px 20px; font-size: 13px;';
828
+ $styles .= '}';
829
+ $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
830
+ $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
831
+ $styles .= '}';
832
+ $styles .= $wrapper_class . ' .test {';
833
+ $styles .= '}';
834
+ $styles .= '</style>';
835
+ $styles .= '';
836
+
837
+ echo $styles;
838
+ ?>
839
+ <script type="text/javascript">
840
+ jQuery(document).ready(function($){
841
+ $("#wpinsights-goodbye-link-<?php echo $class_plugin_name; ?>").on("click",function(){
842
+ // We'll send the user to this deactivation link when they've completed or dismissed the form
843
+ var url = document.getElementById("wpinsights-goodbye-link-<?php echo $class_plugin_name; ?>");
844
+ $('body').toggleClass('wpinsights-form-active-<?php echo $class_plugin_name; ?>');
845
+ $(".wpinsights-goodbye-form-wrapper-<?php echo $class_plugin_name; ?> #wpinsights-goodbye-form").fadeIn();
846
+ $(".wpinsights-goodbye-form-wrapper-<?php echo $class_plugin_name; ?> #wpinsights-goodbye-form").html( '<?php echo $html; ?>' + '<div class="wpinsights-goodbye-form-footer"><div class="wpinsights-goodbye-form-buttons"><a id="wpinsights-submit-form-<?php echo $class_plugin_name; ?>" class="wpinsights-submit-btn" href="#"><?php _e( 'Submit and Deactivate', 'disable-comments' ); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="'+url+'"><?php _e( 'Just Deactivate', 'disable-comments' ); ?></a></div></div>');
847
+ $('#wpinsights-submit-form-<?php echo $class_plugin_name; ?>').on('click', function(e){
848
+ // As soon as we click, the body of the form should disappear
849
+ $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .wpinsights-goodbye-form-body").fadeOut();
850
+ $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .wpinsights-goodbye-form-footer").fadeOut();
851
+ // Fade in spinner
852
+ $("#wpinsights-goodbye-form-<?php echo $class_plugin_name; ?> .deactivating-spinner").fadeIn();
853
+ e.preventDefault();
854
+ var checkedInput = $("input[name='wpinsights-<?php echo $class_plugin_name; ?>-goodbye-options']:checked"),
855
+ checkedInputVal, details;
856
+ if( checkedInput.length > 0 ) {
857
+ checkedInputVal = checkedInput.val();
858
+ details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
859
+ }
860
+
861
+ if( typeof details === 'undefined' ) {
862
+ details = '';
863
+ }
864
+ if( typeof checkedInputVal === 'undefined' ) {
865
+ checkedInputVal = 'No Reason';
866
+ }
867
+
868
+ var data = {
869
+ 'action': 'deactivation_form_<?php echo $class_plugin_name; ?>',
870
+ 'values': checkedInputVal,
871
+ 'details': details,
872
+ 'security': "<?php echo wp_create_nonce ( 'wpins_deactivation_nonce' ); ?>",
873
+ 'dataType': "json"
874
+ }
875
+
876
+ $.post(
877
+ ajaxurl,
878
+ data,
879
+ function(response){
880
+ // Redirect to original deactivation URL
881
+ window.location.href = url;
882
+ }
883
+ );
884
+ });
885
+ $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
886
+ var parent = $(this).parents('li');
887
+ parent.siblings().find('label').next('input, textarea').css('display', 'none');
888
+ parent.find('label').next('input, textarea').css('display', 'block');
889
+ });
890
+ // If we click outside the form, the form will close
891
+ $('.wpinsights-goodbye-form-bg').on('click',function(){
892
+ $("#wpinsights-goodbye-form").fadeOut();
893
+ $('body').removeClass('wpinsights-form-active-<?php echo $class_plugin_name; ?>');
894
+ });
895
+ });
896
+ });
897
+ </script>
898
+ <?php }
899
+ }
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: 301 redirects, 301, shortlinks, link shortener, links, permalink, redirect
4
  Requires at least: 4.0
5
  Tested up to: 5.7
6
  Requires PHP: 5.4
7
- Stable tag: 2.0.0
8
  License: GPL-3.0-or-later
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -100,6 +100,9 @@ Visit [WPDeveloper](https://wpdeveloper.net/) to learn more about how to do bett
100
 
101
  == Changelog ==
102
 
 
 
 
103
  = 2.0.0 - 01/04/2021 =
104
  * Revamped: New UI/UX
105
  * Added: Support for WordPress 5.7
4
  Requires at least: 4.0
5
  Tested up to: 5.7
6
  Requires PHP: 5.4
7
+ Stable tag: 2.0.1
8
  License: GPL-3.0-or-later
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
100
 
101
  == Changelog ==
102
 
103
+ = 2.0.1 - 07/04/2021 =
104
+ * Few minor bug fix and improvements
105
+
106
  = 2.0.0 - 01/04/2021 =
107
  * Revamped: New UI/UX
108
  * Added: Support for WordPress 5.7
wp-simple-301-redirects.php CHANGED
@@ -1,12 +1,14 @@
1
  <?php
2
- /*
3
- Plugin Name: Simple 301 Redirects
4
- Plugin URI: https://wordpress.org/plugins/simple-301-redirects/
5
- Description: Create a list of URLs that you would like to 301 redirect to another page or site. Now with wildcard support.
6
- Version: 2.0.0
7
- Author: WPDeveloper
8
- Author URI: https://wpdeveloper.net/
9
- */
 
 
10
 
11
  /* Copyright 2009-2021 WPDeveloper
12
 
@@ -64,7 +66,7 @@ if (!class_exists("Simple301redirects")) {
64
 
65
  public function define_constants()
66
  {
67
- define('SIMPLE301REDIRECTS_VERSION', '2.0.0');
68
  define('SIMPLE301REDIRECTS_SETTINGS_NAME', '301_redirects');
69
  define('SIMPLE301REDIRECTS_PLUGIN_FILE', __FILE__);
70
  define('SIMPLE301REDIRECTS_PLUGIN_BASENAME', plugin_basename(__FILE__));
1
  <?php
2
+ /**
3
+ * Plugin Name: Simple 301 Redirects
4
+ * Plugin URI: https://wordpress.org/plugins/simple-301-redirects/
5
+ * Description: Create a list of URLs that you would like to 301 redirect to another page or site. Now with wildcard support.
6
+ * Author: WPDeveloper
7
+ * Author URI: https://wpdeveloper.net/
8
+ * Text Domain: simple-301-redirects
9
+ * Domain Path: /languages
10
+ * Version: 2.0.1
11
+ */
12
 
13
  /* Copyright 2009-2021 WPDeveloper
14
 
66
 
67
  public function define_constants()
68
  {
69
+ define('SIMPLE301REDIRECTS_VERSION', '2.0.1');
70
  define('SIMPLE301REDIRECTS_SETTINGS_NAME', '301_redirects');
71
  define('SIMPLE301REDIRECTS_PLUGIN_FILE', __FILE__);
72
  define('SIMPLE301REDIRECTS_PLUGIN_BASENAME', plugin_basename(__FILE__));