WP Htaccess Editor - Version 1.55

Version Description

Download this release

Release Info

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

Code changes from version 1.5 to 1.55

css/wp-htaccess-editor.css CHANGED
@@ -8,6 +8,11 @@
8
  width: 520px;
9
  }
10
 
 
 
 
 
 
11
  .tools_page_wp-htaccess-editor .toggle-card {
12
  position: absolute;
13
  right: 2em;
@@ -127,8 +132,9 @@
127
  }
128
 
129
  #htaccess-editor-wrap .CodeMirror, #htaccess-editor-wrap textarea {
130
- width: 100%;
131
- max-width: 574px;
 
132
  min-height: 300px;
133
  height: calc(100vh - 400px);
134
  border: 1px solid #ddd;
8
  width: 520px;
9
  }
10
 
11
+ .tools_page_wp-htaccess-editor h1 img {
12
+ max-height: 50px;
13
+ width: auto;
14
+ }
15
+
16
  .tools_page_wp-htaccess-editor .toggle-card {
17
  position: absolute;
18
  right: 2em;
132
  }
133
 
134
  #htaccess-editor-wrap .CodeMirror, #htaccess-editor-wrap textarea {
135
+ width: 574px;
136
+ min-width: 300px;
137
+ max-width: 100%;
138
  min-height: 300px;
139
  height: calc(100vh - 400px);
140
  border: 1px solid #ddd;
img/wp-htaccess-editor-logo.png ADDED
Binary file
js/cm-resize.min.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * cm-resize v1.0.0
3
+ * https://github.com/Sphinxxxx/cm-resize
4
+ *
5
+ * Copyright 2017-2018 Andreas Borgen (https://github.com/Sphinxxxx)
6
+ * Released under the MIT license.
7
+ */
8
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.cmResize=t()}(this,function(){"use strict";return document.documentElement.firstElementChild.appendChild(document.createElement("style")).textContent=".cm-resize-handle{display:block;position:absolute;bottom:0;right:0;z-index:99;width:10px;height:10px;opacity:0.5;background:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0,0 16,16'%3E%3Cpath stroke='gray' stroke-width='2' d='M-1,12 l18,-18 M-1,18 l18,-18 M-1,24 l18,-18 M-1,30 l18,-18'/%3E%3C/svg%3E\") center/cover;box-shadow:inset -1px -1px 0 0 silver;cursor:nwse-resize}",function(r,e){var t,c=(e=e||{}).minWidth||200,l=e.minHeight||100,s=!1!==e.resizableWidth,d=!1!==e.resizableHeight,n=e.cssClass||"cm-resize-handle",o=r.display.wrapper,i=e.handle||((t=o.appendChild(document.createElement("div"))).className=n,t),a=o.querySelector(".CodeMirror-vscrollbar"),u=o.querySelector(".CodeMirror-hscrollbar");function h(){e.handle||(a.style.bottom="18px",u.style.right="18px")}r.on("update",h),h();var f=void 0,m=void 0;return function(e){var t=Element.prototype;t.matches||(t.matches=t.msMatchesSelector||t.webkitMatchesSelector),t.closest||(t.closest=function(e){var t=this;do{if(t.matches(e))return t;t="svg"===t.tagName?t.parentNode:t.parentElement}while(t);return null});var l=(e=e||{}).container||document.documentElement,n=e.selector,o=e.callback||console.log,i=e.callbackDragStart,a=e.callbackDragEnd,r=e.callbackClick,c=e.propagateEvents,s=!1!==e.roundCoords,d=!1!==e.dragOutside,u=e.handleOffset||!1!==e.handleOffset,h=null;switch(u){case"center":h=!0;break;case"topleft":case"top-left":h=!1}var f=void 0,m=void 0,p=void 0;function v(e,t,n,o){var i=e.clientX,a=e.clientY;function r(e,t,n){return Math.max(t,Math.min(e,n))}if(t){var c=t.getBoundingClientRect();i-=c.left,a-=c.top,n&&(i-=n[0],a-=n[1]),o&&(i=r(i,0,c.width),a=r(a,0,c.height)),t!==l&&(null!==h?h:"circle"===t.nodeName||"ellipse"===t.nodeName)&&(i-=c.width/2,a-=c.height/2)}return s?[Math.round(i),Math.round(a)]:[i,a]}function g(e){e.preventDefault(),c||e.stopPropagation()}function w(e){(f=n?n instanceof Element?n.contains(e.target)?n:null:e.target.closest(n):{})&&(g(e),m=n&&u?v(e,f):[0,0],p=v(e,l,m),s&&(p=p.map(Math.round)),i&&i(f,p))}function b(e){if(f){g(e);var t=v(e,l,m,!d);o(f,t,p)}}function E(e){if(f){if(a||r){var t=v(e,l,m,!d);r&&p[0]===t[0]&&p[1]===t[1]&&r(f,p),a&&a(f,t,p)}f=null}}function x(e){E(C(e))}function M(e){return void 0!==e.buttons?1===e.buttons:1===e.which}function k(e,t){1===e.touches.length?t(C(e)):E(e)}function C(e){var t=e.targetTouches[0];return t||(t=e.changedTouches[0]),t.preventDefault=e.preventDefault.bind(e),t.stopPropagation=e.stopPropagation.bind(e),t}l.addEventListener("mousedown",function(e){M(e)&&w(e)}),l.addEventListener("touchstart",function(e){k(e,w)}),window.addEventListener("mousemove",function(e){f&&(M(e)?b(e):E(e))}),window.addEventListener("touchmove",function(e){k(e,b)}),window.addEventListener("mouseup",function(e){f&&!M(e)&&E(e)}),l.addEventListener("touchend",x),l.addEventListener("touchcancel",x)}({container:i.offsetParent,selector:i,callbackDragStart:function(e,t){f=t,m=[o.clientWidth,o.clientHeight]},callback:function(e,t){var n=t[0]-f[0],o=t[1]-f[1],i=s?Math.max(c,m[0]+n):null,a=d?Math.max(l,m[1]+o):null;r.setSize(i,a)}}),i}});
js/wp-htaccess-editor.js CHANGED
@@ -5,6 +5,30 @@
5
 
6
 
7
  jQuery(document).ready(function($) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  // init code editor
9
  wp.themePluginEditor.init($('#htaccess-editor-wrap'), wp_htaccess_editor.cm_settings);
10
  wp.themePluginEditor.themeOrPlugin = 'theme';
@@ -127,10 +151,9 @@ jQuery(document).ready(function($) {
127
  swal.close();
128
  }).done(function(data) {
129
  if (typeof data.success != 'undefined' && data.success) {
130
- // TODO: bug; does not work if user continues to edit after saving; we need to re-hook it
131
- $(window).off('beforeunload');
132
  jQuery.get(wp_htaccess_editor.home_url).always(function(data, text, xhr) {
133
  status = xhr.status;
 
134
  if (status.substr(0, 1) != '2') {
135
  swal({ type: 'error', title: wp_htaccess_editor.site_error });
136
  } else {
@@ -181,8 +204,7 @@ jQuery(document).ready(function($) {
181
  swal.close();
182
  }).done(function(data) {
183
  if (data.success) {
184
- // TODO: see note on line #130
185
- $(window).off('beforeunload');
186
  swal({ type: 'success', title: wp_htaccess_editor.restore_success, onClose: function() { location.reload(); } });
187
  } else {
188
  swal({ type: 'error', title: wp_htaccess_editor.documented_error + ' ' + data.data });
5
 
6
 
7
  jQuery(document).ready(function($) {
8
+ var wphe_changed = false;
9
+
10
+ // setup CodeMirror
11
+ wp.CodeMirror.defineInitHook(function(wphe_cm) {
12
+ // add resize handle for editor
13
+ cmResize(wphe_cm);
14
+
15
+ // detect user changes in editor
16
+ wphe_cm.on('change', function() {
17
+ wphe_changed = true;
18
+ });
19
+
20
+ // kill WP's beforeunload
21
+ $(window).off('beforeunload');
22
+
23
+ // set beforeunload save check
24
+ $(window).bind('beforeunload', function() {
25
+ if (wphe_changed) {
26
+ return true;
27
+ }
28
+ });
29
+ }); // CodeMirror setup
30
+
31
+
32
  // init code editor
33
  wp.themePluginEditor.init($('#htaccess-editor-wrap'), wp_htaccess_editor.cm_settings);
34
  wp.themePluginEditor.themeOrPlugin = 'theme';
151
  swal.close();
152
  }).done(function(data) {
153
  if (typeof data.success != 'undefined' && data.success) {
 
 
154
  jQuery.get(wp_htaccess_editor.home_url).always(function(data, text, xhr) {
155
  status = xhr.status;
156
+ wphe_changed = false;
157
  if (status.substr(0, 1) != '2') {
158
  swal({ type: 'error', title: wp_htaccess_editor.site_error });
159
  } else {
204
  swal.close();
205
  }).done(function(data) {
206
  if (data.success) {
207
+ wphe_changed = false;
 
208
  swal({ type: 'success', title: wp_htaccess_editor.restore_success, onClose: function() { location.reload(); } });
209
  } else {
210
  swal({ type: 'error', title: wp_htaccess_editor.documented_error + ' ' + data.data });
readme.txt CHANGED
@@ -4,7 +4,7 @@ Contributors: WebFactory, UnderConstructionPage, googlemapswidget, securityninja
4
  Requires at least: 4.0
5
  Requires PHP: 5.2
6
  Tested up to: 5.0
7
- Stable tag: 1.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -12,15 +12,15 @@ A safe & simple htaccess file editor with automatic backup.
12
 
13
  == Description ==
14
 
15
- WP Htaccess Editor provides a simple, safe and fast way to edit the site's .htaccess file from WP admin. It automatically makes backups 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 the "Tools" menu in WP admin.
18
 
19
  #### Automatic Backups
20
 
21
- 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.
22
 
23
- The plugin was originally developed by <a href="https://profiles.wordpress.org/lukenzi">Lukenzi</a> in March of 2011.
24
 
25
  == Installation ==
26
 
@@ -47,7 +47,13 @@ Or if needed, upload manually;
47
 
48
  == Changelog ==
49
 
50
- = v1.5 =
 
 
 
 
 
 
51
  * 2018/12/21
52
  * WebFactory took over development
53
  * complete plugin rewrite
@@ -95,7 +101,7 @@ Or if needed, upload manually;
95
  = I've killed my site! Help!? =
96
 
97
  Nothing is lost or deleted. You can easily get your site back.
98
- You're probably getting an error 500 or a white screen (of death). First connect to your site via FTP and locate the .htaccess file. Delete it, or rename it. Try the site again - it should open. If it did locate the backup of the old, working .htaccess file in /wp-content/htaccess-editor-backups/ copy the file to your site's root folder and you're back in business.
99
 
100
  = I get an error saying the .htaccess file can't be edited or created =
101
 
4
  Requires at least: 4.0
5
  Requires PHP: 5.2
6
  Tested up to: 5.0
7
+ Stable tag: 1.55
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
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 the site's .htaccess file from WP admin. It 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 the "Tools" menu in WP admin.
18
 
19
  #### Automatic Backups
20
 
21
+ 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.
22
 
23
+ The plugin was originally developed by <a href="https://profiles.wordpress.org/lukenzi">Lukenzi</a> in March of 2011.
24
 
25
  == Installation ==
26
 
47
 
48
  == Changelog ==
49
 
50
+ = v1.55 =
51
+ * 2019/01/15
52
+ * added code editor resize feature
53
+ * fixed a few bugs
54
+ * 40k installations hit on 2019-01-09 with 172,000 downloads
55
+
56
+ = v1.50 =
57
  * 2018/12/21
58
  * WebFactory took over development
59
  * complete plugin rewrite
101
  = I've killed my site! Help!? =
102
 
103
  Nothing is lost or deleted. You can easily get your site back.
104
+ You're probably getting an error 500 or a white screen (of death). First connect to your site via FTP and locate the .htaccess file. Delete it, or rename it. Try the site again - it should open. If it did locate the backup of the old, working .htaccess file in `/wp-content/htaccess-editor-backups/` copy the file to your site's root folder and you're back in business.
105
 
106
  = I get an error saying the .htaccess file can't be edited or created =
107
 
wp-htaccess-editor.php CHANGED
@@ -1,8 +1,9 @@
1
  <?php
2
  /*
3
  Plugin Name: WP Htaccess Editor
 
4
  Description: Safe and easy way to edit the .htaccess file directly from WP admin without using FTP.
5
- Version: 1.5
6
  Author: WebFactory Ltd
7
  Author URI: https://www.webfactoryltd.com/
8
  Text Domain: wp-htaccess-editor
@@ -125,9 +126,11 @@ class WP_Htaccess_Editor {
125
  return $links;
126
  }
127
 
 
128
  $support_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-htaccess-editor" title="' . __('Get help', 'wp-htaccess-editor') . '">' . __('Support', 'wp-htaccess-editor') . '</a>';
129
  $rate_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-htaccess-editor/reviews/#new-post" title="' . __('Rate the plugin', 'wp-htaccess-editor') . '">' . __('Rate the plugin ★★★★★', 'wp-htaccess-editor') . '</a>';
130
 
 
131
  $links[] = $support_link;
132
  $links[] = $rate_link;
133
 
@@ -163,10 +166,10 @@ class WP_Htaccess_Editor {
163
  return $text_org;
164
  }
165
 
166
- $text = '<i>WP Htaccess Editor v' . $this->version . ' by <a href="https://www.webfactoryltd.com/" title="' . __('Visit our site to get more great plugins', 'wp-htaccess-editor'). '" target="_blank">WebFactory Ltd</a>.';
167
  $text .= ' Please <a target="_blank" href="https://wordpress.org/support/plugin/wp-htaccess-editor/reviews/#new-post" title="' . __('Rate the plugin', 'wp-htaccess-editor') . '">' . __('Rate the plugin ★★★★★', 'wp-htaccess-editor') . '</a>.</i> ';
168
 
169
- return $text . $text_org;
170
  } // admin_footer_text
171
 
172
 
@@ -218,18 +221,10 @@ class WP_Htaccess_Editor {
218
  * @return string
219
  */
220
  function get_htaccess_path($folder_only = false) {
221
- $slashed_home = trailingslashit(get_option('home'));
222
- $base = parse_url($slashed_home, PHP_URL_PATH);
223
- $document_root_fix = str_replace('\\', '/', realpath($_SERVER['DOCUMENT_ROOT']));
224
- $abspath_fix = str_replace('\\', '/', ABSPATH);
225
- $home_path = 0 === strpos($abspath_fix, $document_root_fix) ? $document_root_fix . $base : get_home_path();
226
-
227
- $filepath = $home_path . '.htaccess';
228
-
229
  if ($folder_only) {
230
- return $home_path;
231
  } else {
232
- return $filepath;
233
  }
234
  } // get_htaccess_path
235
 
@@ -288,7 +283,7 @@ class WP_Htaccess_Editor {
288
  $change = true;
289
  }
290
  if (empty($options['options'])) {
291
- $options['options'] = array('last_backup' => '');
292
  $change = true;
293
  }
294
  if ($change) {
@@ -383,6 +378,38 @@ class WP_Htaccess_Editor {
383
  } // admin_menu
384
 
385
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  /**
387
  * Dismiss notice via AJAX call
388
  *
@@ -509,6 +536,7 @@ class WP_Htaccess_Editor {
509
  wp_enqueue_script('wp-htaccess-editor-sweetalert2', $this->plugin_url . 'js/sweetalert2.min.js', array('jquery'), $this->version, true);
510
  wp_enqueue_script('wp-theme-plugin-editor');
511
  wp_enqueue_script('wp-htaccess-editor', $this->plugin_url . 'js/wp-htaccess-editor.js', array('jquery'), $this->version, true);
 
512
  wp_localize_script('wp-htaccess-editor', 'wp_htaccess_editor', $js_localize);
513
 
514
  // fix for aggressive plugins that include their CSS files on all pages
@@ -560,10 +588,11 @@ class WP_Htaccess_Editor {
560
 
561
  wp_send_json_success();
562
  } elseif ($subaction == 'restore_htaccess_from_db') {
563
- if ($this->restore_db_backup()) {
 
564
  wp_send_json_success();
565
  } else {
566
- wp_send_json_error();
567
  }
568
  } else {
569
  wp_send_json_error(__('Unknown subaction.', 'wp-htaccess-editor'));
@@ -681,6 +710,11 @@ class WP_Htaccess_Editor {
681
  $htaccess_path = $this->get_htaccess_path();
682
 
683
  $backup_contents = $this->get_options('last_backup');
 
 
 
 
 
684
  if (!empty($backup_contents)) {
685
  @clearstatcache();
686
  $write = $this->wp_filesystem->put_contents($htaccess_path, $backup_contents);
@@ -688,10 +722,10 @@ class WP_Htaccess_Editor {
688
  if ($write) {
689
  return true;
690
  } else {
691
- return false;
692
  }
693
  } else {
694
- return false;
695
  }
696
  } // restore_db_backup
697
 
@@ -715,14 +749,14 @@ class WP_Htaccess_Editor {
715
 
716
  settings_errors();
717
  echo '<div class="wrap">';
718
- echo '<h1>' . __('WP Htaccess Editor', 'wp-htaccess-editor') . '</h1>';
719
  echo '<form id="wp-htaccess-editor-form" action="' . admin_url('tools.php?page=wp-htaccess-editor') . '" method="post" autocomplete="off">';
720
 
721
  // TODO: properly mark for translation
722
  if (false === $this->is_htaccess_readable()) {
723
  echo '<div class="card notice-wrapper notice-error">';
724
  echo '<h2>' . __('.htaccess file does not exist!', 'wp-htaccess-editor') . '</h2>';
725
- echo '<p>We couldn\'t locate your .htaccess file on the default location <code>' . $this->get_htaccess_path() . '</code>. We\'ll attempt to create the file when you make the first save with the editor.<br>We recommend opening <a href="' . admin_url('options-permalink.php') . '">Settings - Permalinks</a> and setting a URL structure other than default which will create the default WP .htaccess file.</p>';
726
  echo '</div>';
727
  $notice_shown = true;
728
  }
@@ -745,7 +779,7 @@ class WP_Htaccess_Editor {
745
  }
746
 
747
  // ask for rating after a few saves
748
- if ($meta['edits_count'] > 2 && false === $notice_shown && false == $this->get_dismissed_notices('rate')) {
749
  echo '<div class="card notice-wrapper">';
750
  echo '<h2>' . __('Please help us keep the plugin free &amp; up-to-date', 'wp-htaccess-editor') . '</h2>';
751
  echo '<p>' . __('If you use &amp; enjoy WP Htaccess Editor, <b>please rate it on WordPress.org</b>. It only takes a second and helps us keep the plugin free and maintained. Thank you!', 'wp-htaccess-editor') . '</p>';
@@ -763,7 +797,7 @@ class WP_Htaccess_Editor {
763
  echo 'For more details about .htaccess syntax and examples, please visit the <a href="http://httpd.apache.org/docs/current/howto/htaccess.html" target="_blank">official Apache Tutorial</a>.</p>';
764
 
765
  echo '<b>How to restore the site in case of error 500 or white screen caused by .htaccess</b>';
766
- echo '<p>Do not panic. No data is lost, and your site will be up again in minutes. FTP to your site or open the server\'s control panel such as cPanel to locate the .htaccess file in <code>' . $this->get_htaccess_path() . '</code>. Once you find the file there are several options to restore the site.<br>The first option is to edit the file to fix the errors you made.<br>The second one is to delete the file. Obviously, any custom rules in it will be gone, and in order for permalinks to work again you have to visit WP Admin - Options - Permalinks and click "Save Changes". This will rebuild the default .htaccess file.<br>Third (and preferred) way of fixing is to restore the file from the backup which you\'ll find in the <code>' . $this->get_backup_folder() . '</code> folder. The folder will probably contain multiple backup files. Locate the latest one by looking at the timestamp in the filename. Once located copy the file to <code>' . $this->get_htaccess_path(true) . '</code> and rename it to .htaccess.</p>';
767
 
768
  echo '<b>How to restore .htaccess in case of a non-white-screen error</b>';
769
  echo '<p>Click the "Restore Last Saved Backup" button below the editor and .htaccess will be restored to the version before the last save. Please note that this method only works if the error in the file is logical, not syntactical. For instance, if you banned the wrong IP you can undo. But if you misspelled "RewriteCond" you have to use the method above as the only way to recover is via FTP or cPanel.</p>';
@@ -822,8 +856,10 @@ class WP_Htaccess_Editor {
822
 
823
 
824
  // Create plugin instance and hook things up
825
- // TODO: load everything only in admin!
826
- global $wp_htaccess_editor;
827
- $wp_htaccess_editor = WP_Htaccess_Editor::get_instance();
828
- add_action('plugins_loaded', array($wp_htaccess_editor, 'load_textdomain'));
829
- register_uninstall_hook(__FILE__, array('WP_Htaccess_Editor', 'uninstall'));
 
 
1
  <?php
2
  /*
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.55
7
  Author: WebFactory Ltd
8
  Author URI: https://www.webfactoryltd.com/
9
  Text Domain: wp-htaccess-editor
126
  return $links;
127
  }
128
 
129
+ $home_link = '<a target="_blank" href="' . $this->generate_web_link('plugins-table-right') . '" title="' . __('Plugin Homepage', 'wp-htaccess-editor') . '">' . __('Plugin Homepage', 'wp-htaccess-editor') . '</a>';
130
  $support_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-htaccess-editor" title="' . __('Get help', 'wp-htaccess-editor') . '">' . __('Support', 'wp-htaccess-editor') . '</a>';
131
  $rate_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-htaccess-editor/reviews/#new-post" title="' . __('Rate the plugin', 'wp-htaccess-editor') . '">' . __('Rate the plugin ★★★★★', 'wp-htaccess-editor') . '</a>';
132
 
133
+ $links[] = $home_link;
134
  $links[] = $support_link;
135
  $links[] = $rate_link;
136
 
166
  return $text_org;
167
  }
168
 
169
+ $text = '<i><a target="_blank" href="' . $this->generate_web_link('admin_footer') . '">WP Htaccess Editor</a> v' . $this->version . ' by <a href="https://www.webfactoryltd.com/" title="' . __('Visit our site to get more great plugins', 'wp-htaccess-editor'). '" target="_blank">WebFactory Ltd</a>.';
170
  $text .= ' Please <a target="_blank" href="https://wordpress.org/support/plugin/wp-htaccess-editor/reviews/#new-post" title="' . __('Rate the plugin', 'wp-htaccess-editor') . '">' . __('Rate the plugin ★★★★★', 'wp-htaccess-editor') . '</a>.</i> ';
171
 
172
+ return $text;
173
  } // admin_footer_text
174
 
175
 
221
  * @return string
222
  */
223
  function get_htaccess_path($folder_only = false) {
 
 
 
 
 
 
 
 
224
  if ($folder_only) {
225
+ return get_home_path();
226
  } else {
227
+ return get_home_path() . '.htaccess';
228
  }
229
  } // get_htaccess_path
230
 
283
  $change = true;
284
  }
285
  if (empty($options['options'])) {
286
+ $options['options'] = array('last_backup' => false);
287
  $change = true;
288
  }
289
  if ($change) {
378
  } // admin_menu
379
 
380
 
381
+ /**
382
+ * Helper function for generating UTM tagged links
383
+ *
384
+ * @param string $placement Optional. UTM content param.
385
+ * @param string $page Optional. Page to link to.
386
+ * @param array $params Optional. Extra URL params.
387
+ * @param string $anchor Optional. URL anchor part.
388
+ *
389
+ * @return string
390
+ */
391
+ function generate_web_link($placement = '', $page = '/', $params = array(), $anchor = '') {
392
+ $base_url = 'https://wphtaccess.com';
393
+
394
+ if ('/' != $page) {
395
+ $page = '/' . trim($page, '/') . '/';
396
+ }
397
+ if ($page == '//') {
398
+ $page = '/';
399
+ }
400
+
401
+ $parts = array_merge(array('utm_source' => 'wp-htaccess-free', 'utm_medium' => 'plugin', 'utm_content' => $placement, 'utm_campaign' => 'wp-htaccess-free-v' . $this->version), $params);
402
+
403
+ if (!empty($anchor)) {
404
+ $anchor = '#' . trim($anchor, '#');
405
+ }
406
+
407
+ $out = $base_url . $page . '?' . http_build_query($parts, '', '&amp;') . $anchor;
408
+
409
+ return $out;
410
+ } // generate_web_link
411
+
412
+
413
  /**
414
  * Dismiss notice via AJAX call
415
  *
536
  wp_enqueue_script('wp-htaccess-editor-sweetalert2', $this->plugin_url . 'js/sweetalert2.min.js', array('jquery'), $this->version, true);
537
  wp_enqueue_script('wp-theme-plugin-editor');
538
  wp_enqueue_script('wp-htaccess-editor', $this->plugin_url . 'js/wp-htaccess-editor.js', array('jquery'), $this->version, true);
539
+ wp_enqueue_script('wp-htaccess-cm-resize', $this->plugin_url . 'js/cm-resize.min.js', array('jquery'), $this->version, true);
540
  wp_localize_script('wp-htaccess-editor', 'wp_htaccess_editor', $js_localize);
541
 
542
  // fix for aggressive plugins that include their CSS files on all pages
588
 
589
  wp_send_json_success();
590
  } elseif ($subaction == 'restore_htaccess_from_db') {
591
+ $res = $this->restore_db_backup();
592
+ if (!is_wp_error($res)) {
593
  wp_send_json_success();
594
  } else {
595
+ wp_send_json_error($res->get_error_message());
596
  }
597
  } else {
598
  wp_send_json_error(__('Unknown subaction.', 'wp-htaccess-editor'));
710
  $htaccess_path = $this->get_htaccess_path();
711
 
712
  $backup_contents = $this->get_options('last_backup');
713
+
714
+ if (false === $backup_contents) {
715
+ return new WP_Error(1, __('There is no available backup to restore.', 'wp-htaccess-editor'));
716
+ }
717
+
718
  if (!empty($backup_contents)) {
719
  @clearstatcache();
720
  $write = $this->wp_filesystem->put_contents($htaccess_path, $backup_contents);
722
  if ($write) {
723
  return true;
724
  } else {
725
+ return new WP_Error(1, __('Unable to write .htaccess file.', 'wp-htaccess-editor'));
726
  }
727
  } else {
728
+ return new WP_Error(1, __('Backup data is empty.', 'wp-htaccess-editor'));
729
  }
730
  } // restore_db_backup
731
 
749
 
750
  settings_errors();
751
  echo '<div class="wrap">';
752
+ echo '<h1><img src="' . $this->plugin_url . 'img/wp-htaccess-editor-logo.png" alt="' . __('WP Htaccess Editor', 'wp-htaccess-editor') . '" title="' . __('WP Htaccess Editor', 'wp-htaccess-editor') . '"></h1>';
753
  echo '<form id="wp-htaccess-editor-form" action="' . admin_url('tools.php?page=wp-htaccess-editor') . '" method="post" autocomplete="off">';
754
 
755
  // TODO: properly mark for translation
756
  if (false === $this->is_htaccess_readable()) {
757
  echo '<div class="card notice-wrapper notice-error">';
758
  echo '<h2>' . __('.htaccess file does not exist!', 'wp-htaccess-editor') . '</h2>';
759
+ echo '<p>We couldn\'t locate your .htaccess file on the default location <code>' . $this->get_htaccess_path() . '</code>. We\'ll attempt to create the file when you make the first save with the editor.<br>We recommend opening <a href="' . admin_url('options-permalink.php') . '">Settings - Permalinks</a> and setting a URL structure other than plain which will create the default WP .htaccess file.</p>';
760
  echo '</div>';
761
  $notice_shown = true;
762
  }
779
  }
780
 
781
  // ask for rating after a few saves
782
+ if ($meta['edits_count'] > 1 && false === $notice_shown && false == $this->get_dismissed_notices('rate')) {
783
  echo '<div class="card notice-wrapper">';
784
  echo '<h2>' . __('Please help us keep the plugin free &amp; up-to-date', 'wp-htaccess-editor') . '</h2>';
785
  echo '<p>' . __('If you use &amp; enjoy WP Htaccess Editor, <b>please rate it on WordPress.org</b>. It only takes a second and helps us keep the plugin free and maintained. Thank you!', 'wp-htaccess-editor') . '</p>';
797
  echo 'For more details about .htaccess syntax and examples, please visit the <a href="http://httpd.apache.org/docs/current/howto/htaccess.html" target="_blank">official Apache Tutorial</a>.</p>';
798
 
799
  echo '<b>How to restore the site in case of error 500 or white screen caused by .htaccess</b>';
800
+ echo '<p>Do not panic. No data is lost, and your site will be up again in minutes. FTP to your site or open the server\'s control panel such as cPanel to locate the .htaccess file in <code>' . $this->get_htaccess_path() . '</code>. Once you find the file there are several options to restore the site.<br><br>The first option is to edit the file to fix the errors you made.<br><br>The second one is to delete the file. Obviously, any custom rules in it will be gone, and in order for permalinks to work again you have to visit <a href="' . admin_url('options-permalink.php') . '">WP Admin - Options - Permalinks</a> and click "Save Changes". This will rebuild the default .htaccess file.<br><br>Third (and preferred) way of fixing is to restore the file from the backup which you\'ll find in the <code>' . $this->get_backup_folder() . '</code> folder. The folder will probably contain multiple backup files. Locate the latest one by looking at the timestamp in the filename. Once located copy the file to <code>' . $this->get_htaccess_path(true) . '</code> and rename it to .htaccess.</p>';
801
 
802
  echo '<b>How to restore .htaccess in case of a non-white-screen error</b>';
803
  echo '<p>Click the "Restore Last Saved Backup" button below the editor and .htaccess will be restored to the version before the last save. Please note that this method only works if the error in the file is logical, not syntactical. For instance, if you banned the wrong IP you can undo. But if you misspelled "RewriteCond" you have to use the method above as the only way to recover is via FTP or cPanel.</p>';
856
 
857
 
858
  // Create plugin instance and hook things up
859
+ // Only in admin; there's no frontend functionality
860
+ if (is_admin()) {
861
+ global $wp_htaccess_editor;
862
+ $wp_htaccess_editor = WP_Htaccess_Editor::get_instance();
863
+ add_action('plugins_loaded', array($wp_htaccess_editor, 'load_textdomain'));
864
+ register_uninstall_hook(__FILE__, array('WP_Htaccess_Editor', 'uninstall'));
865
+ }