Version Description
- Fixed: Removed preload & prefetch since they're causing problems in Safari and Firefox. Let's leave this to the optimization plugins.
- Fixed: Security fix
- Change: Removed small Premium notices from the editor
Download this release
Release Info
Developer | bfintal |
Plugin | Stackable – Page Builder Gutenberg Blocks |
Version | 1.13.3 |
Comparing to | |
See all releases |
Code changes from version 1.13.2 to 1.13.3
- freemius/includes/class-freemius.php +22 -1
- freemius/start.php +1 -1
- freemius/templates/debug.php +2 -0
- freemius/templates/forms/deactivation/form.php +497 -497
- plugin.php +2 -2
- readme.txt +6 -1
- src/init.php +1 -46
- src/pro.php +6 -32
- src/welcome/notification-rate.php +6 -6
freemius/includes/class-freemius.php
CHANGED
@@ -2977,6 +2977,10 @@
|
|
2977 |
* @since 1.1.7.3
|
2978 |
*/
|
2979 |
static function _toggle_debug_mode() {
|
|
|
|
|
|
|
|
|
2980 |
$is_on = fs_request_get( 'is_on', false, 'post' );
|
2981 |
|
2982 |
if ( fs_request_is_post() && in_array( $is_on, array( 0, 1 ) ) ) {
|
@@ -3008,8 +3012,16 @@
|
|
3008 |
* @since 1.2.1.7
|
3009 |
*/
|
3010 |
static function _get_db_option() {
|
|
|
|
|
3011 |
$option_name = fs_request_get( 'option_name' );
|
3012 |
|
|
|
|
|
|
|
|
|
|
|
|
|
3013 |
$value = get_option( $option_name );
|
3014 |
|
3015 |
$result = array(
|
@@ -3032,7 +3044,16 @@
|
|
3032 |
* @since 1.2.1.7
|
3033 |
*/
|
3034 |
static function _set_db_option() {
|
3035 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3036 |
$option_value = fs_request_get( 'option_value' );
|
3037 |
|
3038 |
if ( ! empty( $option_value ) ) {
|
2977 |
* @since 1.1.7.3
|
2978 |
*/
|
2979 |
static function _toggle_debug_mode() {
|
2980 |
+
if ( ! is_super_admin() ) {
|
2981 |
+
return;
|
2982 |
+
}
|
2983 |
+
|
2984 |
$is_on = fs_request_get( 'is_on', false, 'post' );
|
2985 |
|
2986 |
if ( fs_request_is_post() && in_array( $is_on, array( 0, 1 ) ) ) {
|
3012 |
* @since 1.2.1.7
|
3013 |
*/
|
3014 |
static function _get_db_option() {
|
3015 |
+
check_admin_referer( 'fs_get_db_option' );
|
3016 |
+
|
3017 |
$option_name = fs_request_get( 'option_name' );
|
3018 |
|
3019 |
+
if ( ! is_super_admin() ||
|
3020 |
+
! fs_starts_with( $option_name, 'fs_' )
|
3021 |
+
) {
|
3022 |
+
self::shoot_ajax_failure();
|
3023 |
+
}
|
3024 |
+
|
3025 |
$value = get_option( $option_name );
|
3026 |
|
3027 |
$result = array(
|
3044 |
* @since 1.2.1.7
|
3045 |
*/
|
3046 |
static function _set_db_option() {
|
3047 |
+
check_admin_referer( 'fs_set_db_option' );
|
3048 |
+
|
3049 |
+
$option_name = fs_request_get( 'option_name' );
|
3050 |
+
|
3051 |
+
if ( ! is_super_admin() ||
|
3052 |
+
! fs_starts_with( $option_name, 'fs_' )
|
3053 |
+
) {
|
3054 |
+
self::shoot_ajax_failure();
|
3055 |
+
}
|
3056 |
+
|
3057 |
$option_value = fs_request_get( 'option_value' );
|
3058 |
|
3059 |
if ( ! empty( $option_value ) ) {
|
freemius/start.php
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
*
|
16 |
* @var string
|
17 |
*/
|
18 |
-
$this_sdk_version = '2.2.
|
19 |
|
20 |
#region SDK Selection Logic --------------------------------------------------------------------
|
21 |
|
15 |
*
|
16 |
* @var string
|
17 |
*/
|
18 |
+
$this_sdk_version = '2.2.4';
|
19 |
|
20 |
#region SDK Selection Logic --------------------------------------------------------------------
|
21 |
|
freemius/templates/debug.php
CHANGED
@@ -113,6 +113,7 @@
|
|
113 |
if (optionName) {
|
114 |
$.post(ajaxurl, {
|
115 |
action : 'fs_get_db_option',
|
|
|
116 |
option_name: optionName
|
117 |
}, function (response) {
|
118 |
if (response.data.value)
|
@@ -132,6 +133,7 @@
|
|
132 |
if (optionValue) {
|
133 |
$.post(ajaxurl, {
|
134 |
action : 'fs_set_db_option',
|
|
|
135 |
option_name : optionName,
|
136 |
option_value: optionValue
|
137 |
}, function () {
|
113 |
if (optionName) {
|
114 |
$.post(ajaxurl, {
|
115 |
action : 'fs_get_db_option',
|
116 |
+
_wpnonce : '<?php echo wp_create_nonce( 'fs_get_db_option' ) ?>',
|
117 |
option_name: optionName
|
118 |
}, function (response) {
|
119 |
if (response.data.value)
|
133 |
if (optionValue) {
|
134 |
$.post(ajaxurl, {
|
135 |
action : 'fs_set_db_option',
|
136 |
+
_wpnonce : '<?php echo wp_create_nonce( 'fs_set_db_option' ) ?>',
|
137 |
option_name : optionName,
|
138 |
option_value: optionValue
|
139 |
}, function () {
|
freemius/templates/forms/deactivation/form.php
CHANGED
@@ -1,497 +1,497 @@
|
|
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 |
-
$confirmation_message = $fs->apply_filters( 'uninstall_confirmation_message', '' );
|
20 |
-
|
21 |
-
$reasons = $VARS['reasons'];
|
22 |
-
|
23 |
-
$reasons_list_items_html = '';
|
24 |
-
|
25 |
-
foreach ( $reasons as $reason ) {
|
26 |
-
$list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' );
|
27 |
-
|
28 |
-
if ( isset( $reason['internal_message'] ) && ! empty( $reason['internal_message'] ) ) {
|
29 |
-
$list_item_classes .= ' has-internal-message';
|
30 |
-
$reason_internal_message = $reason['internal_message'];
|
31 |
-
} else {
|
32 |
-
$reason_internal_message = '';
|
33 |
-
}
|
34 |
-
|
35 |
-
$reason_input_type = ( ! empty( $reason['input_type'] ) ? $reason['input_type'] : '' );
|
36 |
-
$reason_input_placeholder = ( ! empty( $reason['input_placeholder'] ) ? $reason['input_placeholder'] : '' );
|
37 |
-
|
38 |
-
$reason_list_item_html = <<< HTML
|
39 |
-
<li class="{$list_item_classes}"
|
40 |
-
data-input-type="{$reason_input_type}"
|
41 |
-
data-input-placeholder="{$reason_input_placeholder}">
|
42 |
-
<label>
|
43 |
-
<span>
|
44 |
-
<input type="radio" name="selected-reason" value="{$reason['id']}"/>
|
45 |
-
</span>
|
46 |
-
<span>{$reason['text']}</span>
|
47 |
-
</label>
|
48 |
-
<div class="internal-message">{$reason_internal_message}</div>
|
49 |
-
</li>
|
50 |
-
HTML;
|
51 |
-
|
52 |
-
$reasons_list_items_html .= $reason_list_item_html;
|
53 |
-
}
|
54 |
-
|
55 |
-
$is_anonymous = ( ! $fs->is_registered() );
|
56 |
-
if ( $is_anonymous ) {
|
57 |
-
$anonymous_feedback_checkbox_html = sprintf(
|
58 |
-
'<label class="anonymous-feedback-label"><input type="checkbox" class="anonymous-feedback-checkbox"> %s</label>',
|
59 |
-
fs_esc_html_inline( 'Anonymous feedback', 'anonymous-feedback', $slug )
|
60 |
-
);
|
61 |
-
} else {
|
62 |
-
$anonymous_feedback_checkbox_html = '';
|
63 |
-
}
|
64 |
-
|
65 |
-
// Aliases.
|
66 |
-
$deactivate_text = fs_text_inline( 'Deactivate', 'deactivate', $slug );
|
67 |
-
$theme_text = fs_text_inline( 'Theme', 'theme', $slug );
|
68 |
-
$activate_x_text = fs_text_inline( 'Activate %s', 'activate-x', $slug );
|
69 |
-
|
70 |
-
fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
|
71 |
-
?>
|
72 |
-
<?php $fs->_maybe_add_subscription_cancellation_dialog_box() ?>
|
73 |
-
<script type="text/javascript">
|
74 |
-
(function ($) {
|
75 |
-
var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ) ?>,
|
76 |
-
modalHtml =
|
77 |
-
'<div class="fs-modal fs-modal-deactivation-feedback<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">'
|
78 |
-
+ ' <div class="fs-modal-dialog">'
|
79 |
-
+ ' <div class="fs-modal-header">'
|
80 |
-
+ ' <h4><?php fs_esc_attr_echo_inline( 'Quick Feedback', 'quick-feedback' , $slug ) ?></h4>'
|
81 |
-
+ ' </div>'
|
82 |
-
+ ' <div class="fs-modal-body">'
|
83 |
-
+ ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>'
|
84 |
-
+ ' <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>'
|
85 |
-
+ ' </div>'
|
86 |
-
+ ' <div class="fs-modal-footer">'
|
87 |
-
+ ' <?php echo $anonymous_feedback_checkbox_html ?>'
|
88 |
-
+ ' <a href="#" class="button button-secondary button-deactivate"></a>'
|
89 |
-
+ ' <a href="#" class="button button-primary button-close"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel', $slug ) ?></a>'
|
90 |
-
+ ' </div>'
|
91 |
-
+ ' </div>'
|
92 |
-
+ '</div>',
|
93 |
-
$modal = $(modalHtml),
|
94 |
-
$deactivateLink = $('#the-list .deactivate > [data-module-id=<?php echo $fs->get_id() ?>].fs-module-id').prev(),
|
95 |
-
selectedReasonID = false,
|
96 |
-
redirectLink = '',
|
97 |
-
$anonymousFeedback = $modal.find( '.anonymous-feedback-label' ),
|
98 |
-
isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
|
99 |
-
otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
|
100 |
-
dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>,
|
101 |
-
deleteThemeUpdateData = <?php echo $fs->is_theme() && $fs->is_premium() && ! $fs->has_any_active_valid_license() ? 'true' : 'false' ?>,
|
102 |
-
$subscriptionCancellationModal = $( '.fs-modal-subscription-cancellation-<?php echo $fs->get_id() ?>' );
|
103 |
-
|
104 |
-
$modal.appendTo($('body'));
|
105 |
-
|
106 |
-
if ( 0 !== $subscriptionCancellationModal.length ) {
|
107 |
-
$subscriptionCancellationModal.on( '<?php echo $fs->get_action_tag( 'subscription_cancellation_action' ) ?>', function( evt, cancelSubscription ) {
|
108 |
-
if ( false === cancelSubscription ) {
|
109 |
-
showModal();
|
110 |
-
|
111 |
-
$subscriptionCancellationModal.trigger( 'closeModal' );
|
112 |
-
} else {
|
113 |
-
var $errorMessage = $subscriptionCancellationModal.find( '.notice-error' );
|
114 |
-
|
115 |
-
<?php
|
116 |
-
$subscription_cancellation_context = $fs->is_paid_trial() ?
|
117 |
-
fs_text_inline( 'trial', 'trial', $slug ) :
|
118 |
-
fs_text_inline( 'subscription', 'subscription', $slug );
|
119 |
-
?>
|
120 |
-
|
121 |
-
$.ajax({
|
122 |
-
url : ajaxurl,
|
123 |
-
method : 'POST',
|
124 |
-
data : {
|
125 |
-
action : '<?php echo $fs->get_ajax_action( 'cancel_subscription_or_trial' ) ?>',
|
126 |
-
security : '<?php echo $fs->get_ajax_security( 'cancel_subscription_or_trial' ) ?>',
|
127 |
-
module_id: '<?php echo $fs->get_id() ?>'
|
128 |
-
},
|
129 |
-
beforeSend: function() {
|
130 |
-
$errorMessage.hide();
|
131 |
-
|
132 |
-
$subscriptionCancellationModal.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
|
133 |
-
$subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).text( '<?php echo esc_js(
|
134 |
-
sprintf( fs_text_inline( 'Cancelling %s...', 'cancelling-x' , $slug ), $subscription_cancellation_context )
|
135 |
-
) ?>' );
|
136 |
-
},
|
137 |
-
success: function( result ) {
|
138 |
-
if ( result.success ) {
|
139 |
-
$subscriptionCancellationModal.removeClass( 'has-subscription-actions' );
|
140 |
-
$subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).removeClass( 'warn' );
|
141 |
-
|
142 |
-
$subscriptionCancellationModal.remove();
|
143 |
-
showModal();
|
144 |
-
} else {
|
145 |
-
$errorMessage.find( '> p' ).html( result.error );
|
146 |
-
$errorMessage.show();
|
147 |
-
|
148 |
-
$subscriptionCancellationModal.find( '.fs-modal-footer .button' ).removeClass( 'disabled' );
|
149 |
-
$subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).html( <?php echo json_encode( sprintf(
|
150 |
-
fs_text_inline( 'Cancel %s & Proceed', 'cancel-x-and-proceed', $slug ),
|
151 |
-
ucfirst( $subscription_cancellation_context )
|
152 |
-
) ) ?> );
|
153 |
-
}
|
154 |
-
}
|
155 |
-
});
|
156 |
-
}
|
157 |
-
});
|
158 |
-
}
|
159 |
-
|
160 |
-
registerEventHandlers();
|
161 |
-
|
162 |
-
function registerEventHandlers() {
|
163 |
-
$deactivateLink.click(function (evt) {
|
164 |
-
evt.preventDefault();
|
165 |
-
|
166 |
-
redirectLink = $(this).attr('href');
|
167 |
-
|
168 |
-
if ( 0 == $subscriptionCancellationModal.length ) {
|
169 |
-
showModal();
|
170 |
-
} else {
|
171 |
-
$subscriptionCancellationModal.trigger( 'showModal' );
|
172 |
-
}
|
173 |
-
});
|
174 |
-
|
175 |
-
<?php
|
176 |
-
if ( ! $fs->is_plugin() ) {
|
177 |
-
/**
|
178 |
-
* For "theme" module type, the modal is shown when the current user clicks on
|
179 |
-
* the "Activate" button of any other theme. The "Activate" button is actually
|
180 |
-
* a link to the "Themes" page (/wp-admin/themes.php) containing query params
|
181 |
-
* that tell WordPress to deactivate the current theme and activate a different theme.
|
182 |
-
*
|
183 |
-
* @author Leo Fajardo (@leorw)
|
184 |
-
* @since 1.2.2
|
185 |
-
*
|
186 |
-
* @since 1.2.2.7 Don't trigger the deactivation feedback form if activating the premium version of the theme.
|
187 |
-
*/
|
188 |
-
?>
|
189 |
-
$('body').on('click', '.theme-browser .theme:not([data-slug=<?php echo $fs->get_premium_slug() ?>]) .theme-actions .button.activate', function (evt) {
|
190 |
-
evt.preventDefault();
|
191 |
-
|
192 |
-
redirectLink = $(this).attr('href');
|
193 |
-
|
194 |
-
showModal();
|
195 |
-
});
|
196 |
-
<?php
|
197 |
-
} ?>
|
198 |
-
|
199 |
-
$modal.on('input propertychange', '.reason-input input', function () {
|
200 |
-
if (!isOtherReasonSelected()) {
|
201 |
-
return;
|
202 |
-
}
|
203 |
-
|
204 |
-
var reason = $(this).val().trim();
|
205 |
-
|
206 |
-
/**
|
207 |
-
* If reason is not empty, remove the error-message class of the message container
|
208 |
-
* to change the message color back to default.
|
209 |
-
*/
|
210 |
-
if (reason.length > 0) {
|
211 |
-
$('.message').removeClass('error-message');
|
212 |
-
enableDeactivateButton();
|
213 |
-
}
|
214 |
-
});
|
215 |
-
|
216 |
-
$modal.on('blur', '.reason-input input', function () {
|
217 |
-
var $userReason = $(this);
|
218 |
-
|
219 |
-
setTimeout(function () {
|
220 |
-
if (!isOtherReasonSelected()) {
|
221 |
-
return;
|
222 |
-
}
|
223 |
-
|
224 |
-
/**
|
225 |
-
* If reason is empty, add the error-message class to the message container
|
226 |
-
* to change the message color to red.
|
227 |
-
*/
|
228 |
-
if (0 === $userReason.val().trim().length) {
|
229 |
-
$('.message').addClass('error-message');
|
230 |
-
disableDeactivateButton();
|
231 |
-
}
|
232 |
-
}, 150);
|
233 |
-
});
|
234 |
-
|
235 |
-
$modal.on('click', '.fs-modal-footer .button', function (evt) {
|
236 |
-
evt.preventDefault();
|
237 |
-
|
238 |
-
if ($(this).hasClass('disabled')) {
|
239 |
-
return;
|
240 |
-
}
|
241 |
-
|
242 |
-
var _parent = $(this).parents('.fs-modal:first');
|
243 |
-
var _this = $(this);
|
244 |
-
|
245 |
-
if (_this.hasClass('allow-deactivate')) {
|
246 |
-
var $radio = $('input[type="radio"]:checked');
|
247 |
-
|
248 |
-
if (0 === $radio.length) {
|
249 |
-
if ( ! deleteThemeUpdateData ) {
|
250 |
-
// If no selected reason, just deactivate the plugin.
|
251 |
-
window.location.href = redirectLink;
|
252 |
-
} else {
|
253 |
-
$.ajax({
|
254 |
-
url : ajaxurl,
|
255 |
-
method : 'POST',
|
256 |
-
data : {
|
257 |
-
action : '<?php echo $fs->get_ajax_action( 'delete_theme_update_data' ) ?>',
|
258 |
-
security : '<?php echo $fs->get_ajax_security( 'delete_theme_update_data' ) ?>',
|
259 |
-
module_id: '<?php echo $fs->get_id() ?>'
|
260 |
-
},
|
261 |
-
beforeSend: function() {
|
262 |
-
_parent.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
|
263 |
-
_parent.find( '.fs-modal-footer .button-secondary' ).text( 'Processing...' );
|
264 |
-
},
|
265 |
-
complete : function() {
|
266 |
-
window.location.href = redirectLink;
|
267 |
-
}
|
268 |
-
});
|
269 |
-
}
|
270 |
-
|
271 |
-
return;
|
272 |
-
}
|
273 |
-
|
274 |
-
var $selected_reason = $radio.parents('li:first'),
|
275 |
-
$input = $selected_reason.find('textarea, input[type="text"]'),
|
276 |
-
userReason = ( 0 !== $input.length ) ? $input.val().trim() : '';
|
277 |
-
|
278 |
-
if (isOtherReasonSelected() && ( '' === userReason )) {
|
279 |
-
return;
|
280 |
-
}
|
281 |
-
|
282 |
-
$.ajax({
|
283 |
-
url : ajaxurl,
|
284 |
-
method : 'POST',
|
285 |
-
data : {
|
286 |
-
action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
|
287 |
-
security : '<?php echo $fs->get_ajax_security( 'submit_uninstall_reason' ) ?>',
|
288 |
-
module_id : '<?php echo $fs->get_id() ?>',
|
289 |
-
reason_id : $radio.val(),
|
290 |
-
reason_info : userReason,
|
291 |
-
is_anonymous: isAnonymousFeedback()
|
292 |
-
},
|
293 |
-
beforeSend: function () {
|
294 |
-
_parent.find('.fs-modal-footer .button').addClass('disabled');
|
295 |
-
_parent.find('.fs-modal-footer .button-secondary').text('Processing...');
|
296 |
-
},
|
297 |
-
complete : function () {
|
298 |
-
// Do not show the dialog box, deactivate the plugin.
|
299 |
-
window.location.href = redirectLink;
|
300 |
-
}
|
301 |
-
});
|
302 |
-
} else if (_this.hasClass('button-deactivate')) {
|
303 |
-
// Change the Deactivate button's text and show the reasons panel.
|
304 |
-
_parent.find('.button-deactivate').addClass('allow-deactivate');
|
305 |
-
|
306 |
-
showPanel('reasons');
|
307 |
-
}
|
308 |
-
});
|
309 |
-
|
310 |
-
$modal.on('click', 'input[type="radio"]', function () {
|
311 |
-
var $selectedReasonOption = $( this );
|
312 |
-
|
313 |
-
// If the selection has not changed, do not proceed.
|
314 |
-
if (selectedReasonID === $selectedReasonOption.val())
|
315 |
-
return;
|
316 |
-
|
317 |
-
selectedReasonID = $selectedReasonOption.val();
|
318 |
-
|
319 |
-
if ( isAnonymous ) {
|
320 |
-
if ( isReasonSelected( dontShareDataReasonID ) ) {
|
321 |
-
$anonymousFeedback.hide();
|
322 |
-
} else {
|
323 |
-
$anonymousFeedback.show();
|
324 |
-
}
|
325 |
-
}
|
326 |
-
|
327 |
-
var _parent = $(this).parents('li:first');
|
328 |
-
|
329 |
-
$modal.find('.reason-input').remove();
|
330 |
-
$modal.find( '.internal-message' ).hide();
|
331 |
-
$modal.find('.button-deactivate').html('<?php echo esc_js( sprintf(
|
332 |
-
fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit' , $slug ),
|
333 |
-
$fs->is_plugin() ?
|
334 |
-
$deactivate_text :
|
335 |
-
sprintf( $activate_x_text, $theme_text )
|
336 |
-
) ) ?>');
|
337 |
-
|
338 |
-
enableDeactivateButton();
|
339 |
-
|
340 |
-
if ( _parent.hasClass( 'has-internal-message' ) ) {
|
341 |
-
_parent.find( '.internal-message' ).show();
|
342 |
-
}
|
343 |
-
|
344 |
-
if (_parent.hasClass('has-input')) {
|
345 |
-
var inputType = _parent.data('input-type'),
|
346 |
-
inputPlaceholder = _parent.data('input-placeholder'),
|
347 |
-
reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" />' : '<textarea rows="5"></textarea>' ) + '</div>';
|
348 |
-
|
349 |
-
_parent.append($(reasonInputHtml));
|
350 |
-
_parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus();
|
351 |
-
|
352 |
-
if (isOtherReasonSelected()) {
|
353 |
-
showMessage('<?php echo esc_js( fs_text_inline( 'Kindly tell us the reason so we can improve.', 'ask-for-reason-message' , $slug ) ); ?>');
|
354 |
-
disableDeactivateButton();
|
355 |
-
}
|
356 |
-
}
|
357 |
-
});
|
358 |
-
|
359 |
-
// If the user has clicked outside the window, cancel it.
|
360 |
-
$modal.on('click', function (evt) {
|
361 |
-
var $target = $(evt.target);
|
362 |
-
|
363 |
-
// If the user has clicked anywhere in the modal dialog, just return.
|
364 |
-
if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) {
|
365 |
-
return;
|
366 |
-
}
|
367 |
-
|
368 |
-
// If the user has not clicked the close button and the clicked element is inside the modal dialog, just return.
|
369 |
-
if (
|
370 |
-
! $target.hasClass( 'button-close' ) &&
|
371 |
-
( $target.parents( '.fs-modal-body' ).length > 0 || $target.parents( '.fs-modal-footer' ).length > 0 )
|
372 |
-
) {
|
373 |
-
return;
|
374 |
-
}
|
375 |
-
|
376 |
-
closeModal();
|
377 |
-
|
378 |
-
return false;
|
379 |
-
});
|
380 |
-
}
|
381 |
-
|
382 |
-
function isAnonymousFeedback() {
|
383 |
-
if ( ! isAnonymous ) {
|
384 |
-
return false;
|
385 |
-
}
|
386 |
-
|
387 |
-
return ( isReasonSelected( dontShareDataReasonID ) || $anonymousFeedback.find( 'input' ).prop( 'checked' ) );
|
388 |
-
}
|
389 |
-
|
390 |
-
function isReasonSelected( reasonID ) {
|
391 |
-
// Get the selected radio input element.
|
392 |
-
var $selectedReasonOption = $modal.find('input[type="radio"]:checked');
|
393 |
-
|
394 |
-
return ( reasonID == $selectedReasonOption.val() );
|
395 |
-
}
|
396 |
-
|
397 |
-
function isOtherReasonSelected() {
|
398 |
-
return isReasonSelected( otherReasonID );
|
399 |
-
}
|
400 |
-
|
401 |
-
function showModal() {
|
402 |
-
resetModal();
|
403 |
-
|
404 |
-
// Display the dialog box.
|
405 |
-
$modal.addClass('active');
|
406 |
-
|
407 |
-
$('body').addClass('has-fs-modal');
|
408 |
-
}
|
409 |
-
|
410 |
-
function closeModal() {
|
411 |
-
$modal.removeClass('active');
|
412 |
-
|
413 |
-
$('body').removeClass('has-fs-modal');
|
414 |
-
}
|
415 |
-
|
416 |
-
function resetModal() {
|
417 |
-
selectedReasonID = false;
|
418 |
-
|
419 |
-
enableDeactivateButton();
|
420 |
-
|
421 |
-
// Uncheck all radio buttons.
|
422 |
-
$modal.find('input[type="radio"]').prop('checked', false);
|
423 |
-
|
424 |
-
// Remove all input fields ( textfield, textarea ).
|
425 |
-
$modal.find('.reason-input').remove();
|
426 |
-
|
427 |
-
$modal.find('.message').hide();
|
428 |
-
|
429 |
-
if ( isAnonymous ) {
|
430 |
-
$anonymousFeedback.find( 'input' ).prop( 'checked', false );
|
431 |
-
|
432 |
-
// Hide, since by default there is no selected reason.
|
433 |
-
$anonymousFeedback.hide();
|
434 |
-
}
|
435 |
-
|
436 |
-
var $deactivateButton = $modal.find('.button-deactivate');
|
437 |
-
|
438 |
-
/*
|
439 |
-
* If the modal dialog has no confirmation message, that is, it has only one panel, then ensure
|
440 |
-
* that clicking the deactivate button will actually deactivate the plugin.
|
441 |
-
*/
|
442 |
-
if ( $modal.hasClass( 'no-confirmation-message' ) ) {
|
443 |
-
$deactivateButton.addClass( 'allow-deactivate' );
|
444 |
-
|
445 |
-
showPanel( 'reasons' );
|
446 |
-
} else {
|
447 |
-
$deactivateButton.removeClass( 'allow-deactivate' );
|
448 |
-
|
449 |
-
showPanel( 'confirm' );
|
450 |
-
}
|
451 |
-
}
|
452 |
-
|
453 |
-
function showMessage(message) {
|
454 |
-
$modal.find('.message').text(message).show();
|
455 |
-
}
|
456 |
-
|
457 |
-
function enableDeactivateButton() {
|
458 |
-
$modal.find('.button-deactivate').removeClass('disabled');
|
459 |
-
}
|
460 |
-
|
461 |
-
function disableDeactivateButton() {
|
462 |
-
$modal.find('.button-deactivate').addClass('disabled');
|
463 |
-
}
|
464 |
-
|
465 |
-
function showPanel(panelType) {
|
466 |
-
$modal.find( '.fs-modal-panel' ).removeClass( 'active' );
|
467 |
-
$modal.find( '[data-panel-id="' + panelType + '"]' ).addClass( 'active' );
|
468 |
-
|
469 |
-
updateButtonLabels();
|
470 |
-
}
|
471 |
-
|
472 |
-
function updateButtonLabels() {
|
473 |
-
var $deactivateButton = $modal.find( '.button-deactivate' );
|
474 |
-
|
475 |
-
// Reset the deactivate button's text.
|
476 |
-
if ( 'confirm' === getCurrentPanel() ) {
|
477 |
-
$deactivateButton.text( <?php echo json_encode( sprintf(
|
478 |
-
fs_text_inline( 'Yes - %s', 'deactivation-modal-button-confirm', $slug ),
|
479 |
-
$fs->is_plugin() ?
|
480 |
-
$deactivate_text :
|
481 |
-
sprintf( $activate_x_text, $theme_text )
|
482 |
-
) ) ?> );
|
483 |
-
} else {
|
484 |
-
$deactivateButton.html( <?php echo json_encode( sprintf(
|
485 |
-
fs_text_inline('Skip & %s', 'skip-and-x', $slug ),
|
486 |
-
$fs->is_plugin() ?
|
487 |
-
$deactivate_text :
|
488 |
-
sprintf( $activate_x_text, $theme_text )
|
489 |
-
) ) ?> );
|
490 |
-
}
|
491 |
-
}
|
492 |
-
|
493 |
-
function getCurrentPanel() {
|
494 |
-
return $modal.find('.fs-modal-panel.active').attr('data-panel-id');
|
495 |
-
}
|
496 |
-
})(jQuery);
|
497 |
-
</script>
|
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 |
+
$confirmation_message = $fs->apply_filters( 'uninstall_confirmation_message', '' );
|
20 |
+
|
21 |
+
$reasons = $VARS['reasons'];
|
22 |
+
|
23 |
+
$reasons_list_items_html = '';
|
24 |
+
|
25 |
+
foreach ( $reasons as $reason ) {
|
26 |
+
$list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' );
|
27 |
+
|
28 |
+
if ( isset( $reason['internal_message'] ) && ! empty( $reason['internal_message'] ) ) {
|
29 |
+
$list_item_classes .= ' has-internal-message';
|
30 |
+
$reason_internal_message = $reason['internal_message'];
|
31 |
+
} else {
|
32 |
+
$reason_internal_message = '';
|
33 |
+
}
|
34 |
+
|
35 |
+
$reason_input_type = ( ! empty( $reason['input_type'] ) ? $reason['input_type'] : '' );
|
36 |
+
$reason_input_placeholder = ( ! empty( $reason['input_placeholder'] ) ? $reason['input_placeholder'] : '' );
|
37 |
+
|
38 |
+
$reason_list_item_html = <<< HTML
|
39 |
+
<li class="{$list_item_classes}"
|
40 |
+
data-input-type="{$reason_input_type}"
|
41 |
+
data-input-placeholder="{$reason_input_placeholder}">
|
42 |
+
<label>
|
43 |
+
<span>
|
44 |
+
<input type="radio" name="selected-reason" value="{$reason['id']}"/>
|
45 |
+
</span>
|
46 |
+
<span>{$reason['text']}</span>
|
47 |
+
</label>
|
48 |
+
<div class="internal-message">{$reason_internal_message}</div>
|
49 |
+
</li>
|
50 |
+
HTML;
|
51 |
+
|
52 |
+
$reasons_list_items_html .= $reason_list_item_html;
|
53 |
+
}
|
54 |
+
|
55 |
+
$is_anonymous = ( ! $fs->is_registered() );
|
56 |
+
if ( $is_anonymous ) {
|
57 |
+
$anonymous_feedback_checkbox_html = sprintf(
|
58 |
+
'<label class="anonymous-feedback-label"><input type="checkbox" class="anonymous-feedback-checkbox"> %s</label>',
|
59 |
+
fs_esc_html_inline( 'Anonymous feedback', 'anonymous-feedback', $slug )
|
60 |
+
);
|
61 |
+
} else {
|
62 |
+
$anonymous_feedback_checkbox_html = '';
|
63 |
+
}
|
64 |
+
|
65 |
+
// Aliases.
|
66 |
+
$deactivate_text = fs_text_inline( 'Deactivate', 'deactivate', $slug );
|
67 |
+
$theme_text = fs_text_inline( 'Theme', 'theme', $slug );
|
68 |
+
$activate_x_text = fs_text_inline( 'Activate %s', 'activate-x', $slug );
|
69 |
+
|
70 |
+
fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
|
71 |
+
?>
|
72 |
+
<?php $fs->_maybe_add_subscription_cancellation_dialog_box() ?>
|
73 |
+
<script type="text/javascript">
|
74 |
+
(function ($) {
|
75 |
+
var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ) ?>,
|
76 |
+
modalHtml =
|
77 |
+
'<div class="fs-modal fs-modal-deactivation-feedback<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">'
|
78 |
+
+ ' <div class="fs-modal-dialog">'
|
79 |
+
+ ' <div class="fs-modal-header">'
|
80 |
+
+ ' <h4><?php fs_esc_attr_echo_inline( 'Quick Feedback', 'quick-feedback' , $slug ) ?></h4>'
|
81 |
+
+ ' </div>'
|
82 |
+
+ ' <div class="fs-modal-body">'
|
83 |
+
+ ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>'
|
84 |
+
+ ' <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>'
|
85 |
+
+ ' </div>'
|
86 |
+
+ ' <div class="fs-modal-footer">'
|
87 |
+
+ ' <?php echo $anonymous_feedback_checkbox_html ?>'
|
88 |
+
+ ' <a href="#" class="button button-secondary button-deactivate"></a>'
|
89 |
+
+ ' <a href="#" class="button button-primary button-close"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel', $slug ) ?></a>'
|
90 |
+
+ ' </div>'
|
91 |
+
+ ' </div>'
|
92 |
+
+ '</div>',
|
93 |
+
$modal = $(modalHtml),
|
94 |
+
$deactivateLink = $('#the-list .deactivate > [data-module-id=<?php echo $fs->get_id() ?>].fs-module-id').prev(),
|
95 |
+
selectedReasonID = false,
|
96 |
+
redirectLink = '',
|
97 |
+
$anonymousFeedback = $modal.find( '.anonymous-feedback-label' ),
|
98 |
+
isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
|
99 |
+
otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
|
100 |
+
dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>,
|
101 |
+
deleteThemeUpdateData = <?php echo $fs->is_theme() && $fs->is_premium() && ! $fs->has_any_active_valid_license() ? 'true' : 'false' ?>,
|
102 |
+
$subscriptionCancellationModal = $( '.fs-modal-subscription-cancellation-<?php echo $fs->get_id() ?>' );
|
103 |
+
|
104 |
+
$modal.appendTo($('body'));
|
105 |
+
|
106 |
+
if ( 0 !== $subscriptionCancellationModal.length ) {
|
107 |
+
$subscriptionCancellationModal.on( '<?php echo $fs->get_action_tag( 'subscription_cancellation_action' ) ?>', function( evt, cancelSubscription ) {
|
108 |
+
if ( false === cancelSubscription ) {
|
109 |
+
showModal();
|
110 |
+
|
111 |
+
$subscriptionCancellationModal.trigger( 'closeModal' );
|
112 |
+
} else {
|
113 |
+
var $errorMessage = $subscriptionCancellationModal.find( '.notice-error' );
|
114 |
+
|
115 |
+
<?php
|
116 |
+
$subscription_cancellation_context = $fs->is_paid_trial() ?
|
117 |
+
fs_text_inline( 'trial', 'trial', $slug ) :
|
118 |
+
fs_text_inline( 'subscription', 'subscription', $slug );
|
119 |
+
?>
|
120 |
+
|
121 |
+
$.ajax({
|
122 |
+
url : ajaxurl,
|
123 |
+
method : 'POST',
|
124 |
+
data : {
|
125 |
+
action : '<?php echo $fs->get_ajax_action( 'cancel_subscription_or_trial' ) ?>',
|
126 |
+
security : '<?php echo $fs->get_ajax_security( 'cancel_subscription_or_trial' ) ?>',
|
127 |
+
module_id: '<?php echo $fs->get_id() ?>'
|
128 |
+
},
|
129 |
+
beforeSend: function() {
|
130 |
+
$errorMessage.hide();
|
131 |
+
|
132 |
+
$subscriptionCancellationModal.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
|
133 |
+
$subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).text( '<?php echo esc_js(
|
134 |
+
sprintf( fs_text_inline( 'Cancelling %s...', 'cancelling-x' , $slug ), $subscription_cancellation_context )
|
135 |
+
) ?>' );
|
136 |
+
},
|
137 |
+
success: function( result ) {
|
138 |
+
if ( result.success ) {
|
139 |
+
$subscriptionCancellationModal.removeClass( 'has-subscription-actions' );
|
140 |
+
$subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).removeClass( 'warn' );
|
141 |
+
|
142 |
+
$subscriptionCancellationModal.remove();
|
143 |
+
showModal();
|
144 |
+
} else {
|
145 |
+
$errorMessage.find( '> p' ).html( result.error );
|
146 |
+
$errorMessage.show();
|
147 |
+
|
148 |
+
$subscriptionCancellationModal.find( '.fs-modal-footer .button' ).removeClass( 'disabled' );
|
149 |
+
$subscriptionCancellationModal.find( '.fs-modal-footer .button-primary' ).html( <?php echo json_encode( sprintf(
|
150 |
+
fs_text_inline( 'Cancel %s & Proceed', 'cancel-x-and-proceed', $slug ),
|
151 |
+
ucfirst( $subscription_cancellation_context )
|
152 |
+
) ) ?> );
|
153 |
+
}
|
154 |
+
}
|
155 |
+
});
|
156 |
+
}
|
157 |
+
});
|
158 |
+
}
|
159 |
+
|
160 |
+
registerEventHandlers();
|
161 |
+
|
162 |
+
function registerEventHandlers() {
|
163 |
+
$deactivateLink.click(function (evt) {
|
164 |
+
evt.preventDefault();
|
165 |
+
|
166 |
+
redirectLink = $(this).attr('href');
|
167 |
+
|
168 |
+
if ( 0 == $subscriptionCancellationModal.length ) {
|
169 |
+
showModal();
|
170 |
+
} else {
|
171 |
+
$subscriptionCancellationModal.trigger( 'showModal' );
|
172 |
+
}
|
173 |
+
});
|
174 |
+
|
175 |
+
<?php
|
176 |
+
if ( ! $fs->is_plugin() ) {
|
177 |
+
/**
|
178 |
+
* For "theme" module type, the modal is shown when the current user clicks on
|
179 |
+
* the "Activate" button of any other theme. The "Activate" button is actually
|
180 |
+
* a link to the "Themes" page (/wp-admin/themes.php) containing query params
|
181 |
+
* that tell WordPress to deactivate the current theme and activate a different theme.
|
182 |
+
*
|
183 |
+
* @author Leo Fajardo (@leorw)
|
184 |
+
* @since 1.2.2
|
185 |
+
*
|
186 |
+
* @since 1.2.2.7 Don't trigger the deactivation feedback form if activating the premium version of the theme.
|
187 |
+
*/
|
188 |
+
?>
|
189 |
+
$('body').on('click', '.theme-browser .theme:not([data-slug=<?php echo $fs->get_premium_slug() ?>]) .theme-actions .button.activate', function (evt) {
|
190 |
+
evt.preventDefault();
|
191 |
+
|
192 |
+
redirectLink = $(this).attr('href');
|
193 |
+
|
194 |
+
showModal();
|
195 |
+
});
|
196 |
+
<?php
|
197 |
+
} ?>
|
198 |
+
|
199 |
+
$modal.on('input propertychange', '.reason-input input', function () {
|
200 |
+
if (!isOtherReasonSelected()) {
|
201 |
+
return;
|
202 |
+
}
|
203 |
+
|
204 |
+
var reason = $(this).val().trim();
|
205 |
+
|
206 |
+
/**
|
207 |
+
* If reason is not empty, remove the error-message class of the message container
|
208 |
+
* to change the message color back to default.
|
209 |
+
*/
|
210 |
+
if (reason.length > 0) {
|
211 |
+
$('.message').removeClass('error-message');
|
212 |
+
enableDeactivateButton();
|
213 |
+
}
|
214 |
+
});
|
215 |
+
|
216 |
+
$modal.on('blur', '.reason-input input', function () {
|
217 |
+
var $userReason = $(this);
|
218 |
+
|
219 |
+
setTimeout(function () {
|
220 |
+
if (!isOtherReasonSelected()) {
|
221 |
+
return;
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* If reason is empty, add the error-message class to the message container
|
226 |
+
* to change the message color to red.
|
227 |
+
*/
|
228 |
+
if (0 === $userReason.val().trim().length) {
|
229 |
+
$('.message').addClass('error-message');
|
230 |
+
disableDeactivateButton();
|
231 |
+
}
|
232 |
+
}, 150);
|
233 |
+
});
|
234 |
+
|
235 |
+
$modal.on('click', '.fs-modal-footer .button', function (evt) {
|
236 |
+
evt.preventDefault();
|
237 |
+
|
238 |
+
if ($(this).hasClass('disabled')) {
|
239 |
+
return;
|
240 |
+
}
|
241 |
+
|
242 |
+
var _parent = $(this).parents('.fs-modal:first');
|
243 |
+
var _this = $(this);
|
244 |
+
|
245 |
+
if (_this.hasClass('allow-deactivate')) {
|
246 |
+
var $radio = $('input[type="radio"]:checked');
|
247 |
+
|
248 |
+
if (0 === $radio.length) {
|
249 |
+
if ( ! deleteThemeUpdateData ) {
|
250 |
+
// If no selected reason, just deactivate the plugin.
|
251 |
+
window.location.href = redirectLink;
|
252 |
+
} else {
|
253 |
+
$.ajax({
|
254 |
+
url : ajaxurl,
|
255 |
+
method : 'POST',
|
256 |
+
data : {
|
257 |
+
action : '<?php echo $fs->get_ajax_action( 'delete_theme_update_data' ) ?>',
|
258 |
+
security : '<?php echo $fs->get_ajax_security( 'delete_theme_update_data' ) ?>',
|
259 |
+
module_id: '<?php echo $fs->get_id() ?>'
|
260 |
+
},
|
261 |
+
beforeSend: function() {
|
262 |
+
_parent.find( '.fs-modal-footer .button' ).addClass( 'disabled' );
|
263 |
+
_parent.find( '.fs-modal-footer .button-secondary' ).text( 'Processing...' );
|
264 |
+
},
|
265 |
+
complete : function() {
|
266 |
+
window.location.href = redirectLink;
|
267 |
+
}
|
268 |
+
});
|
269 |
+
}
|
270 |
+
|
271 |
+
return;
|
272 |
+
}
|
273 |
+
|
274 |
+
var $selected_reason = $radio.parents('li:first'),
|
275 |
+
$input = $selected_reason.find('textarea, input[type="text"]'),
|
276 |
+
userReason = ( 0 !== $input.length ) ? $input.val().trim() : '';
|
277 |
+
|
278 |
+
if (isOtherReasonSelected() && ( '' === userReason )) {
|
279 |
+
return;
|
280 |
+
}
|
281 |
+
|
282 |
+
$.ajax({
|
283 |
+
url : ajaxurl,
|
284 |
+
method : 'POST',
|
285 |
+
data : {
|
286 |
+
action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
|
287 |
+
security : '<?php echo $fs->get_ajax_security( 'submit_uninstall_reason' ) ?>',
|
288 |
+
module_id : '<?php echo $fs->get_id() ?>',
|
289 |
+
reason_id : $radio.val(),
|
290 |
+
reason_info : userReason,
|
291 |
+
is_anonymous: isAnonymousFeedback()
|
292 |
+
},
|
293 |
+
beforeSend: function () {
|
294 |
+
_parent.find('.fs-modal-footer .button').addClass('disabled');
|
295 |
+
_parent.find('.fs-modal-footer .button-secondary').text('Processing...');
|
296 |
+
},
|
297 |
+
complete : function () {
|
298 |
+
// Do not show the dialog box, deactivate the plugin.
|
299 |
+
window.location.href = redirectLink;
|
300 |
+
}
|
301 |
+
});
|
302 |
+
} else if (_this.hasClass('button-deactivate')) {
|
303 |
+
// Change the Deactivate button's text and show the reasons panel.
|
304 |
+
_parent.find('.button-deactivate').addClass('allow-deactivate');
|
305 |
+
|
306 |
+
showPanel('reasons');
|
307 |
+
}
|
308 |
+
});
|
309 |
+
|
310 |
+
$modal.on('click', 'input[type="radio"]', function () {
|
311 |
+
var $selectedReasonOption = $( this );
|
312 |
+
|
313 |
+
// If the selection has not changed, do not proceed.
|
314 |
+
if (selectedReasonID === $selectedReasonOption.val())
|
315 |
+
return;
|
316 |
+
|
317 |
+
selectedReasonID = $selectedReasonOption.val();
|
318 |
+
|
319 |
+
if ( isAnonymous ) {
|
320 |
+
if ( isReasonSelected( dontShareDataReasonID ) ) {
|
321 |
+
$anonymousFeedback.hide();
|
322 |
+
} else {
|
323 |
+
$anonymousFeedback.show();
|
324 |
+
}
|
325 |
+
}
|
326 |
+
|
327 |
+
var _parent = $(this).parents('li:first');
|
328 |
+
|
329 |
+
$modal.find('.reason-input').remove();
|
330 |
+
$modal.find( '.internal-message' ).hide();
|
331 |
+
$modal.find('.button-deactivate').html('<?php echo esc_js( sprintf(
|
332 |
+
fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit' , $slug ),
|
333 |
+
$fs->is_plugin() ?
|
334 |
+
$deactivate_text :
|
335 |
+
sprintf( $activate_x_text, $theme_text )
|
336 |
+
) ) ?>');
|
337 |
+
|
338 |
+
enableDeactivateButton();
|
339 |
+
|
340 |
+
if ( _parent.hasClass( 'has-internal-message' ) ) {
|
341 |
+
_parent.find( '.internal-message' ).show();
|
342 |
+
}
|
343 |
+
|
344 |
+
if (_parent.hasClass('has-input')) {
|
345 |
+
var inputType = _parent.data('input-type'),
|
346 |
+
inputPlaceholder = _parent.data('input-placeholder'),
|
347 |
+
reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" />' : '<textarea rows="5"></textarea>' ) + '</div>';
|
348 |
+
|
349 |
+
_parent.append($(reasonInputHtml));
|
350 |
+
_parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus();
|
351 |
+
|
352 |
+
if (isOtherReasonSelected()) {
|
353 |
+
showMessage('<?php echo esc_js( fs_text_inline( 'Kindly tell us the reason so we can improve.', 'ask-for-reason-message' , $slug ) ); ?>');
|
354 |
+
disableDeactivateButton();
|
355 |
+
}
|
356 |
+
}
|
357 |
+
});
|
358 |
+
|
359 |
+
// If the user has clicked outside the window, cancel it.
|
360 |
+
$modal.on('click', function (evt) {
|
361 |
+
var $target = $(evt.target);
|
362 |
+
|
363 |
+
// If the user has clicked anywhere in the modal dialog, just return.
|
364 |
+
if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) {
|
365 |
+
return;
|
366 |
+
}
|
367 |
+
|
368 |
+
// If the user has not clicked the close button and the clicked element is inside the modal dialog, just return.
|
369 |
+
if (
|
370 |
+
! $target.hasClass( 'button-close' ) &&
|
371 |
+
( $target.parents( '.fs-modal-body' ).length > 0 || $target.parents( '.fs-modal-footer' ).length > 0 )
|
372 |
+
) {
|
373 |
+
return;
|
374 |
+
}
|
375 |
+
|
376 |
+
closeModal();
|
377 |
+
|
378 |
+
return false;
|
379 |
+
});
|
380 |
+
}
|
381 |
+
|
382 |
+
function isAnonymousFeedback() {
|
383 |
+
if ( ! isAnonymous ) {
|
384 |
+
return false;
|
385 |
+
}
|
386 |
+
|
387 |
+
return ( isReasonSelected( dontShareDataReasonID ) || $anonymousFeedback.find( 'input' ).prop( 'checked' ) );
|
388 |
+
}
|
389 |
+
|
390 |
+
function isReasonSelected( reasonID ) {
|
391 |
+
// Get the selected radio input element.
|
392 |
+
var $selectedReasonOption = $modal.find('input[type="radio"]:checked');
|
393 |
+
|
394 |
+
return ( reasonID == $selectedReasonOption.val() );
|
395 |
+
}
|
396 |
+
|
397 |
+
function isOtherReasonSelected() {
|
398 |
+
return isReasonSelected( otherReasonID );
|
399 |
+
}
|
400 |
+
|
401 |
+
function showModal() {
|
402 |
+
resetModal();
|
403 |
+
|
404 |
+
// Display the dialog box.
|
405 |
+
$modal.addClass('active');
|
406 |
+
|
407 |
+
$('body').addClass('has-fs-modal');
|
408 |
+
}
|
409 |
+
|
410 |
+
function closeModal() {
|
411 |
+
$modal.removeClass('active');
|
412 |
+
|
413 |
+
$('body').removeClass('has-fs-modal');
|
414 |
+
}
|
415 |
+
|
416 |
+
function resetModal() {
|
417 |
+
selectedReasonID = false;
|
418 |
+
|
419 |
+
enableDeactivateButton();
|
420 |
+
|
421 |
+
// Uncheck all radio buttons.
|
422 |
+
$modal.find('input[type="radio"]').prop('checked', false);
|
423 |
+
|
424 |
+
// Remove all input fields ( textfield, textarea ).
|
425 |
+
$modal.find('.reason-input').remove();
|
426 |
+
|
427 |
+
$modal.find('.message').hide();
|
428 |
+
|
429 |
+
if ( isAnonymous ) {
|
430 |
+
$anonymousFeedback.find( 'input' ).prop( 'checked', false );
|
431 |
+
|
432 |
+
// Hide, since by default there is no selected reason.
|
433 |
+
$anonymousFeedback.hide();
|
434 |
+
}
|
435 |
+
|
436 |
+
var $deactivateButton = $modal.find('.button-deactivate');
|
437 |
+
|
438 |
+
/*
|
439 |
+
* If the modal dialog has no confirmation message, that is, it has only one panel, then ensure
|
440 |
+
* that clicking the deactivate button will actually deactivate the plugin.
|
441 |
+
*/
|
442 |
+
if ( $modal.hasClass( 'no-confirmation-message' ) ) {
|
443 |
+
$deactivateButton.addClass( 'allow-deactivate' );
|
444 |
+
|
445 |
+
showPanel( 'reasons' );
|
446 |
+
} else {
|
447 |
+
$deactivateButton.removeClass( 'allow-deactivate' );
|
448 |
+
|
449 |
+
showPanel( 'confirm' );
|
450 |
+
}
|
451 |
+
}
|
452 |
+
|
453 |
+
function showMessage(message) {
|
454 |
+
$modal.find('.message').text(message).show();
|
455 |
+
}
|
456 |
+
|
457 |
+
function enableDeactivateButton() {
|
458 |
+
$modal.find('.button-deactivate').removeClass('disabled');
|
459 |
+
}
|
460 |
+
|
461 |
+
function disableDeactivateButton() {
|
462 |
+
$modal.find('.button-deactivate').addClass('disabled');
|
463 |
+
}
|
464 |
+
|
465 |
+
function showPanel(panelType) {
|
466 |
+
$modal.find( '.fs-modal-panel' ).removeClass( 'active' );
|
467 |
+
$modal.find( '[data-panel-id="' + panelType + '"]' ).addClass( 'active' );
|
468 |
+
|
469 |
+
updateButtonLabels();
|
470 |
+
}
|
471 |
+
|
472 |
+
function updateButtonLabels() {
|
473 |
+
var $deactivateButton = $modal.find( '.button-deactivate' );
|
474 |
+
|
475 |
+
// Reset the deactivate button's text.
|
476 |
+
if ( 'confirm' === getCurrentPanel() ) {
|
477 |
+
$deactivateButton.text( <?php echo json_encode( sprintf(
|
478 |
+
fs_text_inline( 'Yes - %s', 'deactivation-modal-button-confirm', $slug ),
|
479 |
+
$fs->is_plugin() ?
|
480 |
+
$deactivate_text :
|
481 |
+
sprintf( $activate_x_text, $theme_text )
|
482 |
+
) ) ?> );
|
483 |
+
} else {
|
484 |
+
$deactivateButton.html( <?php echo json_encode( sprintf(
|
485 |
+
fs_text_inline('Skip & %s', 'skip-and-x', $slug ),
|
486 |
+
$fs->is_plugin() ?
|
487 |
+
$deactivate_text :
|
488 |
+
sprintf( $activate_x_text, $theme_text )
|
489 |
+
) ) ?> );
|
490 |
+
}
|
491 |
+
}
|
492 |
+
|
493 |
+
function getCurrentPanel() {
|
494 |
+
return $modal.find('.fs-modal-panel.active').attr('data-panel-id');
|
495 |
+
}
|
496 |
+
})(jQuery);
|
497 |
+
</script>
|
plugin.php
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
* Description: Blocks for everyone
|
7 |
* Author: Gambit Technologies, Inc
|
8 |
* Author URI: http://gambit.ph
|
9 |
-
* Version: 1.13.
|
10 |
*
|
11 |
* @package Stackable
|
12 |
*/
|
@@ -22,7 +22,7 @@ if ( function_exists( 'sugb_fs' ) ) {
|
|
22 |
}
|
23 |
|
24 |
defined( 'STACKABLE_SHOW_PRO_NOTICES' ) || define( 'STACKABLE_SHOW_PRO_NOTICES', true );
|
25 |
-
defined( 'STACKABLE_VERSION' ) || define( 'STACKABLE_VERSION', '1.13.
|
26 |
defined( 'STACKABLE_FILE' ) || define( 'STACKABLE_FILE', __FILE__ );
|
27 |
/********************************************************************************************
|
28 |
* Activation & PHP version checks.
|
6 |
* Description: Blocks for everyone
|
7 |
* Author: Gambit Technologies, Inc
|
8 |
* Author URI: http://gambit.ph
|
9 |
+
* Version: 1.13.3
|
10 |
*
|
11 |
* @package Stackable
|
12 |
*/
|
22 |
}
|
23 |
|
24 |
defined( 'STACKABLE_SHOW_PRO_NOTICES' ) || define( 'STACKABLE_SHOW_PRO_NOTICES', true );
|
25 |
+
defined( 'STACKABLE_VERSION' ) || define( 'STACKABLE_VERSION', '1.13.3' );
|
26 |
defined( 'STACKABLE_FILE' ) || define( 'STACKABLE_FILE', __FILE__ );
|
27 |
/********************************************************************************************
|
28 |
* Activation & PHP version checks.
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Tags: gutenberg, block, blocks, block editor, gutenberg blocks, page builder, ed
|
|
4 |
Requires at least: 4.8
|
5 |
Tested up to: 5.1
|
6 |
Requires PHP: 5.3
|
7 |
-
Stable tag: 1.13.
|
8 |
License: GPLv3
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -119,6 +119,11 @@ You will have to redo all your blocks
|
|
119 |
|
120 |
== Changelog ==
|
121 |
|
|
|
|
|
|
|
|
|
|
|
122 |
= 1.13.2 =
|
123 |
* New: Added modal slider for Premium "Learn More" buttons
|
124 |
* New: Scripts & style loading optimization: CSS files are now preloaded / prefetched, JS files are now deferred
|
4 |
Requires at least: 4.8
|
5 |
Tested up to: 5.1
|
6 |
Requires PHP: 5.3
|
7 |
+
Stable tag: 1.13.3
|
8 |
License: GPLv3
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
119 |
|
120 |
== Changelog ==
|
121 |
|
122 |
+
= 1.13.3 =
|
123 |
+
* Fixed: Removed preload & prefetch since they're causing problems in Safari and Firefox. Let's leave this to the optimization plugins.
|
124 |
+
* Fixed: Security fix
|
125 |
+
* Change: Removed small Premium notices from the editor
|
126 |
+
|
127 |
= 1.13.2 =
|
128 |
* New: Added modal slider for Premium "Learn More" buttons
|
129 |
* New: Scripts & style loading optimization: CSS files are now preloaded / prefetched, JS files are now deferred
|
src/init.php
CHANGED
@@ -38,9 +38,6 @@ if ( ! function_exists( 'stackable_block_assets' ) ) {
|
|
38 |
array(),
|
39 |
STACKABLE_VERSION
|
40 |
);
|
41 |
-
|
42 |
-
stackable_set_style_async( 'ugb-style-css' );
|
43 |
-
stackable_set_script_async( 'ugb-block-frontend-js' );
|
44 |
}
|
45 |
}
|
46 |
add_action( 'enqueue_block_assets', 'stackable_block_assets' );
|
@@ -91,7 +88,7 @@ if ( ! function_exists( 'stackable_block_editor_assets' ) ) {
|
|
91 |
// Premium related variables.
|
92 |
'isPro' => sugb_fs()->can_use_premium_code(),
|
93 |
'showProNotice' => stackable_should_show_pro_notices(),
|
94 |
-
'showSmallProNotices' =>
|
95 |
'pricingURL' => sugb_fs()->get_upgrade_url(),
|
96 |
'planName' => sugb_fs()->is_plan( 'starter', true ) ? 'starter' :
|
97 |
sugb_fs()->is_plan( 'professional', true ) ? 'professional' : 'business',
|
@@ -139,45 +136,3 @@ if ( ! function_exists( 'stackable_add_required_block_styles' ) ) {
|
|
139 |
}
|
140 |
add_action( 'enqueue_block_assets', 'stackable_add_required_block_styles', 11 );
|
141 |
}
|
142 |
-
|
143 |
-
if ( ! function_exists( 'stackable_set_style_async' ) ) {
|
144 |
-
global $stackable_style_asyncs;
|
145 |
-
$stackable_style_asyncs = [];
|
146 |
-
function stackable_set_style_async( $handle ) {
|
147 |
-
global $stackable_style_asyncs;
|
148 |
-
$stackable_style_asyncs[] = $handle;
|
149 |
-
}
|
150 |
-
}
|
151 |
-
|
152 |
-
if ( ! function_exists( 'stackable_style_async' ) ) {
|
153 |
-
function stackable_style_async( $tag, $handle, $src ) {
|
154 |
-
global $stackable_style_asyncs;
|
155 |
-
// ugb-style-css is our BASE CSS, so preload it to prioritize.
|
156 |
-
$rel = $handle === 'ugb-style-css' ? 'preload' : 'prefetch';
|
157 |
-
if ( in_array( $handle, $stackable_style_asyncs ) ) {
|
158 |
-
return str_replace( "rel='stylesheet'", "rel='$rel' as='style' onload='this.rel = \"stylesheet\"'", $tag );
|
159 |
-
}
|
160 |
-
return $tag;
|
161 |
-
}
|
162 |
-
add_filter( 'style_loader_tag', 'stackable_style_async', 10, 3 );
|
163 |
-
}
|
164 |
-
|
165 |
-
if ( ! function_exists( 'stackable_set_script_async' ) ) {
|
166 |
-
global $stackable_script_asyncs;
|
167 |
-
$stackable_script_asyncs = [];
|
168 |
-
function stackable_set_script_async( $handle ) {
|
169 |
-
global $stackable_script_asyncs;
|
170 |
-
$stackable_script_asyncs[] = $handle;
|
171 |
-
}
|
172 |
-
}
|
173 |
-
|
174 |
-
if ( ! function_exists( 'stackable_script_async' ) ) {
|
175 |
-
function stackable_script_async( $tag, $handle, $src ) {
|
176 |
-
global $stackable_script_asyncs;
|
177 |
-
if ( in_array( $handle, $stackable_script_asyncs ) ) {
|
178 |
-
return str_replace( "<script", "<script defer", $tag );
|
179 |
-
}
|
180 |
-
return $tag;
|
181 |
-
}
|
182 |
-
add_filter( 'script_loader_tag', 'stackable_script_async', 10, 3 );
|
183 |
-
}
|
38 |
array(),
|
39 |
STACKABLE_VERSION
|
40 |
);
|
|
|
|
|
|
|
41 |
}
|
42 |
}
|
43 |
add_action( 'enqueue_block_assets', 'stackable_block_assets' );
|
88 |
// Premium related variables.
|
89 |
'isPro' => sugb_fs()->can_use_premium_code(),
|
90 |
'showProNotice' => stackable_should_show_pro_notices(),
|
91 |
+
'showSmallProNotices' => false,
|
92 |
'pricingURL' => sugb_fs()->get_upgrade_url(),
|
93 |
'planName' => sugb_fs()->is_plan( 'starter', true ) ? 'starter' :
|
94 |
sugb_fs()->is_plan( 'professional', true ) ? 'professional' : 'business',
|
136 |
}
|
137 |
add_action( 'enqueue_block_assets', 'stackable_add_required_block_styles', 11 );
|
138 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/pro.php
CHANGED
@@ -66,22 +66,6 @@ if ( ! function_exists( 'stackable_show_pro_notices_option_nonce' ) ) {
|
|
66 |
}
|
67 |
}
|
68 |
|
69 |
-
if ( ! function_exists( 'stackable_should_show_small_pro_notices' ) ) {
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Should we show small premium notices?
|
73 |
-
*
|
74 |
-
* @return Mixed False if hide, 'show' if visible, 'fade' if visible but slightly less.
|
75 |
-
*/
|
76 |
-
function stackable_should_show_small_pro_notices() {
|
77 |
-
$small_notice_show = get_option( 'stackable_small_pro_notice_show' );
|
78 |
-
if ( in_array( $small_notice_show, array( 'show', 'fade' ) ) ) {
|
79 |
-
return $small_notice_show;
|
80 |
-
}
|
81 |
-
return false;
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
if ( ! function_exists( 'stackable_should_show_pro_notices' ) ) {
|
86 |
|
87 |
/**
|
@@ -102,14 +86,14 @@ if ( ! class_exists( 'Stackable_Go_Premium_Notification' ) ) {
|
|
102 |
*
|
103 |
* @var int
|
104 |
*/
|
105 |
-
const SHOW_NOTICE_TIME =
|
106 |
|
107 |
/**
|
108 |
-
* The amount of time
|
109 |
*
|
110 |
* @var int
|
111 |
*/
|
112 |
-
const
|
113 |
|
114 |
|
115 |
function __construct() {
|
@@ -130,17 +114,7 @@ if ( ! class_exists( 'Stackable_Go_Premium_Notification' ) ) {
|
|
130 |
$activation_time = get_option( 'stackable_pro_notice_start_date' );
|
131 |
$elapsed_time = time() - absint( $activation_time );
|
132 |
|
133 |
-
|
134 |
-
if ( $elapsed_time < self::SHOW_NOTICE_TIME ) {
|
135 |
-
delete_option( 'stackable_small_pro_notice_show' );
|
136 |
-
|
137 |
-
// Show notices.
|
138 |
-
} else if ( self::SHOW_NOTICE_TIME < $elapsed_time && $elapsed_time < self::FADE_NOTICE_TIME ) {
|
139 |
-
update_option( 'stackable_small_pro_notice_show', 'show' );
|
140 |
-
|
141 |
-
// Show faded.
|
142 |
-
} else if ( self::FADE_NOTICE_TIME < $elapsed_time ) {
|
143 |
-
update_option( 'stackable_small_pro_notice_show', 'fade' );
|
144 |
$this->show_notification();
|
145 |
}
|
146 |
}
|
@@ -156,8 +130,8 @@ if ( ! class_exists( 'Stackable_Go_Premium_Notification' ) ) {
|
|
156 |
$activation_time = get_option( 'stackable_activation_date' );
|
157 |
$elapsed_time = time() - absint( $activation_time );
|
158 |
|
159 |
-
// This time
|
160 |
-
if ( $elapsed_time > self::
|
161 |
$this->show_notification();
|
162 |
}
|
163 |
}
|
66 |
}
|
67 |
}
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
if ( ! function_exists( 'stackable_should_show_pro_notices' ) ) {
|
70 |
|
71 |
/**
|
86 |
*
|
87 |
* @var int
|
88 |
*/
|
89 |
+
const SHOW_NOTICE_TIME = 604800; // 7 * 24 * 60 * 60
|
90 |
|
91 |
/**
|
92 |
+
* The amount of time for old plugin users to see the premium notice.
|
93 |
*
|
94 |
* @var int
|
95 |
*/
|
96 |
+
const OLD_TIMER_NOTICE_TIME = 604800; // 7 * 24 * 60 * 60
|
97 |
|
98 |
|
99 |
function __construct() {
|
114 |
$activation_time = get_option( 'stackable_pro_notice_start_date' );
|
115 |
$elapsed_time = time() - absint( $activation_time );
|
116 |
|
117 |
+
if ( self::SHOW_NOTICE_TIME < $elapsed_time ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
$this->show_notification();
|
119 |
}
|
120 |
}
|
130 |
$activation_time = get_option( 'stackable_activation_date' );
|
131 |
$elapsed_time = time() - absint( $activation_time );
|
132 |
|
133 |
+
// This time should be more than the rating notice so as not to be annoying.
|
134 |
+
if ( $elapsed_time > self::OLD_TIMER_NOTICE_TIME ) {
|
135 |
$this->show_notification();
|
136 |
}
|
137 |
}
|
src/welcome/notification-rate.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
* Adds a Rate us notification if the plugin has been installed for some time.
|
4 |
-
*
|
5 |
* @package Stackable
|
6 |
*/
|
7 |
|
@@ -15,18 +15,18 @@ if ( ! class_exists( 'Stackable_Welcome_Notification_Rate' ) ) {
|
|
15 |
|
16 |
/**
|
17 |
* The amount of time from plugin activation to wait in seconds to display the rating notice.
|
18 |
-
*
|
19 |
* @var int
|
20 |
*/
|
21 |
-
const RATING_NOTICE_TIME =
|
22 |
|
23 |
function __construct() {
|
24 |
add_action( 'admin_menu', array( $this, 'check_activation_date' ), 9 );
|
25 |
}
|
26 |
|
27 |
-
/**
|
28 |
* Checks whether the activation date surpasses our limit and then displays a rating notification.
|
29 |
-
*
|
30 |
* @since 1.7
|
31 |
*/
|
32 |
public function check_activation_date() {
|
@@ -44,4 +44,4 @@ if ( ! class_exists( 'Stackable_Welcome_Notification_Rate' ) ) {
|
|
44 |
}
|
45 |
|
46 |
new Stackable_Welcome_Notification_Rate();
|
47 |
-
}
|
1 |
<?php
|
2 |
/**
|
3 |
* Adds a Rate us notification if the plugin has been installed for some time.
|
4 |
+
*
|
5 |
* @package Stackable
|
6 |
*/
|
7 |
|
15 |
|
16 |
/**
|
17 |
* The amount of time from plugin activation to wait in seconds to display the rating notice.
|
18 |
+
*
|
19 |
* @var int
|
20 |
*/
|
21 |
+
const RATING_NOTICE_TIME = 432000; // 5 * 24 * 60 * 60
|
22 |
|
23 |
function __construct() {
|
24 |
add_action( 'admin_menu', array( $this, 'check_activation_date' ), 9 );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
* Checks whether the activation date surpasses our limit and then displays a rating notification.
|
29 |
+
*
|
30 |
* @since 1.7
|
31 |
*/
|
32 |
public function check_activation_date() {
|
44 |
}
|
45 |
|
46 |
new Stackable_Welcome_Notification_Rate();
|
47 |
+
}
|