WP Htaccess Editor - Version 1.66

Version Description

Download this release

Release Info

Developer WebFactory
Plugin Icon 128x128 WP Htaccess Editor
Version 1.66
Comparing to
See all releases

Code changes from version 1.65 to 1.66

css/wp-htaccess-editor.css CHANGED
@@ -1,9 +1,10 @@
1
  /**
2
  * WP Htaccess Editor
3
- * (c) WebFactory Ltd, 2018-2019
4
  */
5
 
6
- body, p {
 
7
  font-size: 14px;
8
  }
9
 
1
  /**
2
  * WP Htaccess Editor
3
+ * (c) WebFactory Ltd, 2018-2020
4
  */
5
 
6
+ body,
7
+ p {
8
  font-size: 14px;
9
  }
10
 
js/wp-htaccess-editor-pointers.js CHANGED
@@ -1,32 +1,34 @@
1
  /*
2
  * WP Htaccess Editor
3
  * Backend GUI pointers
4
- * (c) Web factory Ltd, 2017 - 2018
5
  */
6
 
7
- jQuery(document).ready(function($){
8
- if (typeof wp_htaccess_editor_pointers == 'undefined') {
9
  return;
10
  }
11
 
12
- $.each(wp_htaccess_editor_pointers, function(index, pointer) {
13
  if (index.charAt(0) == '_') {
14
  return true;
15
  }
16
- $(pointer.target).pointer({
 
17
  content: '<h3>WP Htaccess Editor</h3><p>' + pointer.content + '</p>',
18
  pointerWidth: 380,
19
  position: {
20
- edge: pointer.edge,
21
- align: pointer.align
22
  },
23
- close: function() {
24
- $.get(ajaxurl, {
25
- notice_name: index,
26
- _ajax_nonce: wp_htaccess_editor_pointers._nonce_dismiss_pointer,
27
- action: 'wp_htaccess_editor_dismiss_notice'
28
- });
29
- }
30
- }).pointer('open');
 
31
  });
32
  });
1
  /*
2
  * WP Htaccess Editor
3
  * Backend GUI pointers
4
+ * (c) WebFactory Ltd, 2017 - 2020
5
  */
6
 
7
+ jQuery(document).ready(function ($) {
8
+ if (typeof wp_htaccess_editor_pointers == 'undefined') {
9
  return;
10
  }
11
 
12
+ $.each(wp_htaccess_editor_pointers, function (index, pointer) {
13
  if (index.charAt(0) == '_') {
14
  return true;
15
  }
16
+ $(pointer.target)
17
+ .pointer({
18
  content: '<h3>WP Htaccess Editor</h3><p>' + pointer.content + '</p>',
19
  pointerWidth: 380,
20
  position: {
21
+ edge: pointer.edge,
22
+ align: pointer.align,
23
  },
24
+ close: function () {
25
+ $.get(ajaxurl, {
26
+ notice_name: index,
27
+ _ajax_nonce: wp_htaccess_editor_pointers._nonce_dismiss_pointer,
28
+ action: 'wp_htaccess_editor_dismiss_notice',
29
+ });
30
+ },
31
+ })
32
+ .pointer('open');
33
  });
34
  });
js/wp-htaccess-editor.js CHANGED
@@ -1,23 +1,23 @@
1
  /**
2
  * WP Htaccess Editor
3
- * (c) WebFactory Ltd, 2018-2019
4
  */
5
 
6
- jQuery(document).ready(function($) {
7
  var wphe_changed = false;
8
 
9
  // setup CodeMirror
10
- wp.CodeMirror.defineInitHook(function(wphe_cm) {
11
  // add resize handle for editor
12
  cmResize(wphe_cm);
13
 
14
  // detect user changes in editor
15
- wphe_cm.on('change', function() {
16
  wphe_changed = true;
17
  });
18
 
19
  // detect and save editor size change
20
- wphe_cm.on('update', function(e) {
21
  localStorage.setItem('wphe-editor-width', e.display.lastWrapWidth);
22
  localStorage.setItem('wphe-editor-height', e.display.lastWrapHeight);
23
  });
@@ -26,36 +26,29 @@ jQuery(document).ready(function($) {
26
  $(window).off('beforeunload');
27
 
28
  // set beforeunload save check
29
- $(window).bind('beforeunload', function() {
30
  if (wphe_changed) {
31
  return true;
32
  }
33
  });
34
-
35
  let wphe_width = parseInt(localStorage.getItem('wphe-editor-width'), 10);
36
  let wphe_height = parseInt(localStorage.getItem('wphe-editor-height'), 10);
37
-
38
- if(!(wphe_width > 0 && wphe_height > 0)){
39
- wphe_width = 676;
40
- wphe_height = 400;
41
  }
42
-
43
  if (wphe_width > 0 && wphe_height > 0) {
44
- $('.CodeMirror')
45
- .width(wphe_width)
46
- .height(wphe_height);
47
-
48
- $('#enable-editor-notice')
49
- .innerHeight(wphe_height)
50
- .innerWidth(wphe_width);
51
  }
52
  }); // CodeMirror setup
53
 
54
  // init code editor
55
- wp.themePluginEditor.init(
56
- $('#htaccess-editor-wrap'),
57
- wp_htaccess_editor.cm_settings
58
- );
59
  wp.themePluginEditor.themeOrPlugin = 'theme';
60
 
61
  // display a message while an action is performed
@@ -74,7 +67,7 @@ jQuery(document).ready(function($) {
74
  allowEscapeKey: false,
75
  allowEnterKey: false,
76
  showConfirmButton: false,
77
- width: 600
78
  });
79
 
80
  return tmp;
@@ -91,14 +84,14 @@ jQuery(document).ready(function($) {
91
  confirmButtonText: btn_confirm,
92
  cancelButtonText: btn_cancel,
93
  confirmButtonColor: '#dd3036',
94
- width: 600
95
  });
96
 
97
  return tmp;
98
  } // confirm_action
99
 
100
  // dismiss notice / pointer
101
- $('.wphe-dismiss-notice').on('click', function(e) {
102
  notice_name = $(this).data('notice');
103
  if (!notice_name) {
104
  return true;
@@ -107,12 +100,10 @@ jQuery(document).ready(function($) {
107
  $.get(ajaxurl, {
108
  notice_name: notice_name,
109
  _ajax_nonce: wp_htaccess_editor.nonce_dismiss_notice,
110
- action: 'wp_htaccess_editor_dismiss_notice'
111
  });
112
 
113
- $(this)
114
- .parents('.notice-wrapper')
115
- .fadeOut();
116
 
117
  if (notice_name == 'editor-warning') {
118
  $('#wphe-buttons').fadeIn();
@@ -123,15 +114,11 @@ jQuery(document).ready(function($) {
123
  }); // dismiss notice
124
 
125
  // collapse / expand card
126
- $('.card').on('click', '.toggle-card', function(e) {
127
  e.preventDefault();
128
 
129
- card = $(this)
130
- .parents('.card')
131
- .toggleClass('collapsed');
132
- $('.dashicons', this)
133
- .toggleClass('dashicons-arrow-up-alt2')
134
- .toggleClass('dashicons-arrow-down-alt2');
135
  $(this).blur();
136
 
137
  cards = localStorage.getItem('wp-htaccess-editor-cards');
@@ -156,14 +143,14 @@ jQuery(document).ready(function($) {
156
  if (cards != null) {
157
  cards = JSON.parse(cards);
158
  }
159
- $.each(cards, function(card_name, card_value) {
160
  if (card_value == 'collapsed') {
161
  $('a.toggle-card', '#' + card_name).trigger('click');
162
  }
163
  });
164
 
165
  // save htaccess file
166
- $('#wphe_save_htaccess').click(function(e) {
167
  e.preventDefault();
168
 
169
  block_ui(wp_htaccess_editor.saving);
@@ -173,42 +160,40 @@ jQuery(document).ready(function($) {
173
  action: 'wp_htaccess_editor_do_action',
174
  _ajax_nonce: wp_htaccess_editor.nonce_do_action,
175
  subaction: 'save_htaccess',
176
- new_content: wp.themePluginEditor.instance.codemirror.getValue()
177
- }
178
  })
179
- .always(function(data) {
180
  swal.close();
181
  })
182
- .done(function(data) {
183
  if (typeof data.success != 'undefined' && data.success) {
184
- jQuery
185
- .get(wp_htaccess_editor.home_url)
186
- .always(function(data, text, xhr) {
187
- status = xhr.status;
188
- wphe_changed = false;
189
- if (status.substr(0, 1) != '2') {
190
- swal({ type: 'error', title: wp_htaccess_editor.site_error });
191
- } else {
192
- swal({
193
- type: 'success',
194
- title: wp_htaccess_editor.save_success,
195
- showConfirmButton: false,
196
- timer: 1000
197
- });
198
- $('#wphe-rating-notice').show();
199
- }
200
- });
201
  } else if (typeof data.success != 'undefined' && !data.success) {
202
  swal({ type: 'error', title: data.data });
203
  } else {
204
  swal({ type: 'error', title: wp_htaccess_editor.undocumented_error });
205
  }
206
  })
207
- .fail(function(data) {
208
  if (data.data) {
209
  swal({
210
  type: 'error',
211
- title: wp_htaccess_editor.documented_error + ' ' + data.data
212
  });
213
  } else {
214
  swal({ type: 'error', title: wp_htaccess_editor.undocumented_error });
@@ -218,9 +203,8 @@ jQuery(document).ready(function($) {
218
  return false;
219
  }); // save htaccess
220
 
221
-
222
  // test htaccess file
223
- $('#wphe_test_htaccess').click(function(e) {
224
  e.preventDefault();
225
 
226
  block_ui(wp_htaccess_editor.testing);
@@ -230,35 +214,37 @@ jQuery(document).ready(function($) {
230
  action: 'wp_htaccess_editor_do_action',
231
  _ajax_nonce: wp_htaccess_editor.nonce_do_action,
232
  subaction: 'test_htaccess',
233
- new_content: wp.themePluginEditor.instance.codemirror.getValue()
234
- }
235
  })
236
- .always(function(data) {
237
  swal.close();
238
  })
239
- .done(function(data) {
240
  if (typeof data.success != 'undefined' && data.success) {
241
- swal({
242
- type: 'success',
243
- title: wp_htaccess_editor.test_success,
244
- html: data.data
245
- });
246
  } else if (typeof data.success != 'undefined' && !data.success) {
247
  swal({
248
- type: 'error',
249
- title: wp_htaccess_editor.test_failed,
250
- html: data.data });
 
251
  } else {
252
  swal({
253
- type: 'error',
254
- title: wp_htaccess_editor.undocumented_error });
 
255
  }
256
  })
257
- .fail(function(data) {
258
  if (data.data) {
259
  swal({
260
  type: 'error',
261
- title: wp_htaccess_editor.test_failed
262
  });
263
  } else {
264
  swal({ type: 'error', title: wp_htaccess_editor.undocumented_error });
@@ -268,9 +254,8 @@ jQuery(document).ready(function($) {
268
  return false;
269
  }); // test htaccess
270
 
271
-
272
  // restore htaccess backup from DB
273
- $('#wphe_restore_htaccess').click(function(e) {
274
  message = wp_htaccess_editor.restore_message;
275
  swal({
276
  title: wp_htaccess_editor.restore_title,
@@ -281,8 +266,8 @@ jQuery(document).ready(function($) {
281
  confirmButtonText: wp_htaccess_editor.restore_button,
282
  cancelButtonText: wp_htaccess_editor.cancel_button,
283
  confirmButtonColor: '#dd3036',
284
- width: 600
285
- }).then(result => {
286
  if (result.value === true) {
287
  block_ui(wp_htaccess_editor.restoring);
288
  $.post({
@@ -290,33 +275,33 @@ jQuery(document).ready(function($) {
290
  data: {
291
  action: 'wp_htaccess_editor_do_action',
292
  _ajax_nonce: wp_htaccess_editor.nonce_do_action,
293
- subaction: 'restore_htaccess_from_db'
294
- }
295
  })
296
- .always(function(data) {
297
  swal.close();
298
  })
299
- .done(function(data) {
300
  if (data.success) {
301
  wphe_changed = false;
302
  swal({
303
  type: 'success',
304
  title: wp_htaccess_editor.restore_success,
305
- onClose: function() {
306
  location.reload();
307
- }
308
  });
309
  } else {
310
  swal({
311
  type: 'error',
312
- title: wp_htaccess_editor.documented_error + ' ' + data.data
313
  });
314
  }
315
  })
316
- .fail(function(data) {
317
  swal({
318
  type: 'error',
319
- title: wp_htaccess_editor.undocumented_error
320
  });
321
  });
322
  return false;
1
  /**
2
  * WP Htaccess Editor
3
+ * (c) WebFactory Ltd, 2018 - 2020
4
  */
5
 
6
+ jQuery(document).ready(function ($) {
7
  var wphe_changed = false;
8
 
9
  // setup CodeMirror
10
+ wp.CodeMirror.defineInitHook(function (wphe_cm) {
11
  // add resize handle for editor
12
  cmResize(wphe_cm);
13
 
14
  // detect user changes in editor
15
+ wphe_cm.on('change', function () {
16
  wphe_changed = true;
17
  });
18
 
19
  // detect and save editor size change
20
+ wphe_cm.on('update', function (e) {
21
  localStorage.setItem('wphe-editor-width', e.display.lastWrapWidth);
22
  localStorage.setItem('wphe-editor-height', e.display.lastWrapHeight);
23
  });
26
  $(window).off('beforeunload');
27
 
28
  // set beforeunload save check
29
+ $(window).bind('beforeunload', function () {
30
  if (wphe_changed) {
31
  return true;
32
  }
33
  });
34
+
35
  let wphe_width = parseInt(localStorage.getItem('wphe-editor-width'), 10);
36
  let wphe_height = parseInt(localStorage.getItem('wphe-editor-height'), 10);
37
+
38
+ if (!(wphe_width > 0 && wphe_height > 0)) {
39
+ wphe_width = 676;
40
+ wphe_height = 400;
41
  }
42
+
43
  if (wphe_width > 0 && wphe_height > 0) {
44
+ $('.CodeMirror').width(wphe_width).height(wphe_height);
45
+
46
+ $('#enable-editor-notice').innerHeight(wphe_height).innerWidth(wphe_width);
 
 
 
 
47
  }
48
  }); // CodeMirror setup
49
 
50
  // init code editor
51
+ wp.themePluginEditor.init($('#htaccess-editor-wrap'), wp_htaccess_editor.cm_settings);
 
 
 
52
  wp.themePluginEditor.themeOrPlugin = 'theme';
53
 
54
  // display a message while an action is performed
67
  allowEscapeKey: false,
68
  allowEnterKey: false,
69
  showConfirmButton: false,
70
+ width: 600,
71
  });
72
 
73
  return tmp;
84
  confirmButtonText: btn_confirm,
85
  cancelButtonText: btn_cancel,
86
  confirmButtonColor: '#dd3036',
87
+ width: 600,
88
  });
89
 
90
  return tmp;
91
  } // confirm_action
92
 
93
  // dismiss notice / pointer
94
+ $('.wphe-dismiss-notice').on('click', function (e) {
95
  notice_name = $(this).data('notice');
96
  if (!notice_name) {
97
  return true;
100
  $.get(ajaxurl, {
101
  notice_name: notice_name,
102
  _ajax_nonce: wp_htaccess_editor.nonce_dismiss_notice,
103
+ action: 'wp_htaccess_editor_dismiss_notice',
104
  });
105
 
106
+ $(this).parents('.notice-wrapper').fadeOut();
 
 
107
 
108
  if (notice_name == 'editor-warning') {
109
  $('#wphe-buttons').fadeIn();
114
  }); // dismiss notice
115
 
116
  // collapse / expand card
117
+ $('.card').on('click', '.toggle-card', function (e) {
118
  e.preventDefault();
119
 
120
+ card = $(this).parents('.card').toggleClass('collapsed');
121
+ $('.dashicons', this).toggleClass('dashicons-arrow-up-alt2').toggleClass('dashicons-arrow-down-alt2');
 
 
 
 
122
  $(this).blur();
123
 
124
  cards = localStorage.getItem('wp-htaccess-editor-cards');
143
  if (cards != null) {
144
  cards = JSON.parse(cards);
145
  }
146
+ $.each(cards, function (card_name, card_value) {
147
  if (card_value == 'collapsed') {
148
  $('a.toggle-card', '#' + card_name).trigger('click');
149
  }
150
  });
151
 
152
  // save htaccess file
153
+ $('#wphe_save_htaccess').click(function (e) {
154
  e.preventDefault();
155
 
156
  block_ui(wp_htaccess_editor.saving);
160
  action: 'wp_htaccess_editor_do_action',
161
  _ajax_nonce: wp_htaccess_editor.nonce_do_action,
162
  subaction: 'save_htaccess',
163
+ new_content: wp.themePluginEditor.instance.codemirror.getValue(),
164
+ },
165
  })
166
+ .always(function (data) {
167
  swal.close();
168
  })
169
+ .done(function (data) {
170
  if (typeof data.success != 'undefined' && data.success) {
171
+ jQuery.get(wp_htaccess_editor.home_url).always(function (data, text, xhr) {
172
+ status = xhr.status;
173
+ wphe_changed = false;
174
+ if (status.substr(0, 1) != '2') {
175
+ swal({ type: 'error', title: wp_htaccess_editor.site_error });
176
+ } else {
177
+ swal({
178
+ type: 'success',
179
+ title: wp_htaccess_editor.save_success,
180
+ showConfirmButton: false,
181
+ timer: 1000,
182
+ });
183
+ $('#wphe-rating-notice').show();
184
+ }
185
+ });
 
 
186
  } else if (typeof data.success != 'undefined' && !data.success) {
187
  swal({ type: 'error', title: data.data });
188
  } else {
189
  swal({ type: 'error', title: wp_htaccess_editor.undocumented_error });
190
  }
191
  })
192
+ .fail(function (data) {
193
  if (data.data) {
194
  swal({
195
  type: 'error',
196
+ title: wp_htaccess_editor.documented_error + ' ' + data.data,
197
  });
198
  } else {
199
  swal({ type: 'error', title: wp_htaccess_editor.undocumented_error });
203
  return false;
204
  }); // save htaccess
205
 
 
206
  // test htaccess file
207
+ $('#wphe_test_htaccess').click(function (e) {
208
  e.preventDefault();
209
 
210
  block_ui(wp_htaccess_editor.testing);
214
  action: 'wp_htaccess_editor_do_action',
215
  _ajax_nonce: wp_htaccess_editor.nonce_do_action,
216
  subaction: 'test_htaccess',
217
+ new_content: wp.themePluginEditor.instance.codemirror.getValue(),
218
+ },
219
  })
220
+ .always(function (data) {
221
  swal.close();
222
  })
223
+ .done(function (data) {
224
  if (typeof data.success != 'undefined' && data.success) {
225
+ swal({
226
+ type: 'success',
227
+ title: wp_htaccess_editor.test_success,
228
+ html: data.data,
229
+ });
230
  } else if (typeof data.success != 'undefined' && !data.success) {
231
  swal({
232
+ type: 'error',
233
+ title: wp_htaccess_editor.test_failed,
234
+ html: data.data,
235
+ });
236
  } else {
237
  swal({
238
+ type: 'error',
239
+ title: wp_htaccess_editor.undocumented_error,
240
+ });
241
  }
242
  })
243
+ .fail(function (data) {
244
  if (data.data) {
245
  swal({
246
  type: 'error',
247
+ title: wp_htaccess_editor.test_failed,
248
  });
249
  } else {
250
  swal({ type: 'error', title: wp_htaccess_editor.undocumented_error });
254
  return false;
255
  }); // test htaccess
256
 
 
257
  // restore htaccess backup from DB
258
+ $('#wphe_restore_htaccess').click(function (e) {
259
  message = wp_htaccess_editor.restore_message;
260
  swal({
261
  title: wp_htaccess_editor.restore_title,
266
  confirmButtonText: wp_htaccess_editor.restore_button,
267
  cancelButtonText: wp_htaccess_editor.cancel_button,
268
  confirmButtonColor: '#dd3036',
269
+ width: 600,
270
+ }).then((result) => {
271
  if (result.value === true) {
272
  block_ui(wp_htaccess_editor.restoring);
273
  $.post({
275
  data: {
276
  action: 'wp_htaccess_editor_do_action',
277
  _ajax_nonce: wp_htaccess_editor.nonce_do_action,
278
+ subaction: 'restore_htaccess_from_db',
279
+ },
280
  })
281
+ .always(function (data) {
282
  swal.close();
283
  })
284
+ .done(function (data) {
285
  if (data.success) {
286
  wphe_changed = false;
287
  swal({
288
  type: 'success',
289
  title: wp_htaccess_editor.restore_success,
290
+ onClose: function () {
291
  location.reload();
292
+ },
293
  });
294
  } else {
295
  swal({
296
  type: 'error',
297
+ title: wp_htaccess_editor.documented_error + ' ' + data.data,
298
  });
299
  }
300
  })
301
+ .fail(function (data) {
302
  swal({
303
  type: 'error',
304
+ title: wp_htaccess_editor.undocumented_error,
305
  });
306
  });
307
  return false;
readme.txt CHANGED
@@ -1,32 +1,32 @@
1
- === Htaccess Editor - Safely Edit Htaccess File ===
2
- Tags: htaccess, htaccess editor, htaccess file, htaccess backup, fix htaccess, modify htaccess, file editor, htaccess backup
3
- Contributors: WebFactory, UnderConstructionPage, googlemapswidget, securityninja, wpreset
4
  Requires at least: 4.0
5
  Requires PHP: 5.2
6
- Tested up to: 5.2
7
- Stable tag: 1.65
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- A safe & simple htaccess file editor. Test htaccess syntax before saving & automatically create htaccess file backups.
12
 
13
  == Description ==
14
 
15
- <a href="https://wphtaccess.com/?utm_source=wordpressorg&utm_medium=content&utm_campaign=wp-htaccess-editor&utm_term=readme-top">WP Htaccess Editor</a> provides a **simple, safe & fast way** to edit & test the site's .htaccess file from WP admin. Before saving htaccess can be tested for syntax errors. It also automatically creates a backup every time you make a change to the htaccess file. Backups can be restored directly from the plugin, or via FTP if the errors in .htaccess file prevent WP from running normally. For all questions, including support please use the official <a href="https://wordpress.org/support/plugin/wp-htaccess-editor">forum</a>.
16
 
17
  Access WP Htaccess Editor via WP Admin - Settings menu.
18
 
19
  #### Testing Htaccess Syntax
20
 
21
- Use the "test before saving" button to test htaccess file syntax before saving. Please note that this test does not check the logic of your htaccess file, ie if the redirects work as intended. It only checks for syntax errors.
22
 
23
- #### Automatic Backups
24
 
25
  Htaccess Editor makes automatic backups of htaccess file every time you make a change to it. Backups are located in `/wp-content/htaccess-editor-backups/` and timestamped so you can easily find the latest htaccess backup and restore it.
26
 
27
  #### WordPress Network (WPMU) Support
28
 
29
- WP Htaccess Editor is fully compatible and tested with WP Network (WPMU). It shows up under the Settings menu in network admin. It's not available in individual sites as there is only one .htaccess file per network.
30
 
31
 
32
  The plugin was originally developed by <a href="https://profiles.wordpress.org/lukenzi">Lukenzi</a> in March of 2011.
@@ -55,10 +55,15 @@ Or if needed, upload manually;
55
 
56
 
57
  == Changelog ==
 
 
 
 
58
  = v1.65 =
59
  * 2019/08/16
60
  * fixed a few bugs
61
  * new feature: test htaccess file for syntax errors before saving
 
62
  * 50,000 installations hit on 2019-08-10
63
 
64
  = v1.60 =
1
+ === Htaccess File Editor - Safely Edit Htaccess File ===
2
+ Tags: htaccess, htaccess editor, htaccess file, htaccess file editor, htaccess backup, fix htaccess, modify htaccess, file editor, htaccess fixer, htaccess error
3
+ Contributors: WebFactory
4
  Requires at least: 4.0
5
  Requires PHP: 5.2
6
+ Tested up to: 5.6
7
+ Stable tag: 1.66
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ A safe & simple htaccess file editor with automatic htaccess backups & htaccess file syntax testing.
12
 
13
  == Description ==
14
 
15
+ <a href="https://wphtaccess.com/?utm_source=wordpressorg&utm_medium=content&utm_campaign=wp-htaccess-editor&utm_term=readme-top">WP Htaccess Editor</a> provides a **simple, safe & fast way** to edit, fix & test the site's htaccess file from WP admin. Before saving, htaccess file can be tested for syntax errors. It also automatically creates a htaccess backup every time you make a change to the htaccess file. Htaccess backups can be restored directly from the plugin, or via FTP if the errors in htaccess file prevents WP from running normally. Great for fixing htaccess errors. For all questions, including support please use the official <a href="https://wordpress.org/support/plugin/wp-htaccess-editor">forum</a>.
16
 
17
  Access WP Htaccess Editor via WP Admin - Settings menu.
18
 
19
  #### Testing Htaccess Syntax
20
 
21
+ Use the "test before saving" button to test htaccess file syntax before saving. Please note that this test does not check the logic of your htaccess file, ie if the redirects work as intended. It only checks for syntax errors. If you need to fix htaccess file we suggest restoring it to the default version and then add custom code line by line.
22
 
23
+ #### Automatic Htaccess Backups
24
 
25
  Htaccess Editor makes automatic backups of htaccess file every time you make a change to it. Backups are located in `/wp-content/htaccess-editor-backups/` and timestamped so you can easily find the latest htaccess backup and restore it.
26
 
27
  #### WordPress Network (WPMU) Support
28
 
29
+ WP Htaccess Editor is fully compatible and tested with WP Network (WPMU). It shows up under the Settings menu in network admin. It's not available in individual sites as there is only one htaccess file per network.
30
 
31
 
32
  The plugin was originally developed by <a href="https://profiles.wordpress.org/lukenzi">Lukenzi</a> in March of 2011.
55
 
56
 
57
  == Changelog ==
58
+ = v1.66 =
59
+ * 2020/10/17
60
+ * minor bug fixes
61
+
62
  = v1.65 =
63
  * 2019/08/16
64
  * fixed a few bugs
65
  * new feature: test htaccess file for syntax errors before saving
66
+ * new feature: htaccess backup
67
  * 50,000 installations hit on 2019-08-10
68
 
69
  = v1.60 =
wp-htaccess-editor.php CHANGED
@@ -3,14 +3,17 @@
3
  Plugin Name: WP Htaccess Editor
4
  Plugin URI: https://wphtaccess.com/
5
  Description: Safe and easy way to edit the .htaccess file directly from WP admin without using FTP.
6
- Version: 1.65
 
 
 
7
  Author: WebFactory Ltd
8
  Author URI: https://www.webfactoryltd.com/
9
  Text Domain: wp-htaccess-editor
10
  Network: true
11
 
12
  Copyright 2011 - 2018 Lukenzi (email: lukenzi@gmail.com)
13
- Copyright 2018 - 2019 WebFactory Ltd (email: support@webfactoryltd.com)
14
 
15
  This program is free software; you can redistribute it and/or modify
16
  it under the terms of the GNU General Public License, version 2, as
@@ -783,7 +786,7 @@ class WP_Htaccess_Editor
783
  /**
784
  * Restore last .htaccess backup from DB.
785
  *
786
- * @return bool
787
  */
788
  function restore_db_backup()
789
  {
@@ -908,7 +911,7 @@ class WP_Htaccess_Editor
908
  * Adds plugins to recommended list
909
  *
910
  * @param object $res List of plugins for recommended list
911
- *
912
  * @return object
913
  */
914
  function plugins_api_result($res)
@@ -917,6 +920,7 @@ class WP_Htaccess_Editor
917
 
918
  $res = $this->add_plugin_favs('wp-reset', $res);
919
  $res = $this->add_plugin_favs('eps-301-redirects', $res);
 
920
 
921
  return $res;
922
  } // plugins_api_result
@@ -926,7 +930,7 @@ class WP_Htaccess_Editor
926
  * Helper function for adding plugins to recommended list
927
  *
928
  * @param $args
929
- *
930
  * @return $args
931
  */
932
  function featured_plugins_tab($args)
@@ -942,7 +946,7 @@ class WP_Htaccess_Editor
942
  *
943
  * @param string $plugin_slug Plugin slug
944
  * @param object $res List of plugins
945
- *
946
  * @return object $res List of plugins
947
  */
948
  function add_plugin_favs($plugin_slug, $res)
@@ -998,7 +1002,8 @@ class WP_Htaccess_Editor
998
  * @return null
999
  */
1000
  private function __clone()
1001
- { }
 
1002
 
1003
 
1004
  /**
@@ -1007,7 +1012,8 @@ class WP_Htaccess_Editor
1007
  * @return null
1008
  */
1009
  private function __sleep()
1010
- { }
 
1011
 
1012
 
1013
  /**
@@ -1016,7 +1022,8 @@ class WP_Htaccess_Editor
1016
  * @return null
1017
  */
1018
  private function __wakeup()
1019
- { }
 
1020
  } // WP_Htaccess_Editor class
1021
 
1022
 
@@ -1027,4 +1034,7 @@ if (is_admin()) {
1027
  $wp_htaccess_editor = WP_Htaccess_Editor::get_instance();
1028
  add_action('plugins_loaded', array($wp_htaccess_editor, 'load_textdomain'));
1029
  register_uninstall_hook(__FILE__, array('WP_Htaccess_Editor', 'uninstall'));
 
 
 
1030
  }
3
  Plugin Name: WP Htaccess Editor
4
  Plugin URI: https://wphtaccess.com/
5
  Description: Safe and easy way to edit the .htaccess file directly from WP admin without using FTP.
6
+ Version: 1.66
7
+ Requires at least: 4.0
8
+ Requires PHP: 5.2
9
+ Tested up to: 5.6
10
  Author: WebFactory Ltd
11
  Author URI: https://www.webfactoryltd.com/
12
  Text Domain: wp-htaccess-editor
13
  Network: true
14
 
15
  Copyright 2011 - 2018 Lukenzi (email: lukenzi@gmail.com)
16
+ Copyright 2018 - 2020 WebFactory Ltd (email: support@webfactoryltd.com)
17
 
18
  This program is free software; you can redistribute it and/or modify
19
  it under the terms of the GNU General Public License, version 2, as
786
  /**
787
  * Restore last .htaccess backup from DB.
788
  *
789
+ * @return bool|WP_Error
790
  */
791
  function restore_db_backup()
792
  {
911
  * Adds plugins to recommended list
912
  *
913
  * @param object $res List of plugins for recommended list
914
+ *
915
  * @return object
916
  */
917
  function plugins_api_result($res)
920
 
921
  $res = $this->add_plugin_favs('wp-reset', $res);
922
  $res = $this->add_plugin_favs('eps-301-redirects', $res);
923
+ $res = $this->add_plugin_favs('simple-author-box', $res);
924
 
925
  return $res;
926
  } // plugins_api_result
930
  * Helper function for adding plugins to recommended list
931
  *
932
  * @param $args
933
+ *
934
  * @return $args
935
  */
936
  function featured_plugins_tab($args)
946
  *
947
  * @param string $plugin_slug Plugin slug
948
  * @param object $res List of plugins
949
+ *
950
  * @return object $res List of plugins
951
  */
952
  function add_plugin_favs($plugin_slug, $res)
1002
  * @return null
1003
  */
1004
  private function __clone()
1005
+ {
1006
+ }
1007
 
1008
 
1009
  /**
1012
  * @return null
1013
  */
1014
  private function __sleep()
1015
+ {
1016
+ }
1017
 
1018
 
1019
  /**
1022
  * @return null
1023
  */
1024
  private function __wakeup()
1025
+ {
1026
+ }
1027
  } // WP_Htaccess_Editor class
1028
 
1029
 
1034
  $wp_htaccess_editor = WP_Htaccess_Editor::get_instance();
1035
  add_action('plugins_loaded', array($wp_htaccess_editor, 'load_textdomain'));
1036
  register_uninstall_hook(__FILE__, array('WP_Htaccess_Editor', 'uninstall'));
1037
+
1038
+ require_once dirname(__FILE__) . '/wp301/wp301.php';
1039
+ new wf_wp301(__FILE__, 'settings_page_wp-htaccess-editor');
1040
  }
wp301/wp301-logo.png ADDED
Binary file
wp301/wp301.js ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Campaign for WP 301 Redirects PRO
3
+ * (c) WebFactory Ltd, 2020
4
+ */
5
+
6
+ jQuery(document).ready(function ($) {
7
+ $('#wp301promo_dismiss').on('click', function (e) {
8
+ e.preventDefault();
9
+
10
+ var slug = $(this).data('plugin-slug');
11
+
12
+ $.get({
13
+ url: ajaxurl,
14
+ data: {
15
+ action: 'wp301_promo_dismiss',
16
+ slug: slug,
17
+ _ajax_nonce: wp301_promo.nonce_wp301_promo_dismiss,
18
+ },
19
+ })
20
+ .always(function (data) {})
21
+ .done(function (data) {
22
+ if (data.success) {
23
+ if (slug == 'dashboard') {
24
+ $('#wp301promo_widget').hide();
25
+ } else {
26
+ $('#wp301-dialog').dialog('close');
27
+ }
28
+ } else {
29
+ alert('Sorry, something is not right. Please reload the page and try again.');
30
+ }
31
+ })
32
+ .fail(function (data) {
33
+ alert('Sorry, something is not right. Please reload the page and try again.');
34
+ });
35
+ }); // dismiss
36
+
37
+
38
+ $('#wp301promo_submit').on('click', function (e) {
39
+ e.preventDefault();
40
+
41
+ var btn = $('#wp301promo_submit');
42
+ var name = $('#wp301promo_name').val();
43
+ var email = $('#wp301promo_email').val();
44
+ var plugin = $('#wp301promo_plugin').val();
45
+ var position = $('#wp301promo_position').val();
46
+ var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
47
+
48
+ if (name.length < 2 || name.length > 128) {
49
+ $('#wp301promo_name').focus();
50
+ alert('Please enter your name. Thank you 👍');
51
+ return false;
52
+ }
53
+ if (!regex.test(email) || email.lenght > 128) {
54
+ $('#wp301promo_email').focus();
55
+ alert('Please enter a valid email address. Thank you 👍');
56
+ return false;
57
+ }
58
+
59
+ $(btn).addClass('disabled');
60
+ $.get({
61
+ url: ajaxurl,
62
+ data: {
63
+ action: 'wp301_promo_submit',
64
+ _ajax_nonce: wp301_promo.nonce_wp301_promo_submit,
65
+ name: name,
66
+ email: email,
67
+ position: position,
68
+ plugin: plugin,
69
+ },
70
+ })
71
+ .always(function (data) {
72
+ $(btn).removeClass('disabled');
73
+ })
74
+ .done(function (data) {
75
+ if (data.success) {
76
+ alert(data.data);
77
+
78
+ if (position == 'dashboard') {
79
+ $('#wp301promo_widget').hide();
80
+ } else {
81
+ $('#wp301-dialog').dialog('close');
82
+ }
83
+ } else {
84
+ alert(data.data);
85
+ }
86
+ })
87
+ .fail(function (data) {
88
+ alert('Sorry, something is not right. Please reload the page and try again.');
89
+ });
90
+ });
91
+
92
+
93
+ $('#wp301promo_name, #wp301promo_email').on('keypress', function (e) {
94
+ if (e.which == 13) {
95
+ $('#wp301promo_submit').trigger('click');
96
+ }
97
+ }); // on enter
98
+
99
+
100
+ if (wp301_promo.open_popup && $('#wp301-dialog').length == 1) {
101
+ $('#wp301-dialog').dialog({
102
+ dialogClass: 'wp-dialog wp301-dialog',
103
+ modal: true,
104
+ resizable: false,
105
+ width: 550,
106
+ height: 'auto',
107
+ show: 'fade',
108
+ hide: 'fade',
109
+ close: function (event, ui) {},
110
+ open: function (event, ui) {
111
+ $(this)
112
+ .siblings()
113
+ .find('span.ui-dialog-title')
114
+ .html('Get a WP 301 Redirects PRO license for FREE <del>$158</del>');
115
+ wp301_fix_dialog_close(event, ui);
116
+ },
117
+ autoOpen: true,
118
+ closeOnEscape: false,
119
+ });
120
+ } // open dialog
121
+ }); // jQuery ready
122
+
123
+
124
+ function wp301_fix_dialog_close(event, ui) {
125
+ jQuery('.ui-widget-overlay').bind('click', function () {
126
+ jQuery('#' + event.target.id).dialog('close');
127
+ });
128
+ } // wp301_fix_dialog_close
wp301/wp301.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Campaign for WP 301 Redirects PRO
5
+ * (c) WebFactory Ltd, 2020
6
+ */
7
+
8
+
9
+ if (false == class_exists('wf_wp301')) {
10
+ class wf_wp301
11
+ {
12
+ var $plugin_file = '';
13
+ var $plugin_slug = '';
14
+ var $plugin_screen = '';
15
+ var $options = '';
16
+ var $disable_dashboard = false;
17
+
18
+
19
+ function __construct($plugin_file, $plugin_screen)
20
+ {
21
+ $this->plugin_file = $plugin_file;
22
+ $this->plugin_slug = basename(dirname($plugin_file));
23
+ $this->plugin_screen = $plugin_screen;
24
+ $this->options = get_option('wp301promo', array());
25
+
26
+ if (!is_admin() || !empty($this->options['email_submitted']) || date('Y-m-d') > '2020-11-05') {
27
+ return;
28
+ } else {
29
+ add_action('admin_init', array($this, 'init'));
30
+ }
31
+ } // __construct
32
+
33
+
34
+ function init()
35
+ {
36
+ add_action('wp_dashboard_setup', array($this, 'add_widget'));
37
+ add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
38
+ add_action('wp_ajax_wp301_promo_submit', array($this, 'ajax_submit'));
39
+ add_action('wp_ajax_wp301_promo_dismiss', array($this, 'ajax_dismiss'));
40
+ add_action('admin_footer', array($this, 'admin_footer'));
41
+ } // init
42
+
43
+
44
+ function admin_enqueue_scripts()
45
+ {
46
+ $screen = get_current_screen();
47
+
48
+ if ($screen->base != 'dashboard' && $screen->id != $this->plugin_screen) {
49
+ return;
50
+ }
51
+
52
+ if ($screen->base == 'dashboard' && (!empty($this->options['popup_dismissed_dashboard']) || !empty($this->disable_dashboard))) {
53
+ return;
54
+ }
55
+
56
+ if ($screen->id == $this->plugin_screen) {
57
+ wp_enqueue_style('wp-jquery-ui-dialog');
58
+ wp_enqueue_script('jquery-ui-dialog');
59
+ }
60
+
61
+ wp_enqueue_script('wp301_promo', plugin_dir_url($this->plugin_file) . 'wp301/wp301.js');
62
+
63
+ $js_vars = array(
64
+ 'nonce_wp301_promo_submit' => wp_create_nonce('wp301_submit'),
65
+ 'nonce_wp301_promo_dismiss' => wp_create_nonce('wp301_dismiss'),
66
+ );
67
+
68
+ if (empty($this->options['popup_dismissed_' . $this->plugin_slug])) {
69
+ $js_vars['open_popup'] = true;
70
+ }
71
+
72
+ wp_localize_script('wp301_promo', 'wp301_promo', $js_vars);
73
+ } // admin_enqueue_scripts
74
+
75
+
76
+ function ajax_dismiss()
77
+ {
78
+ if (!wp_verify_nonce(@$_GET['_ajax_nonce'], 'wp301_dismiss')) {
79
+ wp_send_json_error('Something is not right. Please reload the page and try again.');
80
+ }
81
+
82
+ $slug = substr(strip_tags(trim(@$_GET['slug'])), 0, 64);
83
+
84
+ $this->options['popup_dismissed_' . $slug] = true;
85
+ $tmp = update_option('wp301promo', $this->options);
86
+
87
+ if ($tmp) {
88
+ wp_send_json_success();
89
+ } else {
90
+ wp_send_json_error();
91
+ }
92
+ } // ajax_dismiss
93
+
94
+
95
+ function ajax_submit()
96
+ {
97
+ if (!wp_verify_nonce(@$_GET['_ajax_nonce'], 'wp301_submit')) {
98
+ wp_send_json_error('Something is not right. Please reload the page and try again.');
99
+ }
100
+
101
+ $email = strip_tags(trim(@$_GET['email']));
102
+ $name = strip_tags(trim(@$_GET['name']));
103
+ $plugin = strip_tags(trim(@$_GET['plugin'])) . '-' . strip_tags(trim(@$_GET['position']));
104
+
105
+ if (!is_email($email)) {
106
+ wp_send_json_error('Please enter a valid email address.');
107
+ }
108
+
109
+ $url = add_query_arg(array('name' => $name, 'email' => $email, 'plugin' => $plugin), 'https://wp301redirects.com/subscribe/');
110
+
111
+ $response = wp_remote_get($url, array('timeout' => 25));
112
+
113
+ if (is_wp_error($response)) {
114
+ wp_send_json_error('Something is not right. Please reload the page and try again.');
115
+ }
116
+
117
+ $body = @json_decode(wp_remote_retrieve_body($response), true);
118
+ if (empty($body['success'])) {
119
+ wp_send_json_error('Something is not right. Please reload the page and try again.');
120
+ }
121
+
122
+ $this->options['email_submitted'] = true;
123
+ update_option('wp301promo', $this->options);
124
+ wp_send_json_success('Thank you for trusting us with your email! You\'ll hear from us soon 🚀');
125
+ } // ajax_submit
126
+
127
+
128
+ function add_widget()
129
+ {
130
+ if (!empty($this->options['popup_dismissed_dashboard']) || !empty($this->disable_dashboard)) {
131
+ return;
132
+ }
133
+
134
+ add_meta_box('wp301promo_widget', 'Get a WP 301 Redirects PRO license for FREE <del>$158</del>', array($this, 'widget_content'), 'dashboard', 'side', 'high');
135
+ } // add_widget
136
+
137
+
138
+ function widget_content()
139
+ {
140
+ $out = '';
141
+
142
+ $out .= '<style>';
143
+ $out .= '#wp301promo_widget .disabled { pointer-events: none; }';
144
+ $out .= '#wp301promo_widget label { font-weight: normal; display: inline-block; width: 15%; margin-bottom: 10px; }';
145
+ $out .= '#wp301promo_widget input { width: 74%; margin-bottom: 10px; }';
146
+ $out .= '#wp301promo_widget .button-primary { padding: 14px 28px; text-decoration: none; line-height: 1; }';
147
+ $out .= '#wp301promo_dismiss { font-style: italic; display: inline-block; color: #444; text-decoration: none; margin: 8px 0 0 0; }';
148
+ $out .= '#wp301promo_dismiss:hover { text-decoration: underline; }';
149
+ $out .= '#wp301promo_widget, #wp301promo_widget p { font-size: 14px; }';
150
+ $out .= '#wp301promo_widget .title301 { font-weight: 600; margin: 10px 0 -10px 0; }';
151
+ $out .= '#wp301promo_widget img { max-width: 45%; max-height: 80px; }';
152
+ $out .= '#wp301promo_widget .center { text-align: center; }';
153
+ $out .= '#wp301promo_email { margin-bottom: 0 !important; }';
154
+ $out .= '#wp301promo_widget { background-color: #fafafa; }';
155
+ $out .= '#wp301promo_widget li a { text-decoration: underline; }';
156
+ $out .= '#wp301promo_widget .wp301inside { padding: 25px 12px 0px 12px; position: relative; }';
157
+ $out .= '#wp301promo_widget p { margin-top: 14px; line-height: 1.5; }';
158
+ $out .= '#wp301promo_widget small { margin-left: 17%; }';
159
+ $out .= '#wp301promo_widget ul { font-size: 14px; margin: 0 0 20px 0; list-style-type: disc; list-style-position: inside; }';
160
+ $out .= '#wp301promo_widget li { margin-bottom: 3px; }';
161
+ $out .= '#wp301promo_submit span { display: none; text-decoration: none; margin-right: 10px; animation: wf-spin-animation 1.5s infinite linear; }';
162
+ $out .= '#wp301promo_submit.disabled span { display: inline-block; }';
163
+ $out .= '@keyframes wf-spin-animation {
164
+ from { transform: rotate(0deg); }
165
+ to { transform: rotate(360deg); }
166
+ }';
167
+ $out .= '#wp301promo_widget .inside { overflow: hidden; margin: 0; }
168
+ #wp301promo_widget .ribbon { margin: 0; padding: 11px 20px 10px 20px; background: #007cba; color: #FFF; font-weight: 800; position: absolute; top: -17px; right: -17px; transform: translateX(30%) translateY(0%) rotate(45deg); transform-origin: top left; letter-spacing: 1px; }
169
+ #wp301promo_widget .ribbon:before, #wp301promo_widget .ribbon:after { content: ""; position: absolute; top:0; margin: 0 -1px; width: 100%; height: 100%; background: #007cba; }
170
+ #wp301promo_widget .ribbon:before { right:100%; }
171
+ #wp301promo_widget .ribbon:after { left:100%; }';
172
+ $out .= '</style>';
173
+
174
+ $plugin_url = plugin_dir_url($this->plugin_file);
175
+
176
+ $out .= '<div class="ribbon">FREE</div>';
177
+ $out .= '<div class="wp301inside">';
178
+
179
+ $out .= '<div class="center"><a href="https://wp301redirects.com/free-license/?ref=free-' . $this->plugin_slug . '-dashboard" target="_blank"><img src="' . $plugin_url . 'wp301/wp301-logo.png' . '" alt="WP 301 Redirects PRO" title="WP 301 Redirects PRO"></a></div>';
180
+
181
+ $out .= '<p>On November 6th <a href="https://www.webfactoryltd.com/" target="_blank">WebFactory Ltd</a> will give away a limited number of lifetime WP 301 Redirect PRO licenses, <b>each for 10 sites</b>. A $158 retail value! 🚀 Leave your email, we\'ll send you a link &amp; download your copy.</p><p style="margin-bottom: 0;"><b>What do I get?</b></p>';
182
+
183
+ $out .= '<ul>';
184
+ $out .= '<li>Automatically fix 404 errors &amp; URL typos</li>';
185
+ $out .= '<li>Create advanced redirect rules &amp; control affiliate links</li>';
186
+ $out .= '<li>Detailed log of all redirects &amp; 404s</li>';
187
+ $out .= '<li>Manage all sites\' licenses from a central Dashboard</li>';
188
+ $out .= '<li>Lifetime license for 10 sites. <a href="https://wp301redirects.com/free-license/?ref=free-' . $this->plugin_slug . '-dashboard" target="_blank">See all features</a></li>';
189
+ $out .= '</ul>';
190
+
191
+ $out .= '
192
+ <div>
193
+ <label for="wp301promo_name">Name:</label>
194
+ <input type="text" name="wp301promo_name" id="wp301promo_name" placeholder="How shall we call you?"><br>
195
+ <label for="wp301promo_email">Email:</label>
196
+ <input type="text" name="wp301promo_email" id="wp301promo_email" placeholder="Your best email address to get the plugin"><br>
197
+ <small>We hate spam as much as you do and never send it!</small>
198
+ <input type="hidden" id="wp301promo_plugin" value="' . $this->plugin_slug . '">
199
+ <input type="hidden" id="wp301promo_position" value="dashboard">
200
+ </div>
201
+
202
+ <p class="center">
203
+ <a id="wp301promo_submit" class="button button-primary" href="#"><span class="dashicons dashicons-update"></span>I Want My FREE License <del>$158</del></a><br>
204
+ <a id="wp301promo_dismiss" class="" href="#" data-plugin-slug="dashboard">I don\'t want a free license; don\'t show this again</a>
205
+ </p>
206
+ </div>';
207
+
208
+ echo $out;
209
+ } // widget_content
210
+
211
+
212
+ function admin_footer()
213
+ {
214
+ $screen = get_current_screen();
215
+ if ($screen->id != $this->plugin_screen) {
216
+ return;
217
+ }
218
+
219
+ $out = '';
220
+
221
+ $out .= '<style>';
222
+ $out .= '#wp301promo_widget .disabled { pointer-events: none; }';
223
+ $out .= '.wp301-dialog .ui-dialog-titlebar-close { visibility: hidden; }';
224
+ $out .= '#wp301-dialog label { font-weight: normal; display: inline-block; width: 15%; margin-bottom: 10px; }';
225
+ $out .= '#wp301-dialog input { width: 74%; margin-bottom: 10px; }';
226
+ $out .= '#wp301-dialog .button-primary { padding: 14px 28px; text-decoration: none; line-height: 1; }';
227
+ $out .= '#wp301-dialog, #wp301-dialog p { font-size: 14px; }';
228
+ $out .= '#wp301-dialog .title301 { font-size: 1.3em; font-weight: 600; margin: 10px 0 -10px 0; }';
229
+ $out .= '#wp301-dialog img { max-width: 60%; }';
230
+ $out .= '#wp301-dialog li a { text-decoration: underline; }';
231
+ $out .= '#wp301-dialog small { margin-left: 16%; }';
232
+ $out .= '#wp301-dialog .center { text-align: center; }';
233
+ $out .= '#wp301-dialog, .wp301-dialog .ui-dialog-titlebar { background-color: #fafafa; }';
234
+ $out .= '#wp301-dialog .wp301inside { padding: 12px 12px 0px 12px; }';
235
+ $out .= '#wp301-dialog p { margin-top: 14px; line-height: 1.5; }';
236
+ $out .= '#wp301-dialog ul { margin: 0 0 20px 0; list-style-type: disc; list-style-position: inside; }';
237
+ $out .= '#wp301-dialog li { margin-bottom: 3px; }';
238
+ $out .= '#wp301promo_dismiss { display: inline-block; color: #444; text-decoration: none; margin: 8px 0 0 0; }';
239
+ $out .= '#wp301promo_dismiss:hover { text-decoration: underline; }';
240
+ $out .= '#wp301promo_submit span { display: none; text-decoration: none; margin-right: 10px; animation: wf-spin-animation 1.5s infinite linear; }';
241
+ $out .= '#wp301promo_submit.disabled span { display: inline-block; }';
242
+ $out .= '@keyframes wf-spin-animation {
243
+ from { transform: rotate(0deg); }
244
+ to { transform: rotate(360deg); }
245
+ }';
246
+ $out .= '#wp301-dialog .inside { overflow: hidden; margin: 0; }
247
+ #wp301-dialog .ribbon { margin: 0; padding: 11px 20px 10px 20px; background: #007cba; color: #FFF; font-weight: 800; position: absolute; top: -17px; right: -17px; transform: translateX(30%) translateY(0%) rotate(45deg); transform-origin: top left; letter-spacing: 1px; }
248
+ #wp301-dialog .ribbon:before, #wp301-dialog .ribbon:after { content: ""; position: absolute; top:0; margin: 0 -1px; width: 100%; height: 100%; background: #007cba; }
249
+ #wp301-dialog .ribbon:before { right:100%; }
250
+ #wp301-dialog .ribbon:after { left:100%; }';
251
+ $out .= '</style>';
252
+
253
+ $out .= '<div id="wp301-dialog" style="display: none;" title="Get a WP 301 Redirects PRO license for FREE"><span class="ui-helper-hidden-accessible"><input type="text"/></span>';
254
+
255
+ $plugin_url = plugin_dir_url($this->plugin_file);
256
+
257
+ $out .= '<div class="wp301inside">';
258
+ $out .= '<div class="ribbon">FREE</div>';
259
+
260
+ $out .= '<div class="center"><a href="https://wp301redirects.com/free-license/?ref=free-' . $this->plugin_slug . '-popup" target="_blank"><img src="' . $plugin_url . 'wp301/wp301-logo.png' . '" alt="WP 301 Redirects PRO" title="WP 301 Redirects PRO"></a></div>';
261
+
262
+ $out .= '<p>On November 6th <a href="https://www.webfactoryltd.com/" target="_blank">WebFactory Ltd</a> will give away a limited number of lifetime WP 301 Redirect PRO licenses, <b>each for 10 sites</b>. A $158 retail value! 🚀 Leave your email, we\'ll send you a link &amp; download your copy.</p><p style="margin-bottom: 0;"><b>What do I get?</b></p>';
263
+
264
+ $out .= '<ul>';
265
+ $out .= '<li>Automatically fix 404 errors &amp; URL typos</li>';
266
+ $out .= '<li>Create advanced redirect rules &amp; control affiliate links</li>';
267
+ $out .= '<li>Detailed log of all redirects &amp; 404s</li>';
268
+ $out .= '<li>Manage all sites\' licenses from a central Dashboard</li>';
269
+ $out .= '<li>Lifetime license for 10 sites. <a href="https://wp301redirects.com/free-license/?ref=free-' . $this->plugin_slug . '-popup" target="_blank">See all features</a></li>';
270
+ $out .= '</ul>';
271
+
272
+ $out .= '
273
+ <div>
274
+ <label for="wp301promo_name">Name:</label>
275
+ <input type="text" name="wp301promo_name" id="wp301promo_name" placeholder="How shall we call you?"><br>
276
+ <label for="wp301promo_email">Email:</label>
277
+ <input type="text" name="wp301promo_email" id="wp301promo_email" placeholder="Your best email address to get the plugin"><br>
278
+ <small>We hate spam as much as you do and never send it!</small>
279
+ <input type="hidden" id="wp301promo_plugin" value="' . $this->plugin_slug . '">
280
+ <input type="hidden" id="wp301promo_position" value="popup">
281
+ </div>
282
+
283
+ <p class="center">
284
+ <a id="wp301promo_submit" class="button button-primary" href="#"><span class="dashicons dashicons-update"></span>I Want My FREE License <del>$158</del></a><br>
285
+ <a id="wp301promo_dismiss" class="" href="#" data-plugin-slug="' . $this->plugin_slug . '">I don\'t want a free license; don\'t show this again</a>
286
+ </p>
287
+
288
+ </div>';
289
+
290
+ $out .= '</div>';
291
+
292
+ echo $out;
293
+ } // wp_footer
294
+ } // wf_wp301
295
+ }