PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.0
Code Manager v1.0.0
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
540 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 $deactivateLink = $('#the-list .deactivate > [data-module-id=<?php echo $fs->get_id() ?>].fs-module-id').prev(),
102 selectedReasonID = false,
103 redirectLink = '',
104 $anonymousFeedback = $modal.find( '.anonymous-feedback-label' ),
105 isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
106 otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
107 dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>,
108 deleteThemeUpdateData = <?php echo $fs->is_theme() && $fs->is_premium() && ! $fs->has_any_active_valid_license() ? 'true' : 'false' ?>,
109 $subscriptionCancellationModal = $( '.fs-modal-subscription-cancellation-<?php echo $fs->get_id() ?>' ),
110 showDeactivationFeedbackForm = <?php echo ( $show_deactivation_feedback_form ? 'true' : 'false' ) ?>;
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 $deactivateLink.click(function (evt) {
185 evt.preventDefault();
186
187 redirectLink = $(this).attr('href');
188
189 if ( 0 == $subscriptionCancellationModal.length ) {
190 showModal();
191 } else {
192 $subscriptionCancellationModal.trigger( 'showModal' );
193 }
194 });
195
196 <?php
197 if ( ! $fs->is_plugin() ) {
198 /**
199 * For "theme" module type, the modal is shown when the current user clicks on
200 * the "Activate" button of any other theme. The "Activate" button is actually
201 * a link to the "Themes" page (/wp-admin/themes.php) containing query params
202 * that tell WordPress to deactivate the current theme and activate a different theme.
203 *
204 * @author Leo Fajardo (@leorw)
205 * @since 1.2.2
206 *
207 * @since 1.2.2.7 Don't trigger the deactivation feedback form if activating the premium version of the theme.
208 */
209 ?>
210 $('body').on('click', '.theme-browser .theme:not([data-slug=<?php echo $fs->get_premium_slug() ?>]) .theme-actions .button.activate', function (evt) {
211 evt.preventDefault();
212
213 redirectLink = $(this).attr('href');
214
215 if ( 0 != $subscriptionCancellationModal.length ) {
216 $subscriptionCancellationModal.trigger( 'showModal' );
217 } else {
218 if ( $modal.hasClass( 'no-confirmation-message' ) && ! showDeactivationFeedbackForm ) {
219 deactivateModule();
220 } else {
221 showModal();
222 }
223 }
224 });
225 <?php
226 } ?>
227
228 $modal.on('input propertychange', '.reason-input input', function () {
229 if (!isOtherReasonSelected()) {
230 return;
231 }
232
233 var reason = $(this).val().trim();
234
235 /**
236 * If reason is not empty, remove the error-message class of the message container
237 * to change the message color back to default.
238 */
239 if (reason.length > 0) {
240 $('.message').removeClass('error-message');
241 enableDeactivateButton();
242 }
243 });
244
245 $modal.on('blur', '.reason-input input', function () {
246 var $userReason = $(this);
247
248 setTimeout(function () {
249 if (!isOtherReasonSelected()) {
250 return;
251 }
252
253 /**
254 * If reason is empty, add the error-message class to the message container
255 * to change the message color to red.
256 */
257 if (0 === $userReason.val().trim().length) {
258 $('.message').addClass('error-message');
259 disableDeactivateButton();
260 }
261 }, 150);
262 });
263
264 $modal.on('click', '.fs-modal-footer .button', function (evt) {
265 evt.preventDefault();
266
267 if ($(this).hasClass('disabled')) {
268 return;
269 }
270
271 var _parent = $(this).parents('.fs-modal:first');
272 var _this = $(this);
273
274 if (_this.hasClass('allow-deactivate')) {
275 var $radio = $modal.find('input[type="radio"]:checked');
276
277 if (0 === $radio.length) {
278 if ( ! deleteThemeUpdateData ) {
279 // If no selected reason, just deactivate the plugin.
280 window.location.href = redirectLink;
281 } else {
282 $.ajax({
283 url : ajaxurl,
284 method : 'POST',
285 data : {
286 action : '<?php echo $fs->get_ajax_action( 'delete_theme_update_data' ) ?>',
287 security : '<?php echo $fs->get_ajax_security( 'delete_theme_update_data' ) ?>',
288 module_id: '<?php echo $fs->get_id() ?>'
289 },
290 beforeSend: function() {
291 _parent.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
292 _parent.find( '.fs-modal-footer .button-secondary' ).text( 'Processing...' );
293 },
294 complete : function() {
295 window.location.href = redirectLink;
296 }
297 });
298 }
299
300 return;
301 }
302
303 var $selected_reason = $radio.parents('li:first'),
304 $input = $selected_reason.find('textarea, input[type="text"]'),
305 userReason = ( 0 !== $input.length ) ? $input.val().trim() : '';
306
307 if (isOtherReasonSelected() && ( '' === userReason )) {
308 return;
309 }
310
311 $.ajax({
312 url : ajaxurl,
313 method : 'POST',
314 data : {
315 action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
316 security : '<?php echo $fs->get_ajax_security( 'submit_uninstall_reason' ) ?>',
317 module_id : '<?php echo $fs->get_id() ?>',
318 reason_id : $radio.val(),
319 reason_info : userReason,
320 is_anonymous: isAnonymousFeedback()
321 },
322 beforeSend: function () {
323 _parent.find('.fs-modal-footer .button').addClass('disabled');
324 _parent.find('.fs-modal-footer .button-secondary').text('Processing...');
325 },
326 complete : function () {
327 // Do not show the dialog box, deactivate the plugin.
328 window.location.href = redirectLink;
329 }
330 });
331 } else if (_this.hasClass('button-deactivate')) {
332 // Change the Deactivate button's text and show the reasons panel.
333 _parent.find('.button-deactivate').addClass('allow-deactivate');
334
335 if ( showDeactivationFeedbackForm ) {
336 showPanel('reasons');
337 } else {
338 deactivateModule();
339 }
340 }
341 });
342
343 $modal.on('click', 'input[type="radio"]', function () {
344 var $selectedReasonOption = $( this );
345
346 // If the selection has not changed, do not proceed.
347 if (selectedReasonID === $selectedReasonOption.val())
348 return;
349
350 selectedReasonID = $selectedReasonOption.val();
351
352 if ( isAnonymous ) {
353 if ( isReasonSelected( dontShareDataReasonID ) ) {
354 $anonymousFeedback.hide();
355 } else {
356 $anonymousFeedback.show();
357 }
358 }
359
360 var _parent = $(this).parents('li:first');
361
362 $modal.find('.reason-input').remove();
363 $modal.find( '.internal-message' ).hide();
364 $modal.find('.button-deactivate').html('<?php echo esc_js( sprintf(
365 fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit' , $slug ),
366 $fs->is_plugin() ?
367 $deactivate_text :
368 sprintf( $activate_x_text, $theme_text )
369 ) ) ?>');
370
371 enableDeactivateButton();
372
373 if ( _parent.hasClass( 'has-internal-message' ) ) {
374 _parent.find( '.internal-message' ).show();
375 }
376
377 if (_parent.hasClass('has-input')) {
378 var inputType = _parent.data('input-type'),
379 inputPlaceholder = _parent.data('input-placeholder'),
380 reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" maxlength="128" />' : '<textarea rows="5" maxlength="128"></textarea>' ) + '</div>';
381
382 _parent.append($(reasonInputHtml));
383 _parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus();
384
385 if (isOtherReasonSelected()) {
386 showMessage('<?php echo esc_js( fs_text_inline( 'Kindly tell us the reason so we can improve.', 'ask-for-reason-message' , $slug ) ); ?>');
387 disableDeactivateButton();
388 }
389 }
390 });
391
392 // If the user has clicked outside the window, cancel it.
393 $modal.on('click', function (evt) {
394 var $target = $(evt.target);
395
396 // If the user has clicked anywhere in the modal dialog, just return.
397 if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) {
398 return;
399 }
400
401 // If the user has not clicked the close button and the clicked element is inside the modal dialog, just return.
402 if (
403 ! $target.hasClass( 'button-close' ) &&
404 ( $target.parents( '.fs-modal-body' ).length > 0 || $target.parents( '.fs-modal-footer' ).length > 0 )
405 ) {
406 return;
407 }
408
409 closeModal();
410
411 return false;
412 });
413 }
414
415 function isAnonymousFeedback() {
416 if ( ! isAnonymous ) {
417 return false;
418 }
419
420 return ( isReasonSelected( dontShareDataReasonID ) || $anonymousFeedback.find( 'input' ).prop( 'checked' ) );
421 }
422
423 function isReasonSelected( reasonID ) {
424 // Get the selected radio input element.
425 var $selectedReasonOption = $modal.find('input[type="radio"]:checked');
426
427 return ( reasonID == $selectedReasonOption.val() );
428 }
429
430 function isOtherReasonSelected() {
431 return isReasonSelected( otherReasonID );
432 }
433
434 function showModal() {
435 resetModal();
436
437 // Display the dialog box.
438 $modal.addClass('active');
439
440 $('body').addClass('has-fs-modal');
441 }
442
443 function closeModal() {
444 $modal.removeClass('active');
445
446 $('body').removeClass('has-fs-modal');
447 }
448
449 function resetModal() {
450 selectedReasonID = false;
451
452 enableDeactivateButton();
453
454 // Uncheck all radio buttons.
455 $modal.find('input[type="radio"]').prop('checked', false);
456
457 // Remove all input fields ( textfield, textarea ).
458 $modal.find('.reason-input').remove();
459
460 $modal.find('.message').hide();
461
462 if ( isAnonymous ) {
463 $anonymousFeedback.find( 'input' ).prop( 'checked', false );
464
465 // Hide, since by default there is no selected reason.
466 $anonymousFeedback.hide();
467 }
468
469 var $deactivateButton = $modal.find('.button-deactivate');
470
471 /*
472 * If the modal dialog has no confirmation message, that is, it has only one panel, then ensure
473 * that clicking the deactivate button will actually deactivate the plugin.
474 */
475 if ( $modal.hasClass( 'no-confirmation-message' ) ) {
476 $deactivateButton.addClass( 'allow-deactivate' );
477
478 showPanel( 'reasons' );
479 } else {
480 $deactivateButton.removeClass( 'allow-deactivate' );
481
482 showPanel( 'confirm' );
483 }
484 }
485
486 function showMessage(message) {
487 $modal.find('.message').text(message).show();
488 }
489
490 function enableDeactivateButton() {
491 $modal.find('.button-deactivate').removeClass('disabled');
492 }
493
494 function disableDeactivateButton() {
495 $modal.find('.button-deactivate').addClass('disabled');
496 }
497
498 function showPanel(panelType) {
499 $modal.find( '.fs-modal-panel' ).removeClass( 'active' );
500 $modal.find( '[data-panel-id="' + panelType + '"]' ).addClass( 'active' );
501
502 updateButtonLabels();
503 }
504
505 function updateButtonLabels() {
506 var $deactivateButton = $modal.find( '.button-deactivate' );
507
508 // Reset the deactivate button's text.
509 if ( 'confirm' === getCurrentPanel() ) {
510 $deactivateButton.text( <?php echo json_encode( sprintf(
511 fs_text_inline( 'Yes - %s', 'deactivation-modal-button-confirm', $slug ),
512 $fs->is_plugin() ?
513 $deactivate_text :
514 sprintf( $activate_x_text, $theme_text )
515 ) ) ?> );
516 } else {
517 $deactivateButton.html( <?php echo json_encode( sprintf(
518 fs_text_inline('Skip & %s', 'skip-and-x', $slug ),
519 $fs->is_plugin() ?
520 $deactivate_text :
521 sprintf( $activate_x_text, $theme_text )
522 ) ) ?> );
523 }
524 }
525
526 function getCurrentPanel() {
527 return $modal.find('.fs-modal-panel.active').attr('data-panel-id');
528 }
529
530 /**
531 * @author Leo Fajardo (@leorw)
532 *
533 * @since 2.3.0
534 */
535 function deactivateModule() {
536 window.location.href = redirectLink;
537 }
538 })(jQuery);
539 </script>
540