PluginProbe
BlockSpare – Gutenberg Blocks, AI Content Generator & Site Builder for News, Magazine & Blogs / 5.0.1
BlockSpare – Gutenberg Blocks, AI Content Generator & Site Builder for News, Magazine & Blogs v5.0.1
5.0.1 4.1.0 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 2.1.2 2.5.0 2.5.3 All 39 releases
← All changes | freemius/templates/forms/license-activation.php +900 -870 2.1.2 → 5.0.1 View file →
@@ -1,870 +1,900 @@
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.9
7 - */
8 -
9 - if ( ! defined( 'ABSPATH' ) ) {
10 - exit;
11 - }
12 -
13 - /**
14 - * @var array $VARS
15 - *
16 - * @var Freemius $fs
17 - */
18 - $fs = freemius( $VARS['id'] );
19 - $slug = $fs->get_slug();
20 - $unique_affix = $fs->get_unique_affix();
21 -
22 - $cant_find_license_key_text = fs_text_inline( "Can't find your license key?", 'cant-find-license-key', $slug );
23 - $message_above_input_field = fs_text_inline( 'Please enter the license key that you received in the email right after the purchase:', 'activate-license-message', $slug );
24 - $message_below_input_field = '';
25 -
26 - $header_title = $fs->is_free_plan() ?
27 - fs_text_inline( 'Activate License', 'activate-license', $slug ) :
28 - fs_text_inline( 'Update License', 'update-license', $slug );
29 -
30 - if ( $fs->is_registered() ) {
31 - $activate_button_text = $header_title;
32 - } else {
33 - $freemius_site_url = $fs->has_paid_plan() ?
34 - 'https://freemius.com/' :
35 - // Insights platform information.
36 - $fs->get_usage_tracking_terms_url();
37 -
38 - $freemius_link = '<a href="' . $freemius_site_url . '" target="_blank" rel="noopener" tabindex="0">freemius.com</a>';
39 -
40 - $message_below_input_field = sprintf(
41 - fs_text_inline( 'The %1$s will be periodically sending data to %2$s to check for security and feature updates, and verify the validity of your license.', 'license-sync-disclaimer', $slug ),
42 - $fs->get_module_label( true ),
43 - $freemius_link
44 - );
45 -
46 - $activate_button_text = fs_text_inline( 'Agree & Activate License', 'agree-activate-license', $slug );
47 - }
48 -
49 - $license_key_text = fs_text_inline( 'License key', 'license-key' , $slug );
50 -
51 - $is_network_activation = (
52 - $fs->is_network_active() &&
53 - fs_is_network_admin() &&
54 - ! $fs->is_delegated_connection()
55 - );
56 - $network_activation_html = '';
57 -
58 - $sites_details = array();
59 - if ( $is_network_activation ) {
60 - $all_sites = Freemius::get_sites();
61 -
62 - foreach ( $all_sites as $site ) {
63 - $site_details = $fs->get_site_info( $site );
64 -
65 - $blog_id = Freemius::get_site_blog_id( $site );
66 - $install = $fs->get_install_by_blog_id($blog_id);
67 -
68 - if ( is_object( $install ) && FS_Plugin_License::is_valid_id( $install->license_id ) ) {
69 - $site_details['license_id'] = $install->license_id;
70 - }
71 -
72 - $sites_details[] = $site_details;
73 - }
74 -
75 - if ( $is_network_activation ) {
76 - $vars = array(
77 - 'id' => $fs->get_id(),
78 - 'sites' => $sites_details,
79 - 'require_license_key' => true
80 - );
81 -
82 - $network_activation_html = fs_get_template( 'partials/network-activation.php', $vars );
83 - }
84 - }
85 -
86 - $premium_licenses = $fs->get_available_premium_licenses();
87 - $available_licenses = array();
88 - foreach ( $premium_licenses as $premium_license ) {
89 - $activations_left = $premium_license->left();
90 - if ( ! ( $activations_left > 0 ) ) {
91 - continue;
92 - }
93 -
94 - $available_licenses[ $activations_left . '_' . $premium_license->id ] = $premium_license;
95 - }
96 -
97 - $total_available_licenses = count( $available_licenses );
98 - if ( $total_available_licenses > 0 ) {
99 - $license_input_html = <<< HTML
100 - <div class="fs-license-options-container">
101 - <table>
102 - <tbody>
103 - <tr class="fs-available-license-key-container">
104 - <td><input type="radio" name="license_type" value="available"></td>
105 - <td>
106 -HTML;
107 -
108 - if ( $total_available_licenses > 1 ) {
109 - // Sort the licenses by number of activations left in descending order.
110 - krsort( $available_licenses );
111 -
112 - $license_input_html .= '<select class="fs-licenses">';
113 -
114 - /**
115 - * @var FS_Plugin_License $license
116 - */
117 - foreach ( $available_licenses as $license ) {
118 - $plan = $fs->_get_plan_by_id( $license->plan_id );
119 -
120 - $label = sprintf(
121 - "%s-Site %s License - %s",
122 - ( 1 == $license->quota ?
123 - 'Single' :
124 - ( $license->is_unlimited() ? 'Unlimited' : $license->quota )
125 - ),
126 - ( is_object( $plan ) ? $plan->title : '' ),
127 - $license->get_html_escaped_masked_secret_key()
128 - );
129 -
130 - $license_input_html .= "<option data-id='{$license->id}' value='{$license->secret_key}' data-left='{$license->left()}'>{$label}</option>";
131 - }
132 -
133 - $license_input_html .= '</select>';
134 - } else {
135 - $available_licenses = array_values( $available_licenses );
136 -
137 - /**
138 - * @var FS_Plugin_License $available_license
139 - */
140 - $available_license = $available_licenses[0];
141 - $value = sprintf(
142 - "%s-Site %s License - %s",
143 - ( 1 == $available_license->quota ?
144 - 'Single' :
145 - ( $available_license->is_unlimited() ? 'Unlimited' : $available_license->quota )
146 - ),
147 - $fs->_get_plan_by_id( $available_license->plan_id )->title,
148 - $available_license->get_html_escaped_masked_secret_key()
149 - );
150 -
151 - $license_input_html .= <<< HTML
152 - <input
153 - class="fs-available-license-key"
154 - type="text"
155 - value="{$value}"
156 - data-id="{$available_license->id}"
157 - data-license-key="{$available_license->secret_key}"
158 - data-left="{$available_license->left()}"
159 - readonly />
160 -HTML;
161 - }
162 -
163 - $license_input_html .= <<< HTML
164 - </td>
165 - </tr>
166 - <tr>
167 - <td><input type="radio" name="license_type" value="other"></td>
168 - <td class="fs-other-license-key-container">
169 - <label for="other_license_key_{$unique_affix}">Other: </label>
170 - <div>
171 - <input id="other_license_key_{$unique_affix}" class="fs-license-key" type="text" placeholder="Enter license key" tabindex="1">
172 - </div>
173 - </td>
174 - </tr>
175 - </tbody>
176 - </table>
177 - </div>
178 -HTML;
179 - } else {
180 - $license_input_html = "<input class='fs-license-key' type='text' placeholder='{$license_key_text}' tabindex='1' />";
181 - }
182 -
183 - $ownership_change_option_text = fs_text_inline( "Associate with the license owner's account.", 'associate-account-with-license-owner', $slug );
184 - $ownership_change_option_html = "<div class='ownership-change-option-container' style='display: none'><label><input type='checkbox' /> <strong>{$ownership_change_option_text}</strong></label></div>";
185 -
186 - /**
187 - * IMPORTANT:
188 - * DO NOT ADD MAXLENGTH OR LIMIT THE LICENSE KEY LENGTH SINCE
189 - * WE DO WANT TO ALLOW INPUT OF LONGER KEYS (E.G. WooCommerce Keys)
190 - * FOR MIGRATED MODULES.
191 - */
192 - $modal_content_html = <<< HTML
193 - <div class="notice notice-error inline license-activation-message"><p></p></div>
194 - <p>{$message_above_input_field}</p>
195 - {$license_input_html}
196 - <a class="show-license-resend-modal show-license-resend-modal-{$fs->get_unique_affix()}" href="!#" tabindex="2">{$cant_find_license_key_text}</a>
197 - {$network_activation_html}
198 - <p>{$message_below_input_field}</p>
199 - {$ownership_change_option_html}
200 -HTML;
201 -
202 - /**
203 - * Handle the ownership change option if not an add-on or if no license yet is activated for the
204 - * parent product in case of an add-on.
205 - *
206 - * @author Leo Fajardo (@leorw)
207 - * @since 2.3.2
208 - */
209 - $is_user_change_supported = ( ! $fs->is_addon() || ! $fs->get_parent_instance()->has_active_valid_license() );
210 -
211 - fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
212 -?>
213 -<script type="text/javascript">
214 -(function( $ ) {
215 - $( document ).ready(function() {
216 - var modalContentHtml = <?php echo json_encode($modal_content_html); ?>,
217 - modalHtml =
218 - '<div class="fs-modal fs-modal-license-activation fs-modal-license-activation-<?php echo $unique_affix ?>">'
219 - + ' <div class="fs-modal-dialog">'
220 - + ' <div class="fs-modal-header">'
221 - + ' <h4><?php echo esc_js($header_title) ?></h4>'
222 - + ' <a href="!#" class="fs-close"><i class="dashicons dashicons-no" title="<?php echo esc_js( fs_text_x_inline( 'Dismiss', 'as close a window', 'dismiss', $slug ) ) ?>"></i></a>'
223 - + ' </div>'
224 - + ' <div class="fs-modal-body">'
225 - + ' <div class="fs-modal-panel active">' + modalContentHtml + '</div>'
226 - + ' </div>'
227 - + ' <div class="fs-modal-footer">'
228 - + ' <button class="button button-secondary button-close" tabindex="4"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel', $slug ) ?></button>'
229 - + ' <button class="button button-primary button-activate-license" tabindex="3"><?php echo esc_js( $activate_button_text ) ?></button>'
230 - + ' </div>'
231 - + ' </div>'
232 - + '</div>',
233 - $modal = $(modalHtml),
234 - $activateLicenseButton = $modal.find('.button-activate-license'),
235 - $licenseKeyInput = $modal.find( 'input.fs-license-key' ),
236 - $licenseActivationMessage = $modal.find( '.license-activation-message' ),
237 - isNetworkActivation = <?php echo $is_network_activation ? 'true' : 'false' ?>,
238 - isUserChangeSupported = <?php echo $is_user_change_supported ? 'true' : 'false' ?>,
239 - isSingleSiteActivation = false,
240 - $ownershipChangeOptionContainer = $modal.find( '.ownership-change-option-container' ),
241 - $body = $( 'body' );
242 -
243 - $modal.appendTo( $body );
244 -
245 - var
246 - $licensesDropdown = $modal.find( '.fs-licenses' ),
247 - $licenseTypes = $modal.find( 'input[type="radio"][name="license_type"]' ),
248 - $applyOnAllSites = $modal.find( '.fs-apply-on-all-sites-checkbox' ),
249 - $sitesListContainer = $modal.find( '.fs-sites-list-container' ),
250 - $availableLicenseKey = $modal.find( '.fs-available-license-key' ),
251 - $otherLicenseKey = $modal.find( '#other_license_key_<?php echo $unique_affix ?>' ),
252 - $multisiteOptionsContainer = $modal.find( '.fs-multisite-options-container' ),
253 - $activationsLeft = null,
254 - hasLicensesDropdown = ( $licensesDropdown.length > 0 ),
255 - hasLicenseTypes = ( $licenseTypes.length > 0 ),
256 - maxSitesListHeight = null,
257 - totalSites = <?php echo count( $sites_details ) ?>,
258 - singleBlogID = null;
259 -
260 - var
261 - previousLicenseKey = null,
262 - otherLicenseOwnerID = null,
263 - /**
264 - * @author Leo Fajardo (@leorw)
265 - * @since 2.3.2
266 - */
267 - resetLoadingMode = function () {
268 - // Reset loading mode.
269 - $activateLicenseButton.text( <?php echo json_encode( $activate_button_text ) ?> );
270 - $activateLicenseButton.prop( 'disabled', false );
271 - $( document.body ).css( { 'cursor': 'auto' } );
272 - $( '.fs-loading' ).removeClass( 'fs-loading' );
273 -
274 - console.log( 'resetLoadingMode - Primary button was enabled' );
275 - },
276 - /**
277 - * @author Leo Fajardo (@leorw)
278 - * @since 2.3.2
279 - */
280 - setLoadingMode = function () {
281 - $( document.body ).css( { 'cursor': 'wait' } );
282 - },
283 - /**
284 - * @author Leo Fajardo (@leorw)
285 - * @since 2.3.2
286 - */
287 - afterLicenseUserDataLoaded = function () {
288 - if (
289 - null !== otherLicenseOwnerID &&
290 - otherLicenseOwnerID != <?php echo $fs->is_registered() ? $fs->get_user()->id : 'null' ?>
291 - ) {
292 - $ownershipChangeOptionContainer.show();
293 - } else {
294 - $ownershipChangeOptionContainer.hide();
295 - $activateLicenseButton.focus();
296 - }
297 - },
298 - /**
299 - * @author Leo Fajardo (@leorw)
300 - * @since 2.3.2
301 - */
302 - fetchLicenseUserData = function () {
303 - var hideAndUncheckUserChangeCheckbox = ( ! isUserChangeSupported ),
304 - otherLicenseKeyIsSelected = isOtherLicenseKeySelected();
305 -
306 - if ( ! hideAndUncheckUserChangeCheckbox ) {
307 - // User change is supported only on the site level.
308 - hideAndUncheckUserChangeCheckbox = ( isNetworkActivation || isSingleSiteActivation );
309 - }
310 -
311 - if ( ! hideAndUncheckUserChangeCheckbox ) {
312 - hideAndUncheckUserChangeCheckbox = ( hasLicenseTypes && ! otherLicenseKeyIsSelected );
313 - }
314 -
315 - var licenseKey = $licenseKeyInput.val().trim();
316 -
317 - if ( ! hideAndUncheckUserChangeCheckbox && otherLicenseKeyIsSelected ) {
318 - hideAndUncheckUserChangeCheckbox = ( licenseKey.length < 32 );
319 - }
320 -
321 - if ( licenseKey !== previousLicenseKey ) {
322 - // If the license key has not been changed, keep the owner ID in order to prevent another API call.
323 - otherLicenseOwnerID = null;
324 - }
325 -
326 - if ( hideAndUncheckUserChangeCheckbox ) {
327 - $ownershipChangeOptionContainer.hide().find( 'input' ).attr( 'checked', false );
328 -
329 - return;
330 - }
331 -
332 - if ( null !== otherLicenseOwnerID ) {
333 - afterLicenseUserDataLoaded();
334 - return;
335 - }
336 -
337 - setLoadingMode();
338 -
339 - $activateLicenseButton.addClass( 'fs-loading' );
340 - $activateLicenseButton.attr( 'disabled', 'disabled' );
341 - $activateLicenseButton.html( '<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...' );
342 -
343 - $.ajax( {
344 - url : ajaxurl,
345 - method : 'POST',
346 - data : {
347 - action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
348 - security : '<?php echo $fs->get_ajax_security( 'fetch_is_marketing_required_flag_value' ) ?>',
349 - license_key: licenseKey,
350 - module_id : '<?php echo $fs->get_id() ?>'
351 - },
352 - success: function ( result ) {
353 - resetLoadingMode();
354 -
355 - if ( result.success ) {
356 - result = result.data;
357 -
358 - // Cache license owner's ID.
359 - otherLicenseOwnerID = result.license_owner_id;
360 - }
361 -
362 - afterLicenseUserDataLoaded();
363 - }
364 - } );
365 - };
366 -
367 - function registerEventHandlers() {
368 - var
369 - $otherLicenseKeyContainer = $modal.find( '.fs-other-license-key-container' );
370 -
371 - if ( isNetworkActivation ) {
372 - $applyOnAllSites.click(function() {
373 - var applyOnAllSites = $( this ).is( ':checked' );
374 -
375 - $multisiteOptionsContainer.toggleClass( 'fs-apply-on-all-sites', applyOnAllSites );
376 -
377 - showSites( ! applyOnAllSites );
378 -
379 - if ( hasValidLicenseKey() && ( applyOnAllSites || hasSelectedSite() ) ) {
380 - enableActivateLicenseButton();
381 - } else {
382 - disableActivateLicenseButton();
383 - }
384 - });
385 -
386 - $sitesListContainer.delegate( 'td:not(:first-child)', 'click', function() {
387 - // If a site row is clicked, trigger a click on the checkbox.
388 - $( this ).parent().find( 'td:first-child input' ).click();
389 - });
390 -
391 - $sitesListContainer.delegate( 'input[type="checkbox"]', 'click', function() {
392 - enableDisableSitesSelection();
393 -
394 - if ( hasValidLicenseKey() && hasSelectedSite() ) {
395 - enableActivateLicenseButton();
396 - } else {
397 - disableActivateLicenseButton();
398 - }
399 - });
400 - }
401 -
402 - if ( hasLicensesDropdown ) {
403 - $licensesDropdown.change(function() {
404 - // When a license is selected, select the associated radio button.
405 - $licenseTypes.filter( '[value="available"]' ).attr( 'checked', true );
406 -
407 - if ( ! isNetworkActivation || $modal.hasClass( 'is-single-site-activation' ) ) {
408 - enableActivateLicenseButton();
409 - return true;
410 - }
411 -
412 - toggleActivationOnAllSites();
413 - })
414 - }
415 -
416 - if ( hasLicenseTypes ) {
417 - $licenseTypes.change(function() {
418 - var
419 - licenseKey = $modal.find( 'input.fs-license-key' ).val().trim(),
420 - otherLicenseKeySelected = isOtherLicenseKeySelected();
421 -
422 - if ( ( licenseKey.length > 0 || ( hasLicenseTypes && ! otherLicenseKeySelected ) ) &&
423 - ( $modal.hasClass( 'is-single-site-activation' ) || ! isNetworkActivation || hasSelectedSite() )
424 - ) {
425 - /**
426 - * If the "other" license is not empty or an available license is selected, enable the activate
427 - * button.
428 - *
429 - * @author Leo Fajardo (@leorw)
430 - */
431 - enableActivateLicenseButton();
432 - } else {
433 - disableActivateLicenseButton();
434 - }
435 -
436 - if ( '' !== licenseKey ) {
437 - fetchLicenseUserData();
438 - }
439 -
440 - if ( ! isNetworkActivation ) {
441 - return;
442 - }
443 -
444 - if ( otherLicenseKeySelected ) {
445 - $applyOnAllSites.attr( 'disabled', false );
446 - enableDisableSitesSelection();
447 - resetActivateLicenseCheckboxLabel();
448 - } else if ( ! $modal.hasClass( 'is-single-site-activation' ) ) {
449 - toggleActivationOnAllSites();
450 - }
451 - });
452 -
453 - if ( ! hasLicensesDropdown ) {
454 - $availableLicenseKey.click(function() {
455 - $licenseTypes.filter( '[value="available"]' ).click();
456 - });
457 - }
458 -
459 - $otherLicenseKeyContainer.click(function() {
460 - $licenseTypes.filter( '[value="other"]' ).click();
461 - });
462 - }
463 -
464 - $body.on( 'click', 'span.activate-license.<?php echo $unique_affix ?> a, .activate-license-trigger.<?php echo $unique_affix ?>', function (evt) {
465 - evt.preventDefault();
466 -
467 - showModal( evt );
468 - });
469 -
470 - var licenseTimeout = null;
471 -
472 - /**
473 - * Disable activation button when license key is empty.
474 - *
475 - * @author Leo Fajardo (@leorw)
476 - * @since 2.3.2
477 - */
478 - $modal.on( 'keyup paste delete cut', 'input.fs-license-key', function () {
479 - clearTimeout(licenseTimeout);
480 -
481 - licenseTimeout = setTimeout( function () {
482 - var licenseKey = $licenseKeyInput.val().trim();
483 -
484 - if ( licenseKey == previousLicenseKey ) {
485 - afterLicenseUserDataLoaded();
486 - return;
487 - }
488 -
489 - if ( '' === licenseKey ) {
490 - disableActivateLicenseButton();
491 - $ownershipChangeOptionContainer.hide();
492 - } else {
493 - enableActivateLicenseButton();
494 -
495 - if ( 32 <= licenseKey.length ) {
496 - fetchLicenseUserData();
497 - } else {
498 - $ownershipChangeOptionContainer.hide();
499 - }
500 - }
501 -
502 - previousLicenseKey = licenseKey;
503 - }, 200 );
504 - } ).focus();
505 -
506 - $modal.on('input propertychange', 'input.fs-license-key', function () {
507 -
508 - var licenseKey = $(this).val().trim();
509 -
510 - /**
511 - * If license key is not empty, enable the license activation button.
512 - */
513 - if ( licenseKey.length > 0 && ( $modal.hasClass( 'is-single-site-activation' ) || ! isNetworkActivation || hasSelectedSite() ) ) {
514 - enableActivateLicenseButton();
515 - }
516 - });
517 -
518 - $modal.on( 'blur', 'input.fs-license-key', function( evt ) {
519 - var
520 - licenseKey = $(this).val().trim(),
521 - $focusedElement = $( evt.relatedTarget ),
522 - hasSelectedAvailableLicense = ( hasLicenseTypes && $focusedElement.parents( '.fs-available-license-key-container' ).length > 0 );
523 -
524 - /**
525 - * If license key is empty, disable the license activation button.
526 - */
527 - if ( ( 0 === licenseKey.length && ( ! hasLicenseTypes || ! hasSelectedAvailableLicense ) ) ||
528 - ( isNetworkActivation && ! hasSelectedSite() )
529 - ) {
530 - disableActivateLicenseButton();
531 - }
532 - });
533 -
534 - $modal.on('click', '.button-activate-license', function (evt) {
535 - evt.preventDefault();
536 -
537 - if ($(this).hasClass('disabled')) {
538 - return;
539 - }
540 -
541 - var
542 - licenseKey = '';
543 -
544 - if ( hasLicenseTypes ) {
545 - if ( isOtherLicenseKeySelected() ) {
546 - licenseKey = $otherLicenseKey.val();
547 - } else {
548 - if ( ! hasLicensesDropdown ) {
549 - licenseKey = $availableLicenseKey.data( 'license-key' );
550 - } else {
551 - licenseKey = $licensesDropdown.val();
552 - }
553 - }
554 - } else {
555 - licenseKey = $licenseKeyInput.val().trim();
556 - }
557 -
558 - disableActivateLicenseButton();
559 -
560 - if (0 === licenseKey.length) {
561 - return;
562 - }
563 -
564 - var data = {
565 - action : '<?php echo $fs->get_ajax_action( 'activate_license' ) ?>',
566 - security : '<?php echo $fs->get_ajax_security( 'activate_license' ) ?>',
567 - license_key: licenseKey,
568 - module_id : '<?php echo $fs->get_id() ?>'
569 - };
570 -
571 - if ( isNetworkActivation ) {
572 - var
573 - sites = [];
574 -
575 - if ( null === singleBlogID ) {
576 - var
577 - applyOnAllSites = $applyOnAllSites.is( ':checked' );
578 -
579 - $sitesListContainer.find( 'tr' ).each(function() {
580 - var
581 - $this = $( this ),
582 - includeSite = ( applyOnAllSites || $this.find( 'input' ).is( ':checked' ) );
583 -
584 - if ( ! includeSite )
585 - return;
586 -
587 - var site = {
588 - uid : $this.find( '.uid' ).val(),
589 - url : $this.find( '.url' ).val(),
590 - title : $this.find( '.title' ).val(),
591 - language: $this.find( '.language' ).val(),
592 - charset : $this.find( '.charset' ).val(),
593 - blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
594 - };
595 -
596 - sites.push( site );
597 - });
598 - } else {
599 - data.blog_id = singleBlogID;
600 - }
601 -
602 - data.sites = sites;
603 - }
604 -
605 - if ( $ownershipChangeOptionContainer.find( 'input:checked' ).length > 0 ) {
606 - data.user_id = otherLicenseOwnerID;
607 - }
608 -
609 - $.ajax({
610 - url: ajaxurl,
611 - method: 'POST',
612 - data: data,
613 - beforeSend: function () {
614 - $activateLicenseButton.text( '<?php fs_esc_js_echo_inline( 'Activating license', 'activating-license', $slug ) ?>...' );
615 - },
616 - success: function( result ) {
617 - var resultObj = $.parseJSON( result );
618 - if ( resultObj.success ) {
619 - closeModal();
620 -
621 - // Redirect to the "Account" page and sync the license.
622 - window.location.href = resultObj.next_page;
623 - } else {
624 - showError( resultObj.error.message ? resultObj.error.message : resultObj.error );
625 - resetActivateLicenseButton();
626 - }
627 - }
628 - });
629 - });
630 -
631 - // If the user has clicked outside the window, close the modal.
632 - $modal.on('click', '.fs-close, .button-secondary', function () {
633 - closeModal();
634 - return false;
635 - });
636 - }
637 -
638 - registerEventHandlers();
639 -
640 - $body.trigger('licenseActivationLoaded');
641 -
642 - /**
643 - * @author Leo Fajardo (@leorw)
644 - * @since 2.0.0
645 - */
646 - function enableDisableSitesSelection() {
647 - var
648 - canApplyOnAllSites = $applyOnAllSites.is( ':enabled' ),
649 - disableSitesSelection = null;
650 -
651 - if ( ! canApplyOnAllSites ) {
652 - var
653 - selectedSites = $sitesListContainer.find( 'input[type="checkbox"]:checked' ).length,
654 - activationsLeft = Math.max( 0, $activationsLeft.data( 'left' ) - selectedSites );
655 -
656 - disableSitesSelection = ( 0 === activationsLeft );
657 -
658 - $activationsLeft.text( activationsLeft );
659 - } else {
660 - disableSitesSelection = false;
661 - }
662 -
663 - $sitesListContainer
664 - .find( 'input[type="checkbox"]:not(:checked)' )
665 - .attr( 'disabled', disableSitesSelection );
666 - }
667 -
668 - /**
669 - * @author Leo Fajardo (@leorw)
670 - * @since 2.0.0
671 - *
672 - * @returns {Boolean}
673 - */
674 - function isOtherLicenseKeySelected() {
675 - return ( hasLicenseTypes && 'other' === $licenseTypes.filter( ':checked' ).val() );
676 - }
677 -
678 - /**
679 - * @author Leo Fajardo (@leorw)
680 - * @since 2.0.0
681 - *
682 - * @returns {Boolean}
683 - */
684 - function hasValidLicenseKey() {
685 - var licenseKey = '';
686 - if ( hasLicenseTypes ) {
687 - if ( 'available' === $licenseTypes.filter( ':checked' ).val() ) {
688 - return true;
689 - } else {
690 - licenseKey = $otherLicenseKey.val();
691 - }
692 - } else {
693 - licenseKey = $modal.find( 'input.fs-license-key' ).val();
694 - }
695 -
696 - return ( licenseKey.trim().length > 0 );
697 - }
698 -
699 - /**
700 - * @author Leo Fajardo (@leorw)
701 - * @since 2.0.0
702 - *
703 - * @returns {Boolean}
704 - */
705 - function hasSelectedSite() {
706 - return ( $applyOnAllSites.is( ':checked' ) ||
707 - $sitesListContainer.find( 'input[type="checkbox"]:checked:not(:disabled)' ).length > 0 );
708 - }
709 -
710 - /**
711 - * @author Leo Fajardo (@leorw)
712 - * @since 2.0.0
713 - */
714 - function toggleActivationOnAllSites() {
715 - var activationsLeft,
716 - licenseID;
717 -
718 - if (hasLicensesDropdown) {
719 - var $selectedOption = $licensesDropdown.find( ':selected' );
720 - activationsLeft = $selectedOption.data('left');
721 - licenseID = $selectedOption.data('id');
722 - } else {
723 - activationsLeft = $availableLicenseKey.data('left');
724 - licenseID = $availableLicenseKey.data('id');
725 - }
726 -
727 - // Cleanup previously auto-selected site.
728 - $modal.find( '.fs-sites-list-container input[type=checkbox]:disabled' )
729 - .attr('disabled', false)
730 - .attr('checked', false);
731 -
732 - var $blogsWithActiveLicense = $modal.find( '.fs-sites-list-container tr[data-license-id=' + licenseID + '] input[type=checkbox]' );
733 -
734 - if ($blogsWithActiveLicense.length > 0) {
735 - $blogsWithActiveLicense.attr('checked', true)
736 - .attr('disabled', true);
737 -
738 - activationsLeft += $blogsWithActiveLicense.length;
739 - }
740 -
741 - if ( activationsLeft >= totalSites ) {
742 - $applyOnAllSites.attr( 'disabled', false );
743 - enableDisableSitesSelection();
744 -
745 - resetActivateLicenseCheckboxLabel();
746 -
747 - return;
748 - }
749 -
750 - $applyOnAllSites.attr( 'checked', false );
751 - $applyOnAllSites.attr( 'disabled', true );
752 -
753 - showSites( true );
754 -
755 - var
756 - activateLicenseCheckboxLabel = '<?php fs_esc_js_echo_inline( 'Choose up to %s site(s) to activate the license on.', 'choose-up-to-n-sites-to-activate-the-license-on', $slug ) ?>';
757 -
758 - activateLicenseCheckboxLabel = activateLicenseCheckboxLabel.replace( '%s', '<span data-left="' + activationsLeft + '" class="activations-left">' + activationsLeft + '</span>' );
759 -
760 - // Update the label of the "Activate license on all sites" checkbox.
761 - $applyOnAllSites.parent().find( 'span' ).html( activateLicenseCheckboxLabel );
762 - $activationsLeft = $modal.find( '.activations-left' );
763 -
764 - if ( hasSelectedSite() ) {
765 - enableActivateLicenseButton();
766 - enableDisableSitesSelection();
767 - } else {
768 - disableActivateLicenseButton();
769 - }
770 - }
771 -
772 - /**
773 - * @author Leo Fajardo (@leorw)
774 - * @since 2.0.0
775 - */
776 - function resetActivateLicenseCheckboxLabel() {
777 - var activateLicenseCheckboxLabel = '<?php fs_esc_js_echo_inline( 'Activate license on all sites in the network.', 'activate-license-on-all-sites-in-the-network', $slug ) ?>';
778 - $applyOnAllSites.parent().find( 'span' ).text( activateLicenseCheckboxLabel );
779 - }
780 -
781 - /**
782 - * @author Leo Fajardo (@leorw)
783 - * @since 2.0.0
784 - *
785 - * @param {Boolean} show
786 - */
787 - function showSites( show ) {
788 - $sitesListContainer.toggle( show );
789 - if ( show && null === maxSitesListHeight ) {
790 - /**
791 - * Set the visible number of rows to 5 (5 * height of the first row).
792 - *
793 - * @author Leo Fajardo (@leorw)
794 - */
795 - maxSitesListHeight = ( 5 * $sitesListContainer.find( 'tr:first' ).height() );
796 - $sitesListContainer.css( 'max-height', maxSitesListHeight );
797 - }
798 - }
799 -
800 - function showModal( evt ) {
801 - resetModal();
802 -
803 - // Display the dialog box.
804 - $modal.addClass('active');
805 - $body.addClass('has-fs-modal');
806 -
807 - var
808 - $singleInstallDetails = $( evt.target ).parents( 'tr.fs-install-details' ),
809 - isSingleSiteActivation = ( $singleInstallDetails.length > 0 );
810 -
811 - $modal.toggleClass( 'is-single-site-activation', isSingleSiteActivation );
812 -
813 - singleBlogID = isSingleSiteActivation ?
814 - $singleInstallDetails.prev().data( 'blog-id' ) :
815 - null;
816 -
817 - <?php if ( $fs->apply_filters( 'enable_per_site_activation', true ) ) : ?>
818 - $multisiteOptionsContainer.toggle( isNetworkActivation && ! isSingleSiteActivation );
819 - <?php endif ?>
820 -
821 - if ( hasLicenseTypes ) {
822 - $licenseTypes.attr( 'checked', false );
823 -
824 - if ( hasLicensesDropdown ) {
825 - $licensesDropdown.find( 'option:first' ).attr( 'selected', true ).trigger( 'change' );
826 - } else {
827 - $licenseTypes.filter( '[value="available"]' ).click();
828 - }
829 -
830 - $otherLicenseKey.val( '' );
831 - } else {
832 - $licenseKeyInput.val( '' );
833 - $licenseKeyInput.focus();
834 - }
835 - }
836 -
837 - function closeModal() {
838 - $modal.removeClass('active');
839 - $body.removeClass('has-fs-modal');
840 - }
841 -
842 - function resetActivateLicenseButton() {
843 - enableActivateLicenseButton();
844 - $activateLicenseButton.text( <?php echo json_encode( $activate_button_text ) ?> );
845 - }
846 -
847 - function resetModal() {
848 - hideError();
849 - resetActivateLicenseButton();
850 - }
851 -
852 - function enableActivateLicenseButton() {
853 - $activateLicenseButton.removeClass( 'disabled' );
854 - }
855 -
856 - function disableActivateLicenseButton() {
857 - $activateLicenseButton.addClass( 'disabled' );
858 - }
859 -
860 - function hideError() {
861 - $licenseActivationMessage.hide();
862 - }
863 -
864 - function showError( msg ) {
865 - $licenseActivationMessage.find( ' > p' ).html( msg );
866 - $licenseActivationMessage.show();
867 - }
868 - });
869 -})( jQuery );
870 -</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.9
7 + */
8 +
9 + if ( ! defined( 'ABSPATH' ) ) {
10 + exit;
11 + }
12 +
13 + /**
14 + * @var array $VARS
15 + *
16 + * @var Freemius $fs
17 + */
18 + $fs = freemius( $VARS['id'] );
19 + $slug = $fs->get_slug();
20 + $unique_affix = $fs->get_unique_affix();
21 +
22 + $cant_find_license_key_text = fs_text_inline( "Can't find your license key?", 'cant-find-license-key', $slug );
23 + $message_above_input_field = fs_text_inline( 'Please enter the license key that you received in the email right after the purchase:', 'activate-license-message', $slug );
24 + $message_below_input_field = '';
25 +
26 + $header_title = $fs->is_free_plan() ?
27 + fs_text_inline( 'Activate License', 'activate-license', $slug ) :
28 + fs_text_inline( 'Update License', 'update-license', $slug );
29 +
30 + if ( $fs->is_registered() ) {
31 + $activate_button_text = $header_title;
32 + } else {
33 + $message_below_input_field = sprintf(
34 + fs_text_inline( 'The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.', 'license-sync-disclaimer', $slug ),
35 + $fs->get_module_label( true ),
36 + "<b>{$fs->get_plugin_title()}</b>"
37 + );
38 +
39 + $activate_button_text = fs_text_inline( 'Agree & Activate License', 'agree-activate-license', $slug );
40 + }
41 +
42 + $license_key_text = fs_text_inline( 'License key', 'license-key' , $slug );
43 +
44 + $is_network_activation = (
45 + $fs->is_network_active() &&
46 + fs_is_network_admin() &&
47 + ! $fs->is_delegated_connection()
48 + );
49 + $network_activation_html = '';
50 +
51 + $sites_details = array();
52 + if ( $is_network_activation ) {
53 + $all_sites = Freemius::get_sites();
54 +
55 + $all_site_details = array();
56 + $subsite_url_by_install_id = array();
57 + $install_url_by_install_id = array();
58 +
59 + foreach ( $all_sites as $site ) {
60 + $site_details = $fs->get_site_info( $site );
61 +
62 + if ( FS_Clone_Manager::instance()->is_temporary_duplicate_by_blog_id( $site_details['blog_id'] ) ) {
63 + continue;
64 + }
65 +
66 + $blog_id = Freemius::get_site_blog_id( $site );
67 + $install = $fs->get_install_by_blog_id($blog_id);
68 +
69 + if ( is_object( $install ) ) {
70 + if ( isset( $subsite_url_by_install_id[ $install->id ] ) ) {
71 + $clone_subsite_url = $subsite_url_by_install_id[ $install->id ];
72 + $clone_install_url = $install_url_by_install_id[ $install->id ];
73 +
74 + if (
75 + /**
76 + * If we already have an install with the same URL as the subsite it's stored in, skip the current subsite. Otherwise, replace the existing install's data with the current subsite's install's data if the URLs match.
77 + *
78 + * @author Leo Fajardo (@leorw)
79 + * @since 2.5.0
80 + */
81 + fs_strip_url_protocol( untrailingslashit( $clone_install_url ) ) === fs_strip_url_protocol( untrailingslashit( $clone_subsite_url ) ) ||
82 + fs_strip_url_protocol( untrailingslashit( $install->url ) ) !== fs_strip_url_protocol( untrailingslashit( $site_details['url'] ) )
83 + ) {
84 + continue;
85 + }
86 + }
87 +
88 + if ( FS_Plugin_License::is_valid_id( $install->license_id ) ) {
89 + $site_details['license_id'] = $install->license_id;
90 + }
91 +
92 + $subsite_url_by_install_id[ $install->id ] = $site_details['url'];
93 + $install_url_by_install_id[ $install->id ] = $install->url;
94 + }
95 +
96 + $all_site_details[] = $site_details;
97 + }
98 +
99 + if ( $is_network_activation ) {
100 + $vars = array(
101 + 'id' => $fs->get_id(),
102 + 'sites' => $all_site_details,
103 + 'require_license_key' => true
104 + );
105 +
106 + $network_activation_html = fs_get_template( 'partials/network-activation.php', $vars );
107 + }
108 + }
109 +
110 + $premium_licenses = $fs->get_available_premium_licenses();
111 + $available_licenses = array();
112 + foreach ( $premium_licenses as $premium_license ) {
113 + $activations_left = $premium_license->left();
114 + if ( ! ( $activations_left > 0 ) ) {
115 + continue;
116 + }
117 +
118 + $available_licenses[ $activations_left . '_' . $premium_license->id ] = $premium_license;
119 + }
120 +
121 + $total_available_licenses = count( $available_licenses );
122 + if ( $total_available_licenses > 0 ) {
123 + $license_input_html = <<< HTML
124 + <div class="fs-license-options-container">
125 + <table>
126 + <tbody>
127 + <tr class="fs-available-license-key-container">
128 + <td><input type="radio" name="license_type" value="available"></td>
129 + <td>
130 +HTML;
131 +
132 + if ( $total_available_licenses > 1 ) {
133 + // Sort the licenses by number of activations left in descending order.
134 + krsort( $available_licenses );
135 +
136 + $license_input_html .= '<select class="fs-licenses">';
137 +
138 + /**
139 + * @var FS_Plugin_License $license
140 + */
141 + foreach ( $available_licenses as $license ) {
142 + $plan = $fs->_get_plan_by_id( $license->plan_id );
143 +
144 + $label = sprintf(
145 + "%s-Site %s License - %s",
146 + ( 1 == $license->quota ?
147 + 'Single' :
148 + ( $license->is_unlimited() ? 'Unlimited' : $license->quota )
149 + ),
150 + ( is_object( $plan ) ? $plan->title : '' ),
151 + $license->get_html_escaped_masked_secret_key()
152 + );
153 +
154 + $license_input_html .= "<option data-id='{$license->id}' value='{$license->id}' data-left='{$license->left()}'>{$label}</option>";
155 + }
156 +
157 + $license_input_html .= '</select>';
158 + } else {
159 + $available_licenses = array_values( $available_licenses );
160 +
161 + /**
162 + * @var FS_Plugin_License $available_license
163 + */
164 + $available_license = $available_licenses[0];
165 + $value = sprintf(
166 + "%s-Site %s License - %s",
167 + ( 1 == $available_license->quota ?
168 + 'Single' :
169 + ( $available_license->is_unlimited() ? 'Unlimited' : $available_license->quota )
170 + ),
171 + $fs->_get_plan_by_id( $available_license->plan_id )->title,
172 + $available_license->get_html_escaped_masked_secret_key()
173 + );
174 +
175 + $license_input_html .= <<< HTML
176 + <input
177 + class="fs-available-license-key"
178 + type="text"
179 + value="{$value}"
180 + data-id="{$available_license->id}"
181 + data-left="{$available_license->left()}"
182 + readonly />
183 +HTML;
184 + }
185 +
186 + $license_input_html .= <<< HTML
187 + </td>
188 + </tr>
189 + <tr>
190 + <td><input type="radio" name="license_type" value="other"></td>
191 + <td class="fs-other-license-key-container">
192 + <label for="other_license_key_{$unique_affix}">Other: </label>
193 + <div>
194 + <input id="other_license_key_{$unique_affix}" class="fs-license-key" type="text" placeholder="Enter license key" tabindex="1">
195 + </div>
196 + </td>
197 + </tr>
198 + </tbody>
199 + </table>
200 + </div>
201 +HTML;
202 + } else {
203 + $license_input_html = "<input class='fs-license-key' type='text' placeholder='{$license_key_text}' tabindex='1' />";
204 + }
205 +
206 + $ownership_change_option_text = fs_text_inline( "Associate with the license owner's account.", 'associate-account-with-license-owner', $slug );
207 + $ownership_change_option_html = "<div class='ownership-change-option-container' style='display: none'><label><input type='checkbox' /> <strong>{$ownership_change_option_text}</strong></label></div>";
208 +
209 + /**
210 + * IMPORTANT:
211 + * DO NOT ADD MAXLENGTH OR LIMIT THE LICENSE KEY LENGTH SINCE
212 + * WE DO WANT TO ALLOW INPUT OF LONGER KEYS (E.G. WooCommerce Keys)
213 + * FOR MIGRATED MODULES.
214 + */
215 + $modal_content_html = <<< HTML
216 + <div class="notice notice-error inline license-activation-message"><p></p></div>
217 + <p>{$message_above_input_field}</p>
218 + {$license_input_html}
219 + <a class="show-license-resend-modal show-license-resend-modal-{$fs->get_unique_affix()}" href="!#" tabindex="2">{$cant_find_license_key_text}</a>
220 + {$network_activation_html}
221 + <p>{$message_below_input_field}</p>
222 + {$ownership_change_option_html}
223 +HTML;
224 +
225 + /**
226 + * Handle the ownership change option if not an add-on or if no license yet is activated for the
227 + * parent product in case of an add-on.
228 + *
229 + * @author Leo Fajardo (@leorw)
230 + * @since 2.3.2
231 + */
232 + $is_user_change_supported = ( ! $fs->is_addon() || ! $fs->get_parent_instance()->has_active_valid_license() );
233 +
234 + fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
235 +?>
236 +<script type="text/javascript">
237 +(function( $ ) {
238 + $( document ).ready(function() {
239 + var modalContentHtml = <?php echo json_encode($modal_content_html); ?>,
240 + modalHtml =
241 + '<div class="fs-modal fs-modal-license-activation fs-modal-license-activation-<?php echo $unique_affix ?>">'
242 + + ' <div class="fs-modal-dialog">'
243 + + ' <div class="fs-modal-header">'
244 + + ' <h4><?php echo esc_js($header_title) ?></h4>'
245 + + ' <a href="!#" class="fs-close"><i class="dashicons dashicons-no" title="<?php echo esc_js( fs_text_x_inline( 'Dismiss', 'as close a window', 'dismiss', $slug ) ) ?>"></i></a>'
246 + + ' </div>'
247 + + ' <div class="fs-modal-body">'
248 + + ' <div class="fs-modal-panel active">' + modalContentHtml + '</div>'
249 + + ' </div>'
250 + + ' <div class="fs-modal-footer">'
251 + + ' <button class="button button-secondary button-close" tabindex="4"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel', $slug ) ?></button>'
252 + + ' <button class="button button-primary button-activate-license" tabindex="3"><?php echo esc_js( $activate_button_text ) ?></button>'
253 + + ' </div>'
254 + + ' </div>'
255 + + '</div>',
256 + $modal = $(modalHtml),
257 + $activateLicenseButton = $modal.find('.button-activate-license'),
258 + $licenseKeyInput = $modal.find( 'input.fs-license-key' ),
259 + $licenseActivationMessage = $modal.find( '.license-activation-message' ),
260 + isNetworkActivation = <?php echo $is_network_activation ? 'true' : 'false' ?>,
261 + isUserChangeSupported = <?php echo $is_user_change_supported ? 'true' : 'false' ?>,
262 + isSingleSiteActivation = false,
263 + $ownershipChangeOptionContainer = $modal.find( '.ownership-change-option-container' ),
264 + $body = $( 'body' );
265 +
266 + $modal.appendTo( $body );
267 +
268 + var
269 + $licensesDropdown = $modal.find( '.fs-licenses' ),
270 + $licenseTypes = $modal.find( 'input[type="radio"][name="license_type"]' ),
271 + $applyOnAllSites = $modal.find( '.fs-apply-on-all-sites-checkbox' ),
272 + $sitesListContainer = $modal.find( '.fs-sites-list-container' ),
273 + $availableLicenseKey = $modal.find( '.fs-available-license-key' ),
274 + $otherLicenseKey = $modal.find( '#other_license_key_<?php echo $unique_affix ?>' ),
275 + $multisiteOptionsContainer = $modal.find( '.fs-multisite-options-container' ),
276 + $activationsLeft = null,
277 + hasLicensesDropdown = ( $licensesDropdown.length > 0 ),
278 + hasLicenseTypes = ( $licenseTypes.length > 0 ),
279 + maxSitesListHeight = null,
280 + totalSites = <?php echo count( $sites_details ) ?>,
281 + singleBlogID = null;
282 +
283 + var
284 + previousLicenseKey = null,
285 + otherLicenseOwnerID = null,
286 + /**
287 + * @author Leo Fajardo (@leorw)
288 + * @since 2.3.2
289 + */
290 + resetLoadingMode = function () {
291 + // Reset loading mode.
292 + $activateLicenseButton.text( <?php echo json_encode( $activate_button_text ) ?> );
293 + $activateLicenseButton.prop( 'disabled', false );
294 + $( document.body ).css( { 'cursor': 'auto' } );
295 + $( '.fs-loading' ).removeClass( 'fs-loading' );
296 +
297 + console.log( 'resetLoadingMode - Primary button was enabled' );
298 + },
299 + /**
300 + * @author Leo Fajardo (@leorw)
301 + * @since 2.3.2
302 + */
303 + setLoadingMode = function () {
304 + $( document.body ).css( { 'cursor': 'wait' } );
305 + },
306 + /**
307 + * @author Leo Fajardo (@leorw)
308 + * @since 2.3.2
309 + */
310 + afterLicenseUserDataLoaded = function () {
311 + if (
312 + false !== otherLicenseOwnerID &&
313 + null !== otherLicenseOwnerID &&
314 + otherLicenseOwnerID != <?php echo $fs->is_registered() ? $fs->get_user()->id : 'null' ?>
315 + ) {
316 + $ownershipChangeOptionContainer.show();
317 + } else {
318 + $ownershipChangeOptionContainer.hide();
319 + $activateLicenseButton.focus();
320 + }
321 + },
322 + /**
323 + * @author Leo Fajardo (@leorw)
324 + * @since 2.3.2
325 + */
326 + fetchLicenseUserData = function () {
327 + var hideAndUncheckUserChangeCheckbox = ( ! isUserChangeSupported ),
328 + otherLicenseKeyIsSelected = isOtherLicenseKeySelected();
329 +
330 + if ( ! hideAndUncheckUserChangeCheckbox ) {
331 + // User change is supported only on the site level.
332 + hideAndUncheckUserChangeCheckbox = ( isNetworkActivation || isSingleSiteActivation );
333 + }
334 +
335 + if ( ! hideAndUncheckUserChangeCheckbox ) {
336 + hideAndUncheckUserChangeCheckbox = ( hasLicenseTypes && ! otherLicenseKeyIsSelected );
337 + }
338 +
339 + var licenseKey = $licenseKeyInput.val().trim();
340 +
341 + if ( ! hideAndUncheckUserChangeCheckbox && otherLicenseKeyIsSelected ) {
342 + hideAndUncheckUserChangeCheckbox = ( licenseKey.length < 32 );
343 + }
344 +
345 + if ( licenseKey !== previousLicenseKey ) {
346 + // If the license key has not been changed, keep the owner ID in order to prevent another API call.
347 + otherLicenseOwnerID = null;
348 + }
349 +
350 + if ( hideAndUncheckUserChangeCheckbox ) {
351 + $ownershipChangeOptionContainer.hide().find( 'input' ).attr( 'checked', false );
352 +
353 + return;
354 + }
355 +
356 + if ( null !== otherLicenseOwnerID ) {
357 + afterLicenseUserDataLoaded();
358 + return;
359 + }
360 +
361 + setLoadingMode();
362 +
363 + $activateLicenseButton.addClass( 'fs-loading' );
364 + $activateLicenseButton.attr( 'disabled', 'disabled' );
365 + $activateLicenseButton.html( '<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...' );
366 +
367 + $.ajax( {
368 + url : <?php echo Freemius::ajax_url() ?>,
369 + method : 'POST',
370 + data : {
371 + action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
372 + security : '<?php echo $fs->get_ajax_security( 'fetch_is_marketing_required_flag_value' ) ?>',
373 + license_key: licenseKey,
374 + module_id : '<?php echo $fs->get_id() ?>'
375 + },
376 + success: function ( result ) {
377 + resetLoadingMode();
378 +
379 + if ( result.success ) {
380 + result = result.data;
381 +
382 + // Cache license owner's ID.
383 + otherLicenseOwnerID = result.license_owner_id;
384 + }
385 +
386 + afterLicenseUserDataLoaded();
387 + }
388 + } );
389 + };
390 +
391 + function registerEventHandlers() {
392 + var
393 + $otherLicenseKeyContainer = $modal.find( '.fs-other-license-key-container' );
394 +
395 + if ( isNetworkActivation ) {
396 + $applyOnAllSites.click(function() {
397 + var applyOnAllSites = $( this ).is( ':checked' );
398 +
399 + $multisiteOptionsContainer.toggleClass( 'fs-apply-on-all-sites', applyOnAllSites );
400 +
401 + showSites( ! applyOnAllSites );
402 +
403 + if ( hasValidLicenseKey() && ( applyOnAllSites || hasSelectedSite() ) ) {
404 + enableActivateLicenseButton();
405 + } else {
406 + disableActivateLicenseButton();
407 + }
408 + });
409 +
410 + $sitesListContainer.delegate( 'td:not(:first-child)', 'click', function() {
411 + // If a site row is clicked, trigger a click on the checkbox.
412 + $( this ).parent().find( 'td:first-child input' ).click();
413 + });
414 +
415 + $sitesListContainer.delegate( 'input[type="checkbox"]', 'click', function() {
416 + enableDisableSitesSelection();
417 +
418 + if ( hasValidLicenseKey() && hasSelectedSite() ) {
419 + enableActivateLicenseButton();
420 + } else {
421 + disableActivateLicenseButton();
422 + }
423 + });
424 + }
425 +
426 + if ( hasLicensesDropdown ) {
427 + $licensesDropdown.change(function() {
428 + // When a license is selected, select the associated radio button.
429 + $licenseTypes.filter( '[value="available"]' ).attr( 'checked', true );
430 +
431 + if ( ! isNetworkActivation || $modal.hasClass( 'is-single-site-activation' ) ) {
432 + enableActivateLicenseButton();
433 + return true;
434 + }
435 +
436 + toggleActivationOnAllSites();
437 + })
438 + }
439 +
440 + if ( hasLicenseTypes ) {
441 + $licenseTypes.change(function() {
442 + var
443 + licenseKey = $modal.find( 'input.fs-license-key' ).val().trim(),
444 + otherLicenseKeySelected = isOtherLicenseKeySelected();
445 +
446 + if ( ( licenseKey.length > 0 || ( hasLicenseTypes && ! otherLicenseKeySelected ) ) &&
447 + ( $modal.hasClass( 'is-single-site-activation' ) || ! isNetworkActivation || hasSelectedSite() )
448 + ) {
449 + /**
450 + * If the "other" license is not empty or an available license is selected, enable the activate
451 + * button.
452 + *
453 + * @author Leo Fajardo (@leorw)
454 + */
455 + enableActivateLicenseButton();
456 + } else {
457 + disableActivateLicenseButton();
458 + }
459 +
460 + if ( '' !== licenseKey ) {
461 + fetchLicenseUserData();
462 + }
463 +
464 + if ( ! isNetworkActivation ) {
465 + return;
466 + }
467 +
468 + if ( otherLicenseKeySelected ) {
469 + $applyOnAllSites.attr( 'disabled', false );
470 + enableDisableSitesSelection();
471 + resetActivateLicenseCheckboxLabel();
472 + } else if ( ! $modal.hasClass( 'is-single-site-activation' ) ) {
473 + toggleActivationOnAllSites();
474 + }
475 + });
476 +
477 + if ( ! hasLicensesDropdown ) {
478 + $availableLicenseKey.click(function() {
479 + $licenseTypes.filter( '[value="available"]' ).click();
480 + });
481 + }
482 +
483 + $otherLicenseKeyContainer.click(function() {
484 + $licenseTypes.filter( '[value="other"]' ).click();
485 + });
486 + }
487 +
488 + $body.on( 'click', 'span.activate-license.<?php echo $unique_affix ?> a, .activate-license-trigger.<?php echo $unique_affix ?>', function (evt) {
489 + evt.preventDefault();
490 +
491 + showModal( evt );
492 + });
493 +
494 + var licenseTimeout = null;
495 +
496 + /**
497 + * Disable activation button when license key is empty.
498 + *
499 + * @author Leo Fajardo (@leorw)
500 + * @since 2.3.2
501 + */
502 + $modal.on( 'keyup paste delete cut', 'input.fs-license-key', function () {
503 + clearTimeout(licenseTimeout);
504 +
505 + licenseTimeout = setTimeout( function () {
506 + var licenseKey = $licenseKeyInput.val().trim();
507 +
508 + if ( licenseKey == previousLicenseKey ) {
509 + afterLicenseUserDataLoaded();
510 + return;
511 + }
512 +
513 + if ( '' === licenseKey ) {
514 + disableActivateLicenseButton();
515 + $ownershipChangeOptionContainer.hide();
516 + } else {
517 + enableActivateLicenseButton();
518 +
519 + if ( 32 <= licenseKey.length ) {
520 + fetchLicenseUserData();
521 + } else {
522 + $ownershipChangeOptionContainer.hide();
523 + }
524 + }
525 +
526 + previousLicenseKey = licenseKey;
527 + }, 200 );
528 + } ).focus();
529 +
530 + $modal.on('input propertychange', 'input.fs-license-key', function () {
531 +
532 + var licenseKey = $(this).val().trim();
533 +
534 + /**
535 + * If license key is not empty, enable the license activation button.
536 + */
537 + if ( licenseKey.length > 0 && ( $modal.hasClass( 'is-single-site-activation' ) || ! isNetworkActivation || hasSelectedSite() ) ) {
538 + enableActivateLicenseButton();
539 + }
540 + });
541 +
542 + $modal.on( 'blur', 'input.fs-license-key', function( evt ) {
543 + var
544 + licenseKey = $(this).val().trim(),
545 + $focusedElement = $( evt.relatedTarget ),
546 + hasSelectedAvailableLicense = ( hasLicenseTypes && $focusedElement.parents( '.fs-available-license-key-container' ).length > 0 );
547 +
548 + /**
549 + * If license key is empty, disable the license activation button.
550 + */
551 + if ( ( 0 === licenseKey.length && ( ! hasLicenseTypes || ! hasSelectedAvailableLicense ) ) ||
552 + ( isNetworkActivation && ! hasSelectedSite() )
553 + ) {
554 + disableActivateLicenseButton();
555 + }
556 + });
557 +
558 + $modal.on('click', '.button-activate-license', function (evt) {
559 + evt.preventDefault();
560 +
561 + if ($(this).hasClass('disabled')) {
562 + return;
563 + }
564 +
565 + var licenseKey = '',
566 + licenseID = '';
567 +
568 + if ( hasLicenseTypes ) {
569 + if ( isOtherLicenseKeySelected() ) {
570 + licenseKey = $otherLicenseKey.val();
571 + } else {
572 + if ( ! hasLicensesDropdown ) {
573 + licenseID = $availableLicenseKey.data( 'id' ).toString();
574 + } else {
575 + licenseID = $licensesDropdown.val();
576 + }
577 + }
578 + } else {
579 + licenseKey = $licenseKeyInput.val().trim();
580 + }
581 +
582 + disableActivateLicenseButton();
583 +
584 + if ( 0 === licenseID.length && 0 === licenseKey.length ) {
585 + return;
586 + }
587 +
588 + var data = {
589 + action : '<?php echo $fs->get_ajax_action( 'activate_license' ) ?>',
590 + security : '<?php echo $fs->get_ajax_security( 'activate_license' ) ?>',
591 + module_id : '<?php echo $fs->get_id() ?>'
592 + };
593 +
594 + if ( licenseID.length > 0 ) {
595 + data.license_id = licenseID;
596 + } else {
597 + data.license_key = licenseKey;
598 + }
599 +
600 + if ( isNetworkActivation ) {
601 + var
602 + sites = [];
603 +
604 + if ( null === singleBlogID ) {
605 + var
606 + applyOnAllSites = $applyOnAllSites.is( ':checked' );
607 +
608 + $sitesListContainer.find( 'tr' ).each(function() {
609 + var
610 + $this = $( this ),
611 + includeSite = ( applyOnAllSites || $this.find( 'input' ).is( ':checked' ) );
612 +
613 + if ( ! includeSite )
614 + return;
615 +
616 + var site = {
617 + uid : $this.find( '.uid' ).val(),
618 + url : $this.find( '.url' ).val(),
619 + title : $this.find( '.title' ).val(),
620 + language: $this.find( '.language' ).val(),
621 + blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
622 + };
623 +
624 + sites.push( site );
625 + });
626 + } else {
627 + data.blog_id = singleBlogID;
628 + }
629 +
630 + data.sites = sites;
631 + }
632 +
633 + if ( $ownershipChangeOptionContainer.find( 'input:checked' ).length > 0 ) {
634 + data.user_id = otherLicenseOwnerID;
635 + }
636 +
637 + $.ajax({
638 + url: <?php echo Freemius::ajax_url() ?>,
639 + method: 'POST',
640 + data: data,
641 + beforeSend: function () {
642 + $activateLicenseButton.text( '<?php fs_esc_js_echo_inline( 'Activating license', 'activating-license', $slug ) ?>...' );
643 + },
644 + success: function( result ) {
645 + var resultObj = $.parseJSON( result );
646 + if ( resultObj.success ) {
647 + closeModal();
648 +
649 + // Redirect to the "Account" page and sync the license.
650 + window.location.href = resultObj.next_page;
651 + } else {
652 + showError( resultObj.error.message ? resultObj.error.message : resultObj.error );
653 + resetActivateLicenseButton();
654 + }
655 + }
656 + });
657 + });
658 +
659 + // If the user has clicked outside the window, close the modal.
660 + $modal.on('click', '.fs-close, .button-secondary', function () {
661 + closeModal();
662 + return false;
663 + });
664 + }
665 +
666 + registerEventHandlers();
667 +
668 + $body.trigger('licenseActivationLoaded');
669 +
670 + /**
671 + * @author Leo Fajardo (@leorw)
672 + * @since 2.0.0
673 + */
674 + function enableDisableSitesSelection() {
675 + var
676 + canApplyOnAllSites = $applyOnAllSites.is( ':enabled' ),
677 + disableSitesSelection = null;
678 +
679 + if ( ! canApplyOnAllSites ) {
680 + var
681 + selectedSites = $sitesListContainer.find( 'input[type="checkbox"]:checked' ).length,
682 + activationsLeft = Math.max( 0, $activationsLeft.data( 'left' ) - selectedSites );
683 +
684 + disableSitesSelection = ( 0 === activationsLeft );
685 +
686 + $activationsLeft.text( activationsLeft );
687 + } else {
688 + disableSitesSelection = false;
689 + }
690 +
691 + $sitesListContainer
692 + .find( 'input[type="checkbox"]:not(:checked)' )
693 + .attr( 'disabled', disableSitesSelection );
694 + }
695 +
696 + /**
697 + * @author Leo Fajardo (@leorw)
698 + * @since 2.0.0
699 + *
700 + * @returns {Boolean}
701 + */
702 + function isOtherLicenseKeySelected() {
703 + return ( hasLicenseTypes && 'other' === $licenseTypes.filter( ':checked' ).val() );
704 + }
705 +
706 + /**
707 + * @author Leo Fajardo (@leorw)
708 + * @since 2.0.0
709 + *
710 + * @returns {Boolean}
711 + */
712 + function hasValidLicenseKey() {
713 + var licenseKey = '';
714 + if ( hasLicenseTypes ) {
715 + if ( 'available' === $licenseTypes.filter( ':checked' ).val() ) {
716 + return true;
717 + } else {
718 + licenseKey = $otherLicenseKey.val();
719 + }
720 + } else {
721 + licenseKey = $modal.find( 'input.fs-license-key' ).val();
722 + }
723 +
724 + return ( licenseKey.trim().length > 0 );
725 + }
726 +
727 + /**
728 + * @author Leo Fajardo (@leorw)
729 + * @since 2.0.0
730 + *
731 + * @returns {Boolean}
732 + */
733 + function hasSelectedSite() {
734 + return ( $applyOnAllSites.is( ':checked' ) ||
735 + $sitesListContainer.find( 'input[type="checkbox"]:checked:not(:disabled)' ).length > 0 );
736 + }
737 +
738 + /**
739 + * @author Leo Fajardo (@leorw)
740 + * @since 2.0.0
741 + */
742 + function toggleActivationOnAllSites() {
743 + var activationsLeft,
744 + licenseID;
745 +
746 + if (hasLicensesDropdown) {
747 + var $selectedOption = $licensesDropdown.find( ':selected' );
748 + activationsLeft = $selectedOption.data('left');
749 + licenseID = $selectedOption.data('id');
750 + } else {
751 + activationsLeft = $availableLicenseKey.data('left');
752 + licenseID = $availableLicenseKey.data('id');
753 + }
754 +
755 + // Cleanup previously auto-selected site.
756 + $modal.find( '.fs-sites-list-container input[type=checkbox]:disabled' )
757 + .attr('disabled', false)
758 + .attr('checked', false);
759 +
760 + var $blogsWithActiveLicense = $modal.find( '.fs-sites-list-container tr[data-license-id=' + licenseID + '] input[type=checkbox]' );
761 +
762 + if ($blogsWithActiveLicense.length > 0) {
763 + $blogsWithActiveLicense.attr('checked', true)
764 + .attr('disabled', true);
765 +
766 + activationsLeft += $blogsWithActiveLicense.length;
767 + }
768 +
769 + if ( activationsLeft >= totalSites ) {
770 + $applyOnAllSites.attr( 'disabled', false );
771 + enableDisableSitesSelection();
772 +
773 + resetActivateLicenseCheckboxLabel();
774 +
775 + return;
776 + }
777 +
778 + $applyOnAllSites.attr( 'checked', false );
779 + $applyOnAllSites.attr( 'disabled', true );
780 +
781 + showSites( true );
782 +
783 + var
784 + activateLicenseCheckboxLabel = '<?php fs_esc_js_echo_inline( 'Choose up to %s site(s) to activate the license on.', 'choose-up-to-n-sites-to-activate-the-license-on', $slug ) ?>';
785 +
786 + activateLicenseCheckboxLabel = activateLicenseCheckboxLabel.replace( '%s', '<span data-left="' + activationsLeft + '" class="activations-left">' + activationsLeft + '</span>' );
787 +
788 + // Update the label of the "Activate license on all sites" checkbox.
789 + $applyOnAllSites.parent().find( 'span' ).html( activateLicenseCheckboxLabel );
790 + $activationsLeft = $modal.find( '.activations-left' );
791 +
792 + if ( hasSelectedSite() ) {
793 + enableActivateLicenseButton();
794 + enableDisableSitesSelection();
795 + } else {
796 + disableActivateLicenseButton();
797 + }
798 + }
799 +
800 + /**
801 + * @author Leo Fajardo (@leorw)
802 + * @since 2.0.0
803 + */
804 + function resetActivateLicenseCheckboxLabel() {
805 + var activateLicenseCheckboxLabel = '<?php fs_esc_js_echo_inline( 'Activate license on all sites in the network.', 'activate-license-on-all-sites-in-the-network', $slug ) ?>';
806 + $applyOnAllSites.parent().find( 'span' ).text( activateLicenseCheckboxLabel );
807 + }
808 +
809 + /**
810 + * @author Leo Fajardo (@leorw)
811 + * @since 2.0.0
812 + *
813 + * @param {Boolean} show
814 + */
815 + function showSites( show ) {
816 + $sitesListContainer.toggle( show );
817 + if ( show && null === maxSitesListHeight ) {
818 + /**
819 + * Set the visible number of rows to 5 (5 * height of the first row).
820 + *
821 + * @author Leo Fajardo (@leorw)
822 + */
823 + maxSitesListHeight = ( 5 * $sitesListContainer.find( 'tr:first' ).height() );
824 + $sitesListContainer.css( 'max-height', maxSitesListHeight );
825 + }
826 + }
827 +
828 + function showModal( evt ) {
829 + resetModal();
830 +
831 + // Display the dialog box.
832 + $modal.addClass('active');
833 + $body.addClass('has-fs-modal');
834 +
835 + var
836 + $singleInstallDetails = $( evt.target ).parents( 'tr.fs-install-details' ),
837 + isSingleSiteActivation = ( $singleInstallDetails.length > 0 );
838 +
839 + $modal.toggleClass( 'is-single-site-activation', isSingleSiteActivation );
840 +
841 + singleBlogID = isSingleSiteActivation ?
842 + $singleInstallDetails.prev().data( 'blog-id' ) :
843 + null;
844 +
845 + <?php if ( $fs->apply_filters( 'enable_per_site_activation', true ) ) : ?>
846 + $multisiteOptionsContainer.toggle( isNetworkActivation && ! isSingleSiteActivation );
847 + <?php endif ?>
848 +
849 + if ( hasLicenseTypes ) {
850 + $licenseTypes.attr( 'checked', false );
851 +
852 + if ( hasLicensesDropdown ) {
853 + $licensesDropdown.find( 'option:first' ).attr( 'selected', true ).trigger( 'change' );
854 + } else {
855 + $licenseTypes.filter( '[value="available"]' ).click();
856 + }
857 +
858 + $otherLicenseKey.val( '' );
859 + } else {
860 + $licenseKeyInput.val( '' );
861 + $licenseKeyInput.focus();
862 + }
863 + }
864 +
865 + function closeModal() {
866 + $modal.removeClass('active');
867 + $body.removeClass('has-fs-modal');
868 + }
869 +
870 + function resetActivateLicenseButton() {
871 + enableActivateLicenseButton();
872 + $activateLicenseButton.text( <?php echo json_encode( $activate_button_text ) ?> );
873 + }
874 +
875 + function resetModal() {
876 + hideError();
877 + resetActivateLicenseButton();
878 + }
879 +
880 + function enableActivateLicenseButton() {
881 + $activateLicenseButton.removeClass( 'disabled' );
882 + }
883 +
884 + function disableActivateLicenseButton() {
885 + $activateLicenseButton.addClass( 'disabled' );
886 + }
887 +
888 + function hideError() {
889 + $licenseActivationMessage.hide();
890 + }
891 +
892 + function showError( msg ) {
893 + $licenseActivationMessage.find( ' > p' ).html( msg );
894 + $licenseActivationMessage.show();
895 + }
896 + });
897 +})( jQuery );
898 +</script>
899 +<?php
900 + fs_require_once_template( 'api-connectivity-message-js.php' );