PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.3
Code Manager v1.0.3
1.0.48 1.0.47 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.3 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.4 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9
code-manager / freemius / templates / forms / deactivation / form.php
code-manager / freemius / templates / forms / deactivation Last commit date
contact.php 5 years ago form.php 5 years ago index.php 5 years ago retry-skip.php 5 years ago
form.php
544 lines
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.1.2
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * @var array $VARS
15 */
16 $fs = freemius( $VARS['id'] );
17 $slug = $fs->get_slug();
18
19 $subscription_cancellation_dialog_box_template_params = $VARS['subscription_cancellation_dialog_box_template_params'];
20 $show_deactivation_feedback_form = $VARS['show_deactivation_feedback_form'];
21 $confirmation_message = $VARS['uninstall_confirmation_message'];
22
23 $is_anonymous = ( ! $fs->is_registered() );
24 $anonymous_feedback_checkbox_html = '';
25
26 $reasons_list_items_html = '';
27
28 if ( $show_deactivation_feedback_form ) {
29 $reasons = $VARS['reasons'];
30
31 foreach ( $reasons as $reason ) {
32 $list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' );
33
34 if ( isset( $reason['internal_message'] ) && ! empty( $reason['internal_message'] ) ) {
35 $list_item_classes .= ' has-internal-message';
36 $reason_internal_message = $reason['internal_message'];
37 } else {
38 $reason_internal_message = '';
39 }
40
41 $reason_input_type = ( ! empty( $reason['input_type'] ) ? $reason['input_type'] : '' );
42 $reason_input_placeholder = ( ! empty( $reason['input_placeholder'] ) ? $reason['input_placeholder'] : '' );
43
44 $reason_list_item_html = <<< HTML
45 <li class="{$list_item_classes}"
46 data-input-type="{$reason_input_type}"
47 data-input-placeholder="{$reason_input_placeholder}">
48 <label>
49 <span>
50 <input type="radio" name="selected-reason" value="{$reason['id']}"/>
51 </span>
52 <span>{$reason['text']}</span>
53 </label>
54 <div class="internal-message">{$reason_internal_message}</div>
55 </li>
56 HTML;
57
58 $reasons_list_items_html .= $reason_list_item_html;
59 }
60
61 if ( $is_anonymous ) {
62 $anonymous_feedback_checkbox_html = sprintf(
63 '<label class="anonymous-feedback-label"><input type="checkbox" class="anonymous-feedback-checkbox"> %s</label>',
64 fs_esc_html_inline( 'Anonymous feedback', 'anonymous-feedback', $slug )
65 );
66 }
67 }
68
69 // Aliases.
70 $deactivate_text = fs_text_inline( 'Deactivate', 'deactivate', $slug );
71 $theme_text = fs_text_inline( 'Theme', 'theme', $slug );
72 $activate_x_text = fs_text_inline( 'Activate %s', 'activate-x', $slug );
73
74 fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
75
76 if ( ! empty( $subscription_cancellation_dialog_box_template_params ) ) {
77 fs_require_template( 'forms/subscription-cancellation.php', $subscription_cancellation_dialog_box_template_params );
78 }
79 ?>
80 <script type="text/javascript">
81 (function ($) {
82 var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ) ?>,
83 modalHtml =
84 '<div class="fs-modal fs-modal-deactivation-feedback<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">'
85 + ' <div class="fs-modal-dialog">'
86 + ' <div class="fs-modal-header">'
87 + ' <h4><?php fs_esc_attr_echo_inline( 'Quick Feedback', 'quick-feedback' , $slug ) ?></h4>'
88 + ' </div>'
89 + ' <div class="fs-modal-body">'
90 + ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>'
91 + ' <div class="fs-modal-panel active" data-panel-id="reasons"><h3><strong><?php echo esc_js( sprintf( fs_text_inline( 'If you have a moment, please let us know why you are %s', 'deactivation-share-reason' , $slug ), ( $fs->is_plugin() ? fs_text_inline( 'deactivating', 'deactivating', $slug ) : fs_text_inline( 'switching', 'switching', $slug ) ) ) ) ?>:</strong></h3><ul id="reasons-list">' + reasonsHtml + '</ul></div>'
92 + ' </div>'
93 + ' <div class="fs-modal-footer">'
94 + ' <?php echo $anonymous_feedback_checkbox_html ?>'
95 + ' <a href="#" class="button button-secondary button-deactivate"></a>'
96 + ' <a href="#" class="button button-secondary button-close"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel', $slug ) ?></a>'
97 + ' </div>'
98 + ' </div>'
99 + '</div>',
100 $modal = $(modalHtml),
101 selectedReasonID = false,
102 redirectLink = '',
103 $anonymousFeedback = $modal.find( '.anonymous-feedback-label' ),
104 isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
105 otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
106 dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>,
107 deleteThemeUpdateData = <?php echo $fs->is_theme() && $fs->is_premium() && ! $fs->has_any_active_valid_license() ? 'true' : 'false' ?>,
108 $subscriptionCancellationModal = $( '.fs-modal-subscription-cancellation-<?php echo $fs->get_id() ?>' ),
109 showDeactivationFeedbackForm = <?php echo ( $show_deactivation_feedback_form ? 'true' : 'false' ) ?>,
110 $body = $( 'body' );
111
112 $modal.appendTo( $body );
113
114 if ( 0 !== $subscriptionCancellationModal.length ) {
115 $subscriptionCancellationModal.on( '<?php echo $fs->get_action_tag( 'subscription_cancellation_action' ) ?>', function( evt, cancelSubscription ) {
116 var shouldDeactivateModule = ( $modal.hasClass( 'no-confirmation-message' ) && ! showDeactivationFeedbackForm );
117
118 if ( false === cancelSubscription ) {
119 if ( ! shouldDeactivateModule ) {
120 showModal();
121 }
122
123 $subscriptionCancellationModal.trigger( 'closeModal' );
124
125 if ( shouldDeactivateModule ) {
126 deactivateModule();
127 }
128 } else {
129 var $errorMessage = $subscriptionCancellationModal.find( '.notice-error' );
130
131 <?php
132 $subscription_cancellation_context = $fs->is_paid_trial() ?
133 fs_text_inline( 'trial', 'trial', $slug ) :
134 fs_text_inline( 'subscription', 'subscription', $slug );
135 ?>
136
137 $.ajax({
138 url : ajaxurl,
139 method : 'POST',
140 data : {
141 action : '<?php echo $fs->get_ajax_action( 'cancel_subscription_or_trial' ) ?>',
142 security : '<?php echo $fs->get_ajax_security( 'cancel_subscription_or_trial' ) ?>',
143 module_id: '<?php echo $fs->get_id() ?>'
144 },
145 beforeSend: function() {
146 $errorMessage.hide();
147
148 $subscriptionCancellationModal.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
149 $subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).text( '<?php echo esc_js(
150 sprintf( fs_text_inline( 'Cancelling %s...', 'cancelling-x' , $slug ), $subscription_cancellation_context )
151 ) ?>' );
152 },
153 success: function( result ) {
154 if ( result.success ) {
155 $subscriptionCancellationModal.removeClass( 'has-subscription-actions' );
156 $subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).removeClass( 'warn' );
157
158 $subscriptionCancellationModal.remove();
159
160 if ( ! shouldDeactivateModule ) {
161 showModal();
162 } else {
163 deactivateModule();
164 }
165 } else {
166 $errorMessage.find( '> p' ).html( result.error );
167 $errorMessage.show();
168
169 $subscriptionCancellationModal.find( '.fs-modal-footer .button' ).removeClass( 'disabled' );
170 $subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).html( <?php echo json_encode( sprintf(
171 fs_text_inline( 'Cancel %s & Proceed', 'cancel-x-and-proceed', $slug ),
172 ucfirst( $subscription_cancellation_context )
173 ) ) ?> );
174 }
175 }
176 });
177 }
178 });
179 }
180
181 registerEventHandlers();
182
183 function registerEventHandlers() {
184 $body.on( 'click', '#the-list .deactivate > a', function ( evt ) {
185 if ( 0 === $( this ).next( '[data-module-id=<?php echo $fs->get_id() ?>].fs-module-id' ).length ) {
186 return true;
187 }
188
189 evt.preventDefault();
190
191 redirectLink = $(this).attr('href');
192
193 if ( 0 == $subscriptionCancellationModal.length ) {
194 showModal();
195 } else {
196 $subscriptionCancellationModal.trigger( 'showModal' );
197 }
198 });
199
200 <?php
201 if ( ! $fs->is_plugin() ) {
202 /**
203 * For "theme" module type, the modal is shown when the current user clicks on
204 * the "Activate" button of any other theme. The "Activate" button is actually
205 * a link to the "Themes" page (/wp-admin/themes.php) containing query params
206 * that tell WordPress to deactivate the current theme and activate a different theme.
207 *
208 * @author Leo Fajardo (@leorw)
209 * @since 1.2.2
210 *
211 * @since 1.2.2.7 Don't trigger the deactivation feedback form if activating the premium version of the theme.
212 */
213 ?>
214 $('body').on('click', '.theme-browser .theme:not([data-slug=<?php echo $fs->get_premium_slug() ?>]) .theme-actions .button.activate', function (evt) {
215 evt.preventDefault();
216
217 redirectLink = $(this).attr('href');
218
219 if ( 0 != $subscriptionCancellationModal.length ) {
220 $subscriptionCancellationModal.trigger( 'showModal' );
221 } else {
222 if ( $modal.hasClass( 'no-confirmation-message' ) && ! showDeactivationFeedbackForm ) {
223 deactivateModule();
224 } else {
225 showModal();
226 }
227 }
228 });
229 <?php
230 } ?>
231
232 $modal.on('input propertychange', '.reason-input input', function () {
233 if (!isOtherReasonSelected()) {
234 return;
235 }
236
237 var reason = $(this).val().trim();
238
239 /**
240 * If reason is not empty, remove the error-message class of the message container
241 * to change the message color back to default.
242 */
243 if (reason.length > 0) {
244 $('.message').removeClass('error-message');
245 enableDeactivateButton();
246 }
247 });
248
249 $modal.on('blur', '.reason-input input', function () {
250 var $userReason = $(this);
251
252 setTimeout(function () {
253 if (!isOtherReasonSelected()) {
254 return;
255 }
256
257 /**
258 * If reason is empty, add the error-message class to the message container
259 * to change the message color to red.
260 */
261 if (0 === $userReason.val().trim().length) {
262 $('.message').addClass('error-message');
263 disableDeactivateButton();
264 }
265 }, 150);
266 });
267
268 $modal.on('click', '.fs-modal-footer .button', function (evt) {
269 evt.preventDefault();
270
271 if ($(this).hasClass('disabled')) {
272 return;
273 }
274
275 var _parent = $(this).parents('.fs-modal:first');
276 var _this = $(this);
277
278 if (_this.hasClass('allow-deactivate')) {
279 var $radio = $modal.find('input[type="radio"]:checked');
280
281 if (0 === $radio.length) {
282 if ( ! deleteThemeUpdateData ) {
283 // If no selected reason, just deactivate the plugin.
284 window.location.href = redirectLink;
285 } else {
286 $.ajax({
287 url : ajaxurl,
288 method : 'POST',
289 data : {
290 action : '<?php echo $fs->get_ajax_action( 'delete_theme_update_data' ) ?>',
291 security : '<?php echo $fs->get_ajax_security( 'delete_theme_update_data' ) ?>',
292 module_id: '<?php echo $fs->get_id() ?>'
293 },
294 beforeSend: function() {
295 _parent.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
296 _parent.find( '.fs-modal-footer .button-secondary' ).text( 'Processing...' );
297 },
298 complete : function() {
299 window.location.href = redirectLink;
300 }
301 });
302 }
303
304 return;
305 }
306
307 var $selected_reason = $radio.parents('li:first'),
308 $input = $selected_reason.find('textarea, input[type="text"]'),
309 userReason = ( 0 !== $input.length ) ? $input.val().trim() : '';
310
311 if (isOtherReasonSelected() && ( '' === userReason )) {
312 return;
313 }
314
315 $.ajax({
316 url : ajaxurl,
317 method : 'POST',
318 data : {
319 action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
320 security : '<?php echo $fs->get_ajax_security( 'submit_uninstall_reason' ) ?>',
321 module_id : '<?php echo $fs->get_id() ?>',
322 reason_id : $radio.val(),
323 reason_info : userReason,
324 is_anonymous: isAnonymousFeedback()
325 },
326 beforeSend: function () {
327 _parent.find('.fs-modal-footer .button').addClass('disabled');
328 _parent.find('.fs-modal-footer .button-secondary').text('Processing...');
329 },
330 complete : function () {
331 // Do not show the dialog box, deactivate the plugin.
332 window.location.href = redirectLink;
333 }
334 });
335 } else if (_this.hasClass('button-deactivate')) {
336 // Change the Deactivate button's text and show the reasons panel.
337 _parent.find('.button-deactivate').addClass('allow-deactivate');
338
339 if ( showDeactivationFeedbackForm ) {
340 showPanel('reasons');
341 } else {
342 deactivateModule();
343 }
344 }
345 });
346
347 $modal.on('click', 'input[type="radio"]', function () {
348 var $selectedReasonOption = $( this );
349
350 // If the selection has not changed, do not proceed.
351 if (selectedReasonID === $selectedReasonOption.val())
352 return;
353
354 selectedReasonID = $selectedReasonOption.val();
355
356 if ( isAnonymous ) {
357 if ( isReasonSelected( dontShareDataReasonID ) ) {
358 $anonymousFeedback.hide();
359 } else {
360 $anonymousFeedback.show();
361 }
362 }
363
364 var _parent = $(this).parents('li:first');
365
366 $modal.find('.reason-input').remove();
367 $modal.find( '.internal-message' ).hide();
368 $modal.find('.button-deactivate').html('<?php echo esc_js( sprintf(
369 fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit' , $slug ),
370 $fs->is_plugin() ?
371 $deactivate_text :
372 sprintf( $activate_x_text, $theme_text )
373 ) ) ?>');
374
375 enableDeactivateButton();
376
377 if ( _parent.hasClass( 'has-internal-message' ) ) {
378 _parent.find( '.internal-message' ).show();
379 }
380
381 if (_parent.hasClass('has-input')) {
382 var inputType = _parent.data('input-type'),
383 inputPlaceholder = _parent.data('input-placeholder'),
384 reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" maxlength="128" />' : '<textarea rows="5" maxlength="128"></textarea>' ) + '</div>';
385
386 _parent.append($(reasonInputHtml));
387 _parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus();
388
389 if (isOtherReasonSelected()) {
390 showMessage('<?php echo esc_js( fs_text_inline( 'Kindly tell us the reason so we can improve.', 'ask-for-reason-message' , $slug ) ); ?>');
391 disableDeactivateButton();
392 }
393 }
394 });
395
396 // If the user has clicked outside the window, cancel it.
397 $modal.on('click', function (evt) {
398 var $target = $(evt.target);
399
400 // If the user has clicked anywhere in the modal dialog, just return.
401 if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) {
402 return;
403 }
404
405 // If the user has not clicked the close button and the clicked element is inside the modal dialog, just return.
406 if (
407 ! $target.hasClass( 'button-close' ) &&
408 ( $target.parents( '.fs-modal-body' ).length > 0 || $target.parents( '.fs-modal-footer' ).length > 0 )
409 ) {
410 return;
411 }
412
413 closeModal();
414
415 return false;
416 });
417 }
418
419 function isAnonymousFeedback() {
420 if ( ! isAnonymous ) {
421 return false;
422 }
423
424 return ( isReasonSelected( dontShareDataReasonID ) || $anonymousFeedback.find( 'input' ).prop( 'checked' ) );
425 }
426
427 function isReasonSelected( reasonID ) {
428 // Get the selected radio input element.
429 var $selectedReasonOption = $modal.find('input[type="radio"]:checked');
430
431 return ( reasonID == $selectedReasonOption.val() );
432 }
433
434 function isOtherReasonSelected() {
435 return isReasonSelected( otherReasonID );
436 }
437
438 function showModal() {
439 resetModal();
440
441 // Display the dialog box.
442 $modal.addClass('active');
443
444 $('body').addClass('has-fs-modal');
445 }
446
447 function closeModal() {
448 $modal.removeClass('active');
449
450 $('body').removeClass('has-fs-modal');
451 }
452
453 function resetModal() {
454 selectedReasonID = false;
455
456 enableDeactivateButton();
457
458 // Uncheck all radio buttons.
459 $modal.find('input[type="radio"]').prop('checked', false);
460
461 // Remove all input fields ( textfield, textarea ).
462 $modal.find('.reason-input').remove();
463
464 $modal.find('.message').hide();
465
466 if ( isAnonymous ) {
467 $anonymousFeedback.find( 'input' ).prop( 'checked', false );
468
469 // Hide, since by default there is no selected reason.
470 $anonymousFeedback.hide();
471 }
472
473 var $deactivateButton = $modal.find('.button-deactivate');
474
475 /*
476 * If the modal dialog has no confirmation message, that is, it has only one panel, then ensure
477 * that clicking the deactivate button will actually deactivate the plugin.
478 */
479 if ( $modal.hasClass( 'no-confirmation-message' ) ) {
480 $deactivateButton.addClass( 'allow-deactivate' );
481
482 showPanel( 'reasons' );
483 } else {
484 $deactivateButton.removeClass( 'allow-deactivate' );
485
486 showPanel( 'confirm' );
487 }
488 }
489
490 function showMessage(message) {
491 $modal.find('.message').text(message).show();
492 }
493
494 function enableDeactivateButton() {
495 $modal.find('.button-deactivate').removeClass('disabled');
496 }
497
498 function disableDeactivateButton() {
499 $modal.find('.button-deactivate').addClass('disabled');
500 }
501
502 function showPanel(panelType) {
503 $modal.find( '.fs-modal-panel' ).removeClass( 'active' );
504 $modal.find( '[data-panel-id="' + panelType + '"]' ).addClass( 'active' );
505
506 updateButtonLabels();
507 }
508
509 function updateButtonLabels() {
510 var $deactivateButton = $modal.find( '.button-deactivate' );
511
512 // Reset the deactivate button's text.
513 if ( 'confirm' === getCurrentPanel() ) {
514 $deactivateButton.text( <?php echo json_encode( sprintf(
515 fs_text_inline( 'Yes - %s', 'deactivation-modal-button-confirm', $slug ),
516 $fs->is_plugin() ?
517 $deactivate_text :
518 sprintf( $activate_x_text, $theme_text )
519 ) ) ?> );
520 } else {
521 $deactivateButton.html( <?php echo json_encode( sprintf(
522 fs_text_inline('Skip & %s', 'skip-and-x', $slug ),
523 $fs->is_plugin() ?
524 $deactivate_text :
525 sprintf( $activate_x_text, $theme_text )
526 ) ) ?> );
527 }
528 }
529
530 function getCurrentPanel() {
531 return $modal.find('.fs-modal-panel.active').attr('data-panel-id');
532 }
533
534 /**
535 * @author Leo Fajardo (@leorw)
536 *
537 * @since 2.3.0
538 */
539 function deactivateModule() {
540 window.location.href = redirectLink;
541 }
542 })(jQuery);
543 </script>
544