class-epsilon-feedback-sab.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. class Epsilon_Feedback_SAB {
  3. private $plugin_file = '';
  4. private $plugin_name = '';
  5. function __construct( $_plugin_file ) {
  6. $this->plugin_file = $_plugin_file;
  7. $this->plugin_name = basename( $this->plugin_file, '.php' );
  8. // Deactivation
  9. add_filter(
  10. 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array(
  11. $this,
  12. 'filter_action_links',
  13. )
  14. );
  15. add_action( 'admin_footer-plugins.php', array( $this, 'goodbye_ajax' ) );
  16. add_action( 'wp_ajax_epsilon_deactivate_plugin', array( $this, 'epsilon_deactivate_plugin_callback' ) );
  17. }
  18. /**
  19. * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
  20. *
  21. * @since 1.0.0
  22. */
  23. public function filter_action_links( $links ) {
  24. if ( isset( $links['deactivate'] ) ) {
  25. $deactivation_link = $links['deactivate'];
  26. // Insert an onClick action to allow form before deactivating
  27. $deactivation_link = str_replace( '<a ', '<div class="epsilon-deactivate-form-wrapper"><span class="epsilon-deactivate-form" id="epsilon-deactivate-form-' . esc_attr( $this->plugin_name ) . '"></span></div><a onclick="javascript:event.preventDefault();" id="epsilon-deactivate-link-' . esc_attr( $this->plugin_name ) . '" ', $deactivation_link );
  28. $links['deactivate'] = $deactivation_link;
  29. }
  30. return $links;
  31. }
  32. /**
  33. * Form text strings
  34. * These can be filtered
  35. *
  36. * @since 1.0.0
  37. */
  38. public function goodbye_ajax() {
  39. // Get our strings for the form
  40. $form = $this->get_form_info();
  41. // Build the HTML to go in the form
  42. $html = '<div class="epsilon-deactivate-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
  43. $html .= '<div class="epsilon-deactivate-form-body"><p>' . esc_html( $form['body'] ) . '</p>';
  44. if ( is_array( $form['options'] ) ) {
  45. $html .= '<div class="epsilon-deactivate-options"><p>';
  46. foreach ( $form['options'] as $key => $option ) {
  47. if ( 'features' == $key ) {
  48. $html .= '<input type="radio" name="epsilon-deactivate-reason" checked="checked" id="' . esc_attr( $key ) . '" value="' . esc_attr( $key ) . '"> <label for="' . esc_attr( $key ) . '">' . esc_attr( $option ) . '</label><br>';
  49. } else {
  50. $html .= '<input type="radio" name="epsilon-deactivate-reason" id="' . esc_attr( $key ) . '" value="' . esc_attr( $key ) . '"> <label for="' . esc_attr( $key ) . '">' . esc_attr( $option ) . '</label><br>';
  51. }
  52. }
  53. $html .= '</p><label id="epsilon-deactivate-details-label" for="epsilon-deactivate-reasons"><strong>' . esc_html( $form['details'] ) . '</strong></label><textarea name="epsilon-deactivate-details" id="epsilon-deactivate-details" rows="2" style="width:100%"></textarea>';
  54. $html .= '<input type="checkbox" name="epsilon-deactivate-tracking" checked="" id="allow-tracking" value="yes"> <label for="allow-tracking">' . esc_html__( 'Allow us to get more information in order to improve our plugin', 'saboxplugin' ) . '</label><br>';
  55. $html .= '</div><!-- .epsilon-deactivate-options -->';
  56. }
  57. $html .= '</div><!-- .epsilon-deactivate-form-body -->';
  58. $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'saboxplugin' ) . '</p>';
  59. $html .= '<div class="epsilon-deactivate-form-footer"><p><a id="epsilon-deactivate-plugin" href="#">' . __( 'Just Deactivate', 'saboxplugin' ) . '</a><a id="epsilon-deactivate-submit-form" class="button button-primary" href="#">' . __( 'Submit and Deactivate', 'saboxplugin' ) . '</a></p></div>'
  60. ?>
  61. <div class="epsilon-deactivate-form-bg"></div>
  62. <style type="text/css">
  63. .epsilon-deactivate-form-active .epsilon-deactivate-form-bg {
  64. background: rgba(0, 0, 0, .5);
  65. position: fixed;
  66. top: 0;
  67. left: 0;
  68. width: 100%;
  69. height: 100%;
  70. }
  71. .epsilon-deactivate-form-wrapper {
  72. position: relative;
  73. z-index: 999;
  74. display: none;
  75. }
  76. .epsilon-deactivate-form-active .epsilon-deactivate-form-wrapper {
  77. display: block;
  78. }
  79. .epsilon-deactivate-form {
  80. display: none;
  81. }
  82. .epsilon-deactivate-form-active .epsilon-deactivate-form {
  83. position: absolute;
  84. bottom: 30px;
  85. left: 0;
  86. max-width: 400px;
  87. background: #fff;
  88. white-space: normal;
  89. }
  90. .epsilon-deactivate-form-head {
  91. background: #272754;
  92. color: #fff;
  93. padding: 8px 18px;
  94. }
  95. .epsilon-deactivate-form-body {
  96. padding: 8px 18px;
  97. color: #444;
  98. }
  99. .deactivating-spinner {
  100. display: none;
  101. }
  102. .deactivating-spinner .spinner {
  103. float: none;
  104. margin: 4px 4px 0 18px;
  105. vertical-align: bottom;
  106. visibility: visible;
  107. }
  108. .epsilon-deactivate-form-footer {
  109. padding: 8px 18px;
  110. }
  111. .epsilon-deactivate-form-footer p {
  112. display: flex;
  113. align-items: center;
  114. justify-content: space-between;
  115. }
  116. .epsilon-deactivate-form.process-response .epsilon-deactivate-form-body,
  117. .epsilon-deactivate-form.process-response .epsilon-deactivate-form-footer {
  118. position: relative;
  119. }
  120. .epsilon-deactivate-form.process-response .epsilon-deactivate-form-body:after,
  121. .epsilon-deactivate-form.process-response .epsilon-deactivate-form-footer:after {
  122. content: "";
  123. display: block;
  124. position: absolute;
  125. top: 0;
  126. left: 0;
  127. width: 100%;
  128. height: 100%;
  129. background-color: rgba(255, 255, 255, .5);
  130. }
  131. </style>
  132. <script>
  133. jQuery( document ).ready( function( $ ) {
  134. var deactivateURL = $( "#epsilon-deactivate-link-<?php echo esc_attr( $this->plugin_name ); ?>" ),
  135. formContainer = $( '#epsilon-deactivate-form-<?php echo esc_attr( $this->plugin_name ); ?>' ),
  136. detailsStrings = {
  137. 'setup': '<?php echo __( 'What was the dificult part ?', 'saboxplugin' ); ?>',
  138. 'documentation': '<?php echo __( 'What can we describe more ?', 'saboxplugin' ); ?>',
  139. 'features': '<?php echo __( 'How could we improve ?', 'saboxplugin' ); ?>',
  140. 'better-plugin': '<?php echo __( 'Can you mention it ?', 'saboxplugin' ); ?>',
  141. 'incompatibility': '<?php echo __( 'With what plugin or theme is incompatible ?', 'saboxplugin' ); ?>',
  142. };
  143. $( deactivateURL ).on( "click", function() {
  144. // We'll send the user to this deactivation link when they've completed or dismissed the form
  145. var url = deactivateURL.attr( 'href' );
  146. $( 'body' ).toggleClass( 'epsilon-deactivate-form-active' );
  147. formContainer.fadeIn( {
  148. complete: function() {
  149. var offset = formContainer.offset();
  150. if( offset.top < 50 ) {
  151. $(this).parent().css('top', (50 - offset.top) + 'px')
  152. }
  153. $( 'body' ).animate( { scrollTop: Math.max( 0, offset.top - 50 ) } );
  154. }
  155. } );
  156. formContainer.html( '<?php echo $html; ?>' );
  157. formContainer.on( 'change', 'input[name="epsilon-deactivate-reason"]', function() {
  158. var detailsLabel = formContainer.find( '#epsilon-deactivate-details-label strong' );
  159. var value = formContainer.find( 'input[name="epsilon-deactivate-reason"]:checked' ).val();
  160. detailsLabel.text( detailsStrings[ value ] );
  161. } );
  162. formContainer.on( 'click', '#epsilon-deactivate-submit-form', function( e ) {
  163. var data = {
  164. 'action': 'epsilon_deactivate_plugin',
  165. 'security': "<?php echo wp_create_nonce( 'epsilon_deactivate_plugin' ); ?>",
  166. 'dataType': "json"
  167. };
  168. e.preventDefault();
  169. // As soon as we click, the body of the form should disappear
  170. formContainer.addClass( 'process-response' );
  171. // Fade in spinner
  172. formContainer.find( ".deactivating-spinner" ).fadeIn();
  173. data[ 'reason' ] = formContainer.find( 'input[name="epsilon-deactivate-reason"]:checked' ).val();
  174. data[ 'details' ] = formContainer.find( '#epsilon-deactivate-details' ).val();
  175. data[ 'tracking' ] = formContainer.find( '#allow-tracking:checked' ).length;
  176. $.post(
  177. ajaxurl,
  178. data,
  179. function( response ) {
  180. // Redirect to original deactivation URL
  181. window.location.href = url;
  182. }
  183. );
  184. } );
  185. formContainer.on( 'click', '#epsilon-deactivate-plugin', function( e ) {
  186. e.preventDefault();
  187. window.location.href = url;
  188. } );
  189. // If we click outside the form, the form will close
  190. $( '.epsilon-deactivate-form-bg' ).on( 'click', function() {
  191. formContainer.fadeOut();
  192. $( 'body' ).removeClass( 'epsilon-deactivate-form-active' );
  193. } );
  194. } );
  195. } );
  196. </script>
  197. <?php
  198. }
  199. /*
  200. * Form text strings
  201. * These are non-filterable and used as fallback in case filtered strings aren't set correctly
  202. * @since 1.0.0
  203. */
  204. public function get_form_info() {
  205. $form = array();
  206. $form['heading'] = __( 'Sorry to see you go', 'saboxplugin' );
  207. $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'saboxplugin' );
  208. $form['options'] = array(
  209. 'setup' => __( 'Set up is too difficult', 'saboxplugin' ),
  210. 'documentation' => __( 'Lack of documentation', 'saboxplugin' ),
  211. 'features' => __( 'Not the features I wanted', 'saboxplugin' ),
  212. 'better-plugin' => __( 'Found a better plugin', 'saboxplugin' ),
  213. 'incompatibility' => __( 'Incompatible with theme or plugin', 'saboxplugin' ),
  214. );
  215. $form['details'] = __( 'How could we improve ?', 'saboxplugin' );
  216. return $form;
  217. }
  218. public function epsilon_deactivate_plugin_callback() {
  219. check_ajax_referer( 'epsilon_deactivate_plugin', 'security' );
  220. if ( isset( $_POST['reason'] ) && isset( $_POST['details'] ) && isset( $_POST['tracking'] ) ) {
  221. require_once 'class-epsilon-plugin-request-sab.php';
  222. $args = array(
  223. 'reason' => $_POST['reason'],
  224. 'details' => $_POST['details'],
  225. 'tracking' => $_POST['tracking'],
  226. );
  227. $request = new Epsilon_Plugin_Request_SAB( $this->plugin_file, $args );
  228. if ( $request->request_successful ) {
  229. echo json_encode(
  230. array(
  231. 'status' => 'ok',
  232. )
  233. );
  234. } else {
  235. echo json_encode(
  236. array(
  237. 'status' => 'nok',
  238. )
  239. );
  240. }
  241. } else {
  242. echo json_encode(
  243. array(
  244. 'status' => 'ok',
  245. )
  246. );
  247. }
  248. die();
  249. }
  250. }