FooBox Image Lightbox WordPress Plugin - Version 2.7.17

Version Description

  • Updated 01/02/2022
  • Fix : Security Fix in wp-admin
  • Update : Update to Freemius SDK
Download this release

Release Info

Developer bradvin
Plugin Icon 128x128 FooBox Image Lightbox WordPress Plugin
Version 2.7.17
Comparing to
See all releases

Code changes from version 2.7.16 to 2.7.17

Files changed (48) hide show
  1. foobox-free.php +2 -2
  2. free/css/admin-toplevel_page_foobox-image-lightbox.css +10 -10
  3. freemius/assets/css/admin/common.css +1 -1
  4. freemius/assets/css/admin/connect.css +1 -1
  5. freemius/assets/img/foobox-image-lightbox.png +0 -0
  6. freemius/includes/class-freemius.php +104 -43
  7. freemius/includes/class-fs-logger.php +2 -2
  8. freemius/includes/class-fs-options.php +430 -430
  9. freemius/includes/class-fs-storage.php +531 -531
  10. freemius/includes/entities/class-fs-site.php +17 -0
  11. freemius/includes/entities/class-fs-user.php +0 -17
  12. freemius/includes/fs-core-functions.php +1415 -1415
  13. freemius/includes/managers/class-fs-admin-notice-manager.php +7 -2
  14. freemius/includes/sdk/Exceptions/ArgumentNotExistException.php +5 -1
  15. freemius/includes/sdk/Exceptions/EmptyArgumentException.php +5 -1
  16. freemius/includes/sdk/Exceptions/Exception.php +5 -1
  17. freemius/includes/sdk/Exceptions/InvalidArgumentException.php +5 -1
  18. freemius/includes/sdk/Exceptions/OAuthException.php +5 -1
  19. freemius/includes/sdk/FreemiusBase.php +219 -215
  20. freemius/includes/sdk/FreemiusWordPress.php +4 -1
  21. freemius/languages/freemius-cs_CZ.mo +0 -0
  22. freemius/languages/freemius-da_DK.mo +0 -0
  23. freemius/languages/freemius-en.mo +0 -0
  24. freemius/languages/freemius-es_ES.mo +0 -0
  25. freemius/languages/freemius-fr_FR.mo +0 -0
  26. freemius/languages/freemius-he_IL.mo +0 -0
  27. freemius/languages/freemius-hu_HU.mo +0 -0
  28. freemius/languages/freemius-it_IT.mo +0 -0
  29. freemius/languages/freemius-ja.mo +0 -0
  30. freemius/languages/freemius-nl_NL.mo +0 -0
  31. freemius/languages/freemius-ru_RU.mo +0 -0
  32. freemius/languages/freemius-ta.mo +0 -0
  33. freemius/languages/freemius-zh_CN.mo +0 -0
  34. freemius/languages/freemius.pot +345 -313
  35. freemius/require.php +5 -1
  36. freemius/start.php +3 -3
  37. freemius/templates/account.php +5 -3
  38. freemius/templates/account/partials/addon.php +6 -1
  39. freemius/templates/ajax-loader.php +6 -1
  40. freemius/templates/connect.php +1037 -1025
  41. freemius/templates/debug.php +8 -2
  42. freemius/templates/firewall-issues-js.php +10 -6
  43. freemius/templates/forms/license-activation.php +3 -1
  44. freemius/templates/forms/optout.php +336 -336
  45. freemius/templates/partials/network-activation.php +6 -1
  46. freemius/templates/sticky-admin-notice-js.php +4 -2
  47. license.txt +673 -673
  48. readme.txt +7 -2
foobox-free.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: FooBox Image Lightbox
5
  Plugin URI: http://fooplugins.com/foobox/
6
  Description: The best responsive lightbox for WordPress.
7
- Version: 2.7.16
8
  Author: FooPlugins
9
  Author URI: http://fooplugins.com
10
  License: GPL2
@@ -24,7 +24,7 @@ if ( function_exists( 'foobox_fs' ) ) {
24
  define( 'FOOBOX_BASE_ACTIVATION_REDIRECT_TRANSIENT_KEY', '_foobox_activation_redirect' );
25
  define( 'FOOBOX_BASE_PATH', plugin_dir_path( __FILE__ ) );
26
  define( 'FOOBOX_BASE_URL', plugin_dir_url( __FILE__ ) );
27
- define( 'FOOBOX_BASE_VERSION', '2.7.16' );
28
  // Create a helper function for easy SDK access.
29
  function foobox_fs()
30
  {
4
  Plugin Name: FooBox Image Lightbox
5
  Plugin URI: http://fooplugins.com/foobox/
6
  Description: The best responsive lightbox for WordPress.
7
+ Version: 2.7.17
8
  Author: FooPlugins
9
  Author URI: http://fooplugins.com
10
  License: GPL2
24
  define( 'FOOBOX_BASE_ACTIVATION_REDIRECT_TRANSIENT_KEY', '_foobox_activation_redirect' );
25
  define( 'FOOBOX_BASE_PATH', plugin_dir_path( __FILE__ ) );
26
  define( 'FOOBOX_BASE_URL', plugin_dir_url( __FILE__ ) );
27
+ define( 'FOOBOX_BASE_VERSION', '2.7.17' );
28
  // Create a helper function for easy SDK access.
29
  function foobox_fs()
30
  {
free/css/admin-toplevel_page_foobox-image-lightbox.css CHANGED
@@ -1,11 +1,11 @@
1
- a.nav-tab:focus {
2
- box-shadow: none;
3
- }
4
-
5
- .foobox-getting-started.about-wrap img {
6
- border: none;
7
- }
8
-
9
- .foobox-getting-started.about-wrap .feature-section img {
10
- margin-bottom: 0;
11
  }
1
+ a.nav-tab:focus {
2
+ box-shadow: none;
3
+ }
4
+
5
+ .foobox-getting-started.about-wrap img {
6
+ border: none;
7
+ }
8
+
9
+ .foobox-getting-started.about-wrap .feature-section img {
10
+ margin-bottom: 0;
11
  }
freemius/assets/css/admin/common.css CHANGED
@@ -1,2 +1,2 @@
1
  .fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:white;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);box-shadow:0 2px 1px -1px rgba(0,0,0,0.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,0.1),inset 0 1px 3px 0 rgba(0,0,0,0.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);z-index:999;-moz-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}.fs-switch-feedback{margin-left:10px}.fs-switch-feedback.success{color:#71ae00}.rtl .fs-switch-feedback{margin-left:0;margin-right:10px}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media (max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}
2
- .fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,0.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,0.3);box-shadow:0 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 500px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'}.fs-submenu-item.pricing.upgrade-mode{color:greenyellow}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px}
1
  .fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:white;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);box-shadow:0 2px 1px -1px rgba(0,0,0,0.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,0.1),inset 0 1px 3px 0 rgba(0,0,0,0.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);z-index:999;-moz-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}.fs-switch-feedback{margin-left:10px}.fs-switch-feedback.success{color:#71ae00}.rtl .fs-switch-feedback{margin-left:0;margin-right:10px}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media (max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}
2
+ .fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,0.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,0.3);box-shadow:0 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 1250px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'}.fs-submenu-item.pricing.upgrade-mode{color:greenyellow}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px}
freemius/assets/css/admin/connect.css CHANGED
@@ -1 +1 @@
1
- #fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content .fs-error{background:snow;color:#d3135a;border:1px solid #d3135a;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-license-key-container{position:relative;width:280px;margin:10px auto 0 auto}#fs_connect .fs-license-key-container input{width:100%}#fs_connect .fs-license-key-container .dashicons{position:absolute;top:5px;right:5px}#fs_connect.require-license-key .fs-sites-list-container td{cursor:pointer}#fs_connect #delegate_to_site_admins{margin-right:15px;float:right;height:26px;vertical-align:middle;line-height:37px;font-weight:bold;border-bottom:1px dashed;text-decoration:none}#fs_connect #delegate_to_site_admins.rtl{margin-left:15px;margin-right:0}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions .fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li .fs-switch{float:right}#fs_connect .fs-permissions ul li .fs-permission-description{margin-left:55px}#fs_connect .fs-permissions ul li .fs-permission-description span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:#C2EEFF;text-decoration:underline}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:10px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity 0.3s ease-in-out;-o-transition:opacity 0.3s ease-in-out;-ms-transition:opacity 0.3s ease-in-out;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;position:absolute;background:rgba(0,0,0,0.8);color:#fff;font-family:'arial', serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:0;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);line-height:1.3em;font-weight:bold;text-align:left}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right}.fs-tooltip-trigger .fs-tooltip::after{content:' ';display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,0.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li .fs-switch{float:left}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(0,0,0,0.75);text-align:center;overflow-y:auto}#fs_theme_connect_wrapper:before{content:"";display:inline-block;vertical-align:middle;height:100%}#fs_theme_connect_wrapper>button.close{color:white;cursor:pointer;height:40px;width:40px;position:absolute;right:0;border:0;background-color:transparent;top:32px}#fs_theme_connect_wrapper #fs_connect{top:0;text-align:left;display:inline-block;vertical-align:middle;margin-top:52px;margin-bottom:20px}#fs_theme_connect_wrapper #fs_connect .fs-terms{background:rgba(140,140,140,0.64)}#fs_theme_connect_wrapper #fs_connect .fs-terms,#fs_theme_connect_wrapper #fs_connect .fs-terms a{color:#c5c5c5}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa}
1
+ #fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content .fs-error{background:snow;color:#d3135a;border:1px solid #d3135a;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-license-key-container{position:relative;width:280px;margin:10px auto 0 auto}#fs_connect .fs-license-key-container input{width:100%}#fs_connect .fs-license-key-container .dashicons{position:absolute;top:5px;right:5px}#fs_connect.require-license-key .fs-sites-list-container td{cursor:pointer}#fs_connect #delegate_to_site_admins{margin-right:15px;float:right;height:26px;vertical-align:middle;line-height:37px;font-weight:bold;border-bottom:1px dashed;text-decoration:none}#fs_connect #delegate_to_site_admins.rtl{margin-left:15px;margin-right:0}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions>.fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li>i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li .fs-switch{float:right}#fs_connect .fs-permissions ul li .fs-permission-description{margin-left:55px}#fs_connect .fs-permissions ul li .fs-permission-description span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:#C2EEFF;text-decoration:underline}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:10px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity 0.3s ease-in-out;-o-transition:opacity 0.3s ease-in-out;-ms-transition:opacity 0.3s ease-in-out;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;position:absolute;background:rgba(0,0,0,0.8);color:#fff !important;font-family:'arial', serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:-17px;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);line-height:1.3em;font-weight:bold;text-align:left;text-transform:none !important}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right;left:auto;right:-17px}.fs-tooltip-trigger .fs-tooltip::after{content:' ';display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,0.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li .fs-switch{float:left}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(0,0,0,0.75);text-align:center;overflow-y:auto}#fs_theme_connect_wrapper:before{content:"";display:inline-block;vertical-align:middle;height:100%}#fs_theme_connect_wrapper>button.close{color:white;cursor:pointer;height:40px;width:40px;position:absolute;right:0;border:0;background-color:transparent;top:32px}#fs_theme_connect_wrapper #fs_connect{top:0;text-align:left;display:inline-block;vertical-align:middle;margin-top:52px;margin-bottom:20px}#fs_theme_connect_wrapper #fs_connect .fs-terms{background:rgba(140,140,140,0.64)}#fs_theme_connect_wrapper #fs_connect .fs-terms,#fs_theme_connect_wrapper #fs_connect .fs-terms a{color:#c5c5c5}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa}#license_issues_link{display:block;text-align:center;font-size:0.9em;margin-top:10px}
freemius/assets/img/foobox-image-lightbox.png DELETED
Binary file
freemius/includes/class-freemius.php CHANGED
@@ -384,6 +384,13 @@
384
  * @var boolean|null
385
  */
386
  private $_use_external_pricing = null;
 
 
 
 
 
 
 
387
 
388
  #endregion
389
 
@@ -3543,6 +3550,8 @@
3543
  * @since 1.1.7.3
3544
  */
3545
  static function _toggle_debug_mode() {
 
 
3546
  if ( ! is_super_admin() ) {
3547
  return;
3548
  }
@@ -3564,10 +3573,19 @@
3564
  * @since 1.2.1.6
3565
  */
3566
  static function _get_debug_log() {
 
 
 
 
 
 
 
 
 
3567
  $logs = FS_Logger::load_db_logs(
3568
  fs_request_get( 'filters', false, 'post' ),
3569
- ! empty( $_POST['limit'] ) && is_numeric( $_POST['limit'] ) ? $_POST['limit'] : 200,
3570
- ! empty( $_POST['offset'] ) && is_numeric( $_POST['offset'] ) ? $_POST['offset'] : 0
3571
  );
3572
 
3573
  self::shoot_ajax_success( $logs );
@@ -4440,6 +4458,12 @@
4440
  * @since 1.0.9
4441
  */
4442
  function _email_about_firewall_issue() {
 
 
 
 
 
 
4443
  $this->_admin_notices->remove_sticky( 'failed_connect_api' );
4444
 
4445
  $pong = $this->ping();
@@ -4514,6 +4538,12 @@
4514
  * @since 1.1.7.4
4515
  */
4516
  function _retry_connectivity_test() {
 
 
 
 
 
 
4517
  $this->_admin_notices->remove_sticky( 'failed_connect_api_first' );
4518
 
4519
  $pong = $this->ping();
@@ -5484,7 +5514,7 @@
5484
  function is_extensions_tracking_allowed() {
5485
  return ( true === $this->apply_filters(
5486
  'is_extensions_tracking_allowed',
5487
- $this->_storage->get( 'is_extensions_tracking_allowed', true )
5488
  ) );
5489
  }
5490
 
@@ -5528,10 +5558,12 @@
5528
  * @author Leo Fajardo (@leorw)
5529
  * @since 2.3.2
5530
  *
5531
- * @param bool $is_enabled
5532
  */
5533
- private function update_extensions_tracking_flag( $is_enabled ) {
5534
- $this->_storage->store( 'is_extensions_tracking_allowed', $is_enabled );
 
 
5535
  }
5536
 
5537
  /**
@@ -6860,8 +6892,6 @@
6860
  */
6861
  function _sync_cron_method( array $blog_ids, $current_blog_id = null ) {
6862
  if ( $this->is_registered() ) {
6863
- $this->sync_user_beta_mode();
6864
-
6865
  if ( $this->has_paid_plan() ) {
6866
  // Initiate background plan sync.
6867
  $this->_sync_license( true, false, $current_blog_id );
@@ -7234,7 +7264,8 @@
7234
  }
7235
 
7236
  if ( $this->is_plugin_new_install() || $this->is_only_premium() ) {
7237
- if ( ! $this->_anonymous_mode ) {
 
7238
  // Show notice for new plugin installations.
7239
  $this->_admin_notices->add(
7240
  sprintf(
@@ -7285,6 +7316,10 @@
7285
  * @return bool
7286
  */
7287
  private function should_add_sticky_optin_notice() {
 
 
 
 
7288
  if ( fs_is_network_admin() ) {
7289
  if ( ! $this->_is_network_active ) {
7290
  return false;
@@ -13238,26 +13273,25 @@
13238
  self::shoot_ajax_failure();
13239
  }
13240
 
13241
- $user = $this->get_api_user_scope()->call(
13242
  '',
13243
  'put',
13244
  array(
13245
- 'plugin_id' => $this->get_id(),
13246
  'is_beta' => ( 'true' == $is_beta ),
13247
  'fields' => 'is_beta'
13248
  )
13249
  );
13250
 
13251
- if ( ! $this->is_api_result_entity( $user ) ) {
13252
  self::shoot_ajax_failure(
13253
- FS_Api::is_api_error_object( $user ) ?
13254
- $user->error->message :
13255
  fs_text_inline( "An unknown error has occurred while trying to set the user's beta mode.", 'unknown-error-occurred', $this->get_slug() )
13256
  );
13257
  }
13258
 
13259
- $this->_user->is_beta = $user->is_beta;
13260
- $this->_store_user();
13261
 
13262
  self::shoot_ajax_response( array( 'success' => true ) );
13263
  }
@@ -13292,7 +13326,7 @@
13292
  fs_request_get( 'blog_id', null ),
13293
  fs_request_get( 'module_id', null, 'post' ),
13294
  fs_request_get( 'user_id', null ),
13295
- fs_request_get_bool( 'is_extensions_tracking_allowed', true )
13296
  );
13297
 
13298
  if (
@@ -13482,7 +13516,31 @@
13482
  * @return string
13483
  */
13484
  function get_pricing_js_path() {
13485
- return $this->apply_filters( 'freemius_pricing_js_path', WP_FS__DIR_INCLUDES . '/freemius-pricing/freemius-pricing.js' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13486
  }
13487
 
13488
  /**
@@ -13527,7 +13585,7 @@
13527
  $blog_id = null,
13528
  $plugin_id = null,
13529
  $license_owner_id = null,
13530
- $is_extensions_tracking_allowed = true
13531
  ) {
13532
  $this->_logger->entrance();
13533
 
@@ -16448,19 +16506,6 @@
16448
  );
16449
  }
16450
 
16451
- /**
16452
- * @author Leo Fajardo (@leorw)
16453
- * @since 2.3.0
16454
- */
16455
- private function sync_user_beta_mode() {
16456
- $user = $this->get_api_user_scope()->get( '/?plugin_id=' . $this->get_id() . '&fields=is_beta' );
16457
-
16458
- if ( $this->is_api_result_entity( $user ) ) {
16459
- $this->_user->is_beta = $user->is_beta;
16460
- $this->_store_user();
16461
- }
16462
- }
16463
-
16464
  /**
16465
  * @author Vova Feldman (@svovaf)
16466
  * @since 1.1.7.4
@@ -17148,9 +17193,7 @@
17148
  $this->disable_opt_in_notice_and_lock_user();
17149
  }
17150
 
17151
- if ( ! is_null( $is_extensions_tracking_allowed ) ) {
17152
- $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
17153
- }
17154
 
17155
  return $this->setup_account(
17156
  $this->_user,
@@ -17195,9 +17238,7 @@
17195
  $this->disable_opt_in_notice_and_lock_user();
17196
  }
17197
 
17198
- if ( ! is_null( $is_extensions_tracking_allowed ) ) {
17199
- $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
17200
- }
17201
 
17202
  $sites = array();
17203
  foreach ( $site_ids as $site_id ) {
@@ -17240,9 +17281,7 @@
17240
  $this->disable_opt_in_notice_and_lock_user();
17241
  }
17242
 
17243
- if ( ! is_null( $is_extensions_tracking_allowed ) ) {
17244
- $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
17245
- }
17246
 
17247
  $install_ids = array();
17248
 
@@ -17353,7 +17392,7 @@
17353
  */
17354
  $license_key = fs_request_get( 'license_secret_key' );
17355
 
17356
- $this->update_extensions_tracking_flag( fs_request_get_bool( 'is_extensions_tracking_allowed', true ) );
17357
 
17358
  $this->install_with_current_user( $license_key );
17359
  }
@@ -20605,6 +20644,20 @@
20605
  }
20606
  }
20607
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20608
  if ( $this->is_addon() || $this->has_addons() ) {
20609
  /**
20610
  * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded,
@@ -21298,7 +21351,7 @@
21298
 
21299
  if ( $this->has_secret_key() ) {
21300
  $endpoint = add_query_arg( 'type', 'all', $endpoint );
21301
- } else if ( $this->is_registered() && $this->_user->is_beta() ) {
21302
  $endpoint = add_query_arg( 'type', 'beta', $endpoint );
21303
  }
21304
 
@@ -23396,6 +23449,14 @@
23396
  return;
23397
  }
23398
 
 
 
 
 
 
 
 
 
23399
  if ( fs_is_network_admin() ) {
23400
  if ( ! $this->_is_network_active ) {
23401
  // Don't add tracking links when browsing the network WP Admin and the plugin is not network active.
384
  * @var boolean|null
385
  */
386
  private $_use_external_pricing = null;
387
+ /**
388
+ * @author Leo Fajardo (@leorw)
389
+ * @since 2.4.2
390
+ *
391
+ * @var string|null
392
+ */
393
+ private $_pricing_js_path = null;
394
 
395
  #endregion
396
 
3550
  * @since 1.1.7.3
3551
  */
3552
  static function _toggle_debug_mode() {
3553
+ check_admin_referer( 'fs_toggle_debug_mode' );
3554
+
3555
  if ( ! is_super_admin() ) {
3556
  return;
3557
  }
3573
  * @since 1.2.1.6
3574
  */
3575
  static function _get_debug_log() {
3576
+ check_admin_referer( 'fs_get_debug_log' );
3577
+
3578
+ if ( ! is_super_admin() ) {
3579
+ return;
3580
+ }
3581
+
3582
+ $limit = min( ! empty( $_POST['limit'] ) ? absint( $_POST['limit'] ) : 200, 200 );
3583
+ $offset = min( ! empty( $_POST['offset'] ) ? absint( $_POST['offset'] ) : 200, 200 );
3584
+
3585
  $logs = FS_Logger::load_db_logs(
3586
  fs_request_get( 'filters', false, 'post' ),
3587
+ $limit,
3588
+ $offset
3589
  );
3590
 
3591
  self::shoot_ajax_success( $logs );
4458
  * @since 1.0.9
4459
  */
4460
  function _email_about_firewall_issue() {
4461
+ check_admin_referer( 'fs_resolve_firewall_issues' );
4462
+
4463
+ if ( ! current_user_can( is_multisite() ? 'manage_options' : 'activate_plugins' ) ) {
4464
+ return;
4465
+ }
4466
+
4467
  $this->_admin_notices->remove_sticky( 'failed_connect_api' );
4468
 
4469
  $pong = $this->ping();
4538
  * @since 1.1.7.4
4539
  */
4540
  function _retry_connectivity_test() {
4541
+ check_admin_referer( 'fs_retry_connectivity_test' );
4542
+
4543
+ if ( ! current_user_can( is_multisite() ? 'manage_options' : 'activate_plugins' ) ) {
4544
+ return;
4545
+ }
4546
+
4547
  $this->_admin_notices->remove_sticky( 'failed_connect_api_first' );
4548
 
4549
  $pong = $this->ping();
5514
  function is_extensions_tracking_allowed() {
5515
  return ( true === $this->apply_filters(
5516
  'is_extensions_tracking_allowed',
5517
+ $this->_storage->get( 'is_extensions_tracking_allowed', null )
5518
  ) );
5519
  }
5520
 
5558
  * @author Leo Fajardo (@leorw)
5559
  * @since 2.3.2
5560
  *
5561
+ * @param bool|null $is_enabled
5562
  */
5563
+ function update_extensions_tracking_flag( $is_enabled ) {
5564
+ if ( is_bool( $is_enabled ) ) {
5565
+ $this->_storage->store( 'is_extensions_tracking_allowed', $is_enabled );
5566
+ }
5567
  }
5568
 
5569
  /**
6892
  */
6893
  function _sync_cron_method( array $blog_ids, $current_blog_id = null ) {
6894
  if ( $this->is_registered() ) {
 
 
6895
  if ( $this->has_paid_plan() ) {
6896
  // Initiate background plan sync.
6897
  $this->_sync_license( true, false, $current_blog_id );
7264
  }
7265
 
7266
  if ( $this->is_plugin_new_install() || $this->is_only_premium() ) {
7267
+ if ( ! $this->_anonymous_mode &&
7268
+ ( ! $this->is_addon() || ! $this->_parent->is_anonymous() ) ) {
7269
  // Show notice for new plugin installations.
7270
  $this->_admin_notices->add(
7271
  sprintf(
7316
  * @return bool
7317
  */
7318
  private function should_add_sticky_optin_notice() {
7319
+ if ( $this->is_addon() && $this->_parent->is_anonymous() ) {
7320
+ return false;
7321
+ }
7322
+
7323
  if ( fs_is_network_admin() ) {
7324
  if ( ! $this->_is_network_active ) {
7325
  return false;
13273
  self::shoot_ajax_failure();
13274
  }
13275
 
13276
+ $site = $this->get_api_site_scope()->call(
13277
  '',
13278
  'put',
13279
  array(
 
13280
  'is_beta' => ( 'true' == $is_beta ),
13281
  'fields' => 'is_beta'
13282
  )
13283
  );
13284
 
13285
+ if ( ! $this->is_api_result_entity( $site ) ) {
13286
  self::shoot_ajax_failure(
13287
+ FS_Api::is_api_error_object( $site ) ?
13288
+ $site->error->message :
13289
  fs_text_inline( "An unknown error has occurred while trying to set the user's beta mode.", 'unknown-error-occurred', $this->get_slug() )
13290
  );
13291
  }
13292
 
13293
+ $this->_site->is_beta = $site->is_beta;
13294
+ $this->_store_site();
13295
 
13296
  self::shoot_ajax_response( array( 'success' => true ) );
13297
  }
13326
  fs_request_get( 'blog_id', null ),
13327
  fs_request_get( 'module_id', null, 'post' ),
13328
  fs_request_get( 'user_id', null ),
13329
+ fs_request_get_bool( 'is_extensions_tracking_allowed', null )
13330
  );
13331
 
13332
  if (
13516
  * @return string
13517
  */
13518
  function get_pricing_js_path() {
13519
+ if ( ! isset( $this->_pricing_js_path ) ) {
13520
+ $pricing_js_path = $this->apply_filters( 'freemius_pricing_js_path', '' );
13521
+
13522
+ if ( empty( $pricing_js_path ) ) {
13523
+ global $fs_active_plugins;
13524
+
13525
+ foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) {
13526
+ if ( $data->plugin_path == $this->get_plugin_basename() ) {
13527
+ $plugin_or_theme_root_dir = ( $this->is_plugin() ? WP_PLUGIN_DIR : get_theme_root( get_stylesheet() ) );
13528
+
13529
+ $pricing_js_path = $plugin_or_theme_root_dir
13530
+ . '/'
13531
+ // The basename will be `plugins`, `themes`, or the basename of a custom plugins or themes directory.
13532
+ . str_replace( '../' . basename( $plugin_or_theme_root_dir ) . '/', '', $sdk_path )
13533
+ . '/includes/freemius-pricing/freemius-pricing.js';
13534
+
13535
+ break;
13536
+ }
13537
+ }
13538
+ }
13539
+
13540
+ $this->_pricing_js_path = $pricing_js_path;
13541
+ }
13542
+
13543
+ return $this->_pricing_js_path;
13544
  }
13545
 
13546
  /**
13585
  $blog_id = null,
13586
  $plugin_id = null,
13587
  $license_owner_id = null,
13588
+ $is_extensions_tracking_allowed = null
13589
  ) {
13590
  $this->_logger->entrance();
13591
 
16506
  );
16507
  }
16508
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16509
  /**
16510
  * @author Vova Feldman (@svovaf)
16511
  * @since 1.1.7.4
17193
  $this->disable_opt_in_notice_and_lock_user();
17194
  }
17195
 
17196
+ $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
 
 
17197
 
17198
  return $this->setup_account(
17199
  $this->_user,
17238
  $this->disable_opt_in_notice_and_lock_user();
17239
  }
17240
 
17241
+ $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
 
 
17242
 
17243
  $sites = array();
17244
  foreach ( $site_ids as $site_id ) {
17281
  $this->disable_opt_in_notice_and_lock_user();
17282
  }
17283
 
17284
+ $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
 
 
17285
 
17286
  $install_ids = array();
17287
 
17392
  */
17393
  $license_key = fs_request_get( 'license_secret_key' );
17394
 
17395
+ $this->update_extensions_tracking_flag( fs_request_get_bool( 'is_extensions_tracking_allowed', null ) );
17396
 
17397
  $this->install_with_current_user( $license_key );
17398
  }
20644
  }
20645
  }
20646
 
20647
+ if ( ! $this->is_addon() &&
20648
+ $this->_site->is_beta() !== $site->is_beta
20649
+ ) {
20650
+ // Beta flag updated.
20651
+ $this->_site = $site;
20652
+
20653
+ $this->_store_site(
20654
+ true,
20655
+ $is_site_level_sync ?
20656
+ null :
20657
+ $this->get_network_install_blog_id()
20658
+ );
20659
+ }
20660
+
20661
  if ( $this->is_addon() || $this->has_addons() ) {
20662
  /**
20663
  * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded,
21351
 
21352
  if ( $this->has_secret_key() ) {
21353
  $endpoint = add_query_arg( 'type', 'all', $endpoint );
21354
+ } else if ( is_object( $this->_site ) && $this->_site->is_beta() ) {
21355
  $endpoint = add_query_arg( 'type', 'beta', $endpoint );
21356
  }
21357
 
23449
  return;
23450
  }
23451
 
23452
+ if (
23453
+ $this->is_addon() &&
23454
+ ! $this->is_only_premium() &&
23455
+ $this->_parent->is_anonymous()
23456
+ ) {
23457
+ return;
23458
+ }
23459
+
23460
  if ( fs_is_network_admin() ) {
23461
  if ( ! $this->_is_network_active ) {
23462
  // Don't add tracking links when browsing the network WP Admin and the plugin is not network active.
freemius/includes/class-fs-logger.php CHANGED
@@ -142,7 +142,7 @@
142
  return $this->_file_start;
143
  }
144
 
145
- private function _log( &$message, $type = 'log', $wrapper ) {
146
  if ( ! $this->is_on() ) {
147
  return;
148
  }
@@ -688,4 +688,4 @@ KEY `type` (`type` ASC))" );
688
  }
689
 
690
  #endregion
691
- }
142
  return $this->_file_start;
143
  }
144
 
145
+ private function _log( &$message, $type, $wrapper = false ) {
146
  if ( ! $this->is_on() ) {
147
  return;
148
  }
688
  }
689
 
690
  #endregion
691
+ }
freemius/includes/class-fs-options.php CHANGED
@@ -1,431 +1,431 @@
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.2.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Class FS_Options
15
- *
16
- * A wrapper class for handling network level and single site level options.
17
- */
18
- class FS_Options {
19
- /**
20
- * @var string
21
- */
22
- private $_id;
23
-
24
- /**
25
- * @var array[string]FS_Options {
26
- * @key string
27
- * @value FS_Options
28
- * }
29
- */
30
- private static $_instances;
31
-
32
- /**
33
- * @var FS_Option_Manager Site level options.
34
- */
35
- private $_options;
36
-
37
- /**
38
- * @var FS_Option_Manager Network level options.
39
- */
40
- private $_network_options;
41
-
42
- /**
43
- * @var int The ID of the blog that is associated with the current site level options.
44
- */
45
- private $_blog_id = 0;
46
-
47
- /**
48
- * @var bool
49
- */
50
- private $_is_multisite;
51
-
52
- /**
53
- * @var string[] Lazy collection of params on the site level.
54
- */
55
- private static $_SITE_OPTIONS_MAP;
56
-
57
- /**
58
- * @author Leo Fajardo (@leorw)
59
- * @since 2.0.0
60
- *
61
- * @param string $id
62
- * @param bool $load
63
- *
64
- * @return FS_Options
65
- */
66
- static function instance( $id, $load = false ) {
67
- if ( ! isset( self::$_instances[ $id ] ) ) {
68
- self::$_instances[ $id ] = new FS_Options( $id, $load );
69
- }
70
-
71
- return self::$_instances[ $id ];
72
- }
73
-
74
- /**
75
- * @author Leo Fajardo (@leorw)
76
- * @since 2.0.0
77
- *
78
- * @param string $id
79
- * @param bool $load
80
- */
81
- private function __construct( $id, $load = false ) {
82
- $this->_id = $id;
83
- $this->_is_multisite = is_multisite();
84
-
85
- if ( $this->_is_multisite ) {
86
- $this->_blog_id = get_current_blog_id();
87
- $this->_network_options = FS_Option_Manager::get_manager( $id, $load, true );
88
- }
89
-
90
- $this->_options = FS_Option_Manager::get_manager( $id, $load, $this->_blog_id );
91
- }
92
-
93
- /**
94
- * Switch the context of the site level options manager.
95
- *
96
- * @author Vova Feldman (@svovaf)
97
- * @since 2.0.0
98
- *
99
- * @param $blog_id
100
- */
101
- function set_site_blog_context( $blog_id ) {
102
- $this->_blog_id = $blog_id;
103
-
104
- $this->_options = FS_Option_Manager::get_manager( $this->_id, false, $this->_blog_id );
105
- }
106
-
107
- /**
108
- * @author Leo Fajardo (@leorw)
109
- *
110
- * @param string $option
111
- * @param mixed $default
112
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
113
- *
114
- * @return mixed
115
- */
116
- function get_option( $option, $default = null, $network_level_or_blog_id = null ) {
117
- if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
118
- return $this->_network_options->get_option( $option, $default );
119
- }
120
-
121
- $site_options = $this->get_site_options( $network_level_or_blog_id );
122
-
123
- return $site_options->get_option( $option, $default );
124
- }
125
-
126
- /**
127
- * @author Leo Fajardo (@leorw)
128
- * @since 2.0.0
129
- *
130
- * @param string $option
131
- * @param mixed $value
132
- * @param bool $flush
133
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
134
- */
135
- function set_option( $option, $value, $flush = false, $network_level_or_blog_id = null ) {
136
- if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
137
- $this->_network_options->set_option( $option, $value, $flush );
138
- } else {
139
- $site_options = $this->get_site_options( $network_level_or_blog_id );
140
- $site_options->set_option( $option, $value, $flush );
141
- }
142
- }
143
-
144
- /**
145
- * @author Vova Feldman (@svovaf)
146
- * @since 2.0.0
147
- *
148
- * @param string $option
149
- * @param bool $flush
150
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
151
- */
152
- function unset_option( $option, $flush = false, $network_level_or_blog_id = null ) {
153
- if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
154
- $this->_network_options->unset_option( $option, $flush );
155
- } else {
156
- $site_options = $this->get_site_options( $network_level_or_blog_id );
157
- $site_options->unset_option( $option, $flush );
158
- }
159
- }
160
-
161
- /**
162
- * @author Leo Fajardo (@leorw)
163
- * @since 2.0.0
164
- *
165
- * @param bool $flush
166
- * @param bool $network_level
167
- */
168
- function load( $flush = false, $network_level = true ) {
169
- if ( $this->_is_multisite && $network_level ) {
170
- $this->_network_options->load( $flush );
171
- } else {
172
- $this->_options->load( $flush );
173
- }
174
- }
175
-
176
- /**
177
- * @author Leo Fajardo (@leorw)
178
- * @since 2.0.0
179
- *
180
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, store both network storage and the current context blog storage.
181
- */
182
- function store( $network_level_or_blog_id = null ) {
183
- if ( ! $this->_is_multisite ||
184
- false === $network_level_or_blog_id ||
185
- 0 == $network_level_or_blog_id ||
186
- is_null( $network_level_or_blog_id )
187
- ) {
188
- $site_options = $this->get_site_options( $network_level_or_blog_id );
189
- $site_options->store();
190
- }
191
-
192
- if ( $this->_is_multisite &&
193
- ( is_null( $network_level_or_blog_id ) || true === $network_level_or_blog_id )
194
- ) {
195
- $this->_network_options->store();
196
- }
197
- }
198
-
199
- /**
200
- * @author Vova Feldman (@svovaf)
201
- * @since 2.0.0
202
- *
203
- * @param int|null|bool $network_level_or_blog_id
204
- * @param bool $flush
205
- */
206
- function clear( $network_level_or_blog_id = null, $flush = false ) {
207
- if ( ! $this->_is_multisite ||
208
- false === $network_level_or_blog_id ||
209
- is_null( $network_level_or_blog_id ) ||
210
- is_numeric( $network_level_or_blog_id )
211
- ) {
212
- $site_options = $this->get_site_options( $network_level_or_blog_id );
213
- $site_options->clear( $flush );
214
- }
215
-
216
- if ( $this->_is_multisite &&
217
- ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
218
- ) {
219
- $this->_network_options->clear( $flush );
220
- }
221
- }
222
-
223
- /**
224
- * Migration script to the new storage data structure that is network compatible.
225
- *
226
- * IMPORTANT:
227
- * This method should be executed only after it is determined if this is a network
228
- * level compatible product activation.
229
- *
230
- * @author Vova Feldman (@svovaf)
231
- * @since 2.0.0
232
- *
233
- * @param int $blog_id
234
- */
235
- function migrate_to_network( $blog_id = 0 ) {
236
- if ( ! $this->_is_multisite ) {
237
- return;
238
- }
239
-
240
- $updated = false;
241
-
242
- $site_options = $this->get_site_options( $blog_id );
243
-
244
- $keys = $site_options->get_options_keys();
245
-
246
- foreach ( $keys as $option ) {
247
- if ( $this->is_site_option( $option ) ||
248
- // Don't move admin notices to the network storage.
249
- in_array($option, array(
250
- // Don't move admin notices to the network storage.
251
- 'admin_notices',
252
- // Don't migrate the module specific data, it will be migrated by the FS_Storage.
253
- 'plugin_data',
254
- 'theme_data',
255
- ))
256
- ) {
257
- continue;
258
- }
259
-
260
- $option_updated = false;
261
-
262
- // Migrate option to the network storage.
263
- $site_option = $site_options->get_option( $option );
264
-
265
- if ( ! $this->_network_options->has_option( $option ) ) {
266
- // Option not set on the network level, so just set it.
267
- $this->_network_options->set_option( $option, $site_option, false );
268
-
269
- $option_updated = true;
270
- } else {
271
- // Option already set on the network level, so we need to merge it inelegantly.
272
- $network_option = $this->_network_options->get_option( $option );
273
-
274
- if ( is_array( $network_option ) && is_array( $site_option ) ) {
275
- // Option is an array.
276
- foreach ( $site_option as $key => $value ) {
277
- if ( ! isset( $network_option[ $key ] ) ) {
278
- $network_option[ $key ] = $value;
279
-
280
- $option_updated = true;
281
- } else if ( is_array( $network_option[ $key ] ) && is_array( $value ) ) {
282
- if ( empty( $network_option[ $key ] ) ) {
283
- $network_option[ $key ] = $value;
284
-
285
- $option_updated = true;
286
- } else if ( empty( $value ) ) {
287
- // Do nothing.
288
- } else {
289
- reset($value);
290
- $first_key = key($value);
291
- if ( $value[$first_key] instanceof FS_Entity ) {
292
- // Merge entities by IDs.
293
- $network_entities_ids = array();
294
- foreach ( $network_option[ $key ] as $entity ) {
295
- $network_entities_ids[ $entity->id ] = true;
296
- }
297
-
298
- foreach ( $value as $entity ) {
299
- if ( ! isset( $network_entities_ids[ $entity->id ] ) ) {
300
- $network_option[ $key ][] = $entity;
301
-
302
- $option_updated = true;
303
- }
304
- }
305
- }
306
- }
307
- }
308
- }
309
- }
310
-
311
- if ( $option_updated ) {
312
- $this->_network_options->set_option( $option, $network_option, false );
313
- }
314
- }
315
-
316
- /**
317
- * Remove the option from site level storage.
318
- *
319
- * IMPORTANT:
320
- * The line below is intentionally commented since we want to preserve the option
321
- * on the site storage level for "downgrade compatibility". Basically, if the user
322
- * will downgrade to an older version of the plugin with the prev storage structure,
323
- * it will continue working.
324
- *
325
- * @todo After a few releases we can remove this.
326
- */
327
- // $site_options->unset_option($option, false);
328
-
329
- if ( $option_updated ) {
330
- $updated = true;
331
- }
332
- }
333
-
334
- if ( ! $updated ) {
335
- return;
336
- }
337
-
338
- // Update network level storage.
339
- $this->_network_options->store();
340
- // $site_options->store();
341
- }
342
-
343
-
344
- #--------------------------------------------------------------------------------
345
- #region Helper Methods
346
- #--------------------------------------------------------------------------------
347
-
348
- /**
349
- * We don't want to load the map right away since it's not even needed in a non-MS environment.
350
- *
351
- * @author Vova Feldman (@svovaf)
352
- * @since 2.0.0
353
- */
354
- private static function load_site_options_map() {
355
- self::$_SITE_OPTIONS_MAP = array(
356
- 'sites' => true,
357
- 'theme_sites' => true,
358
- 'unique_id' => true,
359
- 'active_plugins' => true,
360
- );
361
- }
362
-
363
- /**
364
- * @author Vova Feldman (@svovaf)
365
- * @since 2.0.0
366
- *
367
- * @param string $option
368
- *
369
- * @return bool
370
- */
371
- private function is_site_option( $option ) {
372
- if ( WP_FS__ACCOUNTS_OPTION_NAME != $this->_id ) {
373
- return false;
374
- }
375
-
376
- if ( ! isset( self::$_SITE_OPTIONS_MAP ) ) {
377
- self::load_site_options_map();
378
- }
379
-
380
- return isset( self::$_SITE_OPTIONS_MAP[ $option ] );
381
- }
382
-
383
- /**
384
- * @author Vova Feldman (@svovaf)
385
- * @since 2.0.0
386
- *
387
- * @param int $blog_id
388
- *
389
- * @return FS_Option_Manager
390
- */
391
- private function get_site_options( $blog_id = 0 ) {
392
- if ( 0 == $blog_id || $blog_id == $this->_blog_id ) {
393
- return $this->_options;
394
- }
395
-
396
- return FS_Option_Manager::get_manager( $this->_id, true, $blog_id );
397
- }
398
-
399
- /**
400
- * Check if an option should be stored on the MS network storage.
401
- *
402
- * @author Vova Feldman (@svovaf)
403
- * @since 2.0.0
404
- *
405
- * @param string $option
406
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
407
- *
408
- * @return bool
409
- */
410
- private function should_use_network_storage( $option, $network_level_or_blog_id = null ) {
411
- if ( ! $this->_is_multisite ) {
412
- // Not a multisite environment.
413
- return false;
414
- }
415
-
416
- if ( is_numeric( $network_level_or_blog_id ) ) {
417
- // Explicitly asked to use a specified blog storage.
418
- return false;
419
- }
420
-
421
- if ( is_bool( $network_level_or_blog_id ) ) {
422
- // Explicitly specified whether should use the network or blog level storage.
423
- return $network_level_or_blog_id;
424
- }
425
-
426
- // Determine which storage to use based on the option.
427
- return ! $this->is_site_option( $option );
428
- }
429
-
430
- #endregion
431
  }
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.2.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Class FS_Options
15
+ *
16
+ * A wrapper class for handling network level and single site level options.
17
+ */
18
+ class FS_Options {
19
+ /**
20
+ * @var string
21
+ */
22
+ private $_id;
23
+
24
+ /**
25
+ * @var array[string]FS_Options {
26
+ * @key string
27
+ * @value FS_Options
28
+ * }
29
+ */
30
+ private static $_instances;
31
+
32
+ /**
33
+ * @var FS_Option_Manager Site level options.
34
+ */
35
+ private $_options;
36
+
37
+ /**
38
+ * @var FS_Option_Manager Network level options.
39
+ */
40
+ private $_network_options;
41
+
42
+ /**
43
+ * @var int The ID of the blog that is associated with the current site level options.
44
+ */
45
+ private $_blog_id = 0;
46
+
47
+ /**
48
+ * @var bool
49
+ */
50
+ private $_is_multisite;
51
+
52
+ /**
53
+ * @var string[] Lazy collection of params on the site level.
54
+ */
55
+ private static $_SITE_OPTIONS_MAP;
56
+
57
+ /**
58
+ * @author Leo Fajardo (@leorw)
59
+ * @since 2.0.0
60
+ *
61
+ * @param string $id
62
+ * @param bool $load
63
+ *
64
+ * @return FS_Options
65
+ */
66
+ static function instance( $id, $load = false ) {
67
+ if ( ! isset( self::$_instances[ $id ] ) ) {
68
+ self::$_instances[ $id ] = new FS_Options( $id, $load );
69
+ }
70
+
71
+ return self::$_instances[ $id ];
72
+ }
73
+
74
+ /**
75
+ * @author Leo Fajardo (@leorw)
76
+ * @since 2.0.0
77
+ *
78
+ * @param string $id
79
+ * @param bool $load
80
+ */
81
+ private function __construct( $id, $load = false ) {
82
+ $this->_id = $id;
83
+ $this->_is_multisite = is_multisite();
84
+
85
+ if ( $this->_is_multisite ) {
86
+ $this->_blog_id = get_current_blog_id();
87
+ $this->_network_options = FS_Option_Manager::get_manager( $id, $load, true );
88
+ }
89
+
90
+ $this->_options = FS_Option_Manager::get_manager( $id, $load, $this->_blog_id );
91
+ }
92
+
93
+ /**
94
+ * Switch the context of the site level options manager.
95
+ *
96
+ * @author Vova Feldman (@svovaf)
97
+ * @since 2.0.0
98
+ *
99
+ * @param $blog_id
100
+ */
101
+ function set_site_blog_context( $blog_id ) {
102
+ $this->_blog_id = $blog_id;
103
+
104
+ $this->_options = FS_Option_Manager::get_manager( $this->_id, false, $this->_blog_id );
105
+ }
106
+
107
+ /**
108
+ * @author Leo Fajardo (@leorw)
109
+ *
110
+ * @param string $option
111
+ * @param mixed $default
112
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
113
+ *
114
+ * @return mixed
115
+ */
116
+ function get_option( $option, $default = null, $network_level_or_blog_id = null ) {
117
+ if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
118
+ return $this->_network_options->get_option( $option, $default );
119
+ }
120
+
121
+ $site_options = $this->get_site_options( $network_level_or_blog_id );
122
+
123
+ return $site_options->get_option( $option, $default );
124
+ }
125
+
126
+ /**
127
+ * @author Leo Fajardo (@leorw)
128
+ * @since 2.0.0
129
+ *
130
+ * @param string $option
131
+ * @param mixed $value
132
+ * @param bool $flush
133
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
134
+ */
135
+ function set_option( $option, $value, $flush = false, $network_level_or_blog_id = null ) {
136
+ if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
137
+ $this->_network_options->set_option( $option, $value, $flush );
138
+ } else {
139
+ $site_options = $this->get_site_options( $network_level_or_blog_id );
140
+ $site_options->set_option( $option, $value, $flush );
141
+ }
142
+ }
143
+
144
+ /**
145
+ * @author Vova Feldman (@svovaf)
146
+ * @since 2.0.0
147
+ *
148
+ * @param string $option
149
+ * @param bool $flush
150
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
151
+ */
152
+ function unset_option( $option, $flush = false, $network_level_or_blog_id = null ) {
153
+ if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
154
+ $this->_network_options->unset_option( $option, $flush );
155
+ } else {
156
+ $site_options = $this->get_site_options( $network_level_or_blog_id );
157
+ $site_options->unset_option( $option, $flush );
158
+ }
159
+ }
160
+
161
+ /**
162
+ * @author Leo Fajardo (@leorw)
163
+ * @since 2.0.0
164
+ *
165
+ * @param bool $flush
166
+ * @param bool $network_level
167
+ */
168
+ function load( $flush = false, $network_level = true ) {
169
+ if ( $this->_is_multisite && $network_level ) {
170
+ $this->_network_options->load( $flush );
171
+ } else {
172
+ $this->_options->load( $flush );
173
+ }
174
+ }
175
+
176
+ /**
177
+ * @author Leo Fajardo (@leorw)
178
+ * @since 2.0.0
179
+ *
180
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, store both network storage and the current context blog storage.
181
+ */
182
+ function store( $network_level_or_blog_id = null ) {
183
+ if ( ! $this->_is_multisite ||
184
+ false === $network_level_or_blog_id ||
185
+ 0 == $network_level_or_blog_id ||
186
+ is_null( $network_level_or_blog_id )
187
+ ) {
188
+ $site_options = $this->get_site_options( $network_level_or_blog_id );
189
+ $site_options->store();
190
+ }
191
+
192
+ if ( $this->_is_multisite &&
193
+ ( is_null( $network_level_or_blog_id ) || true === $network_level_or_blog_id )
194
+ ) {
195
+ $this->_network_options->store();
196
+ }
197
+ }
198
+
199
+ /**
200
+ * @author Vova Feldman (@svovaf)
201
+ * @since 2.0.0
202
+ *
203
+ * @param int|null|bool $network_level_or_blog_id
204
+ * @param bool $flush
205
+ */
206
+ function clear( $network_level_or_blog_id = null, $flush = false ) {
207
+ if ( ! $this->_is_multisite ||
208
+ false === $network_level_or_blog_id ||
209
+ is_null( $network_level_or_blog_id ) ||
210
+ is_numeric( $network_level_or_blog_id )
211
+ ) {
212
+ $site_options = $this->get_site_options( $network_level_or_blog_id );
213
+ $site_options->clear( $flush );
214
+ }
215
+
216
+ if ( $this->_is_multisite &&
217
+ ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
218
+ ) {
219
+ $this->_network_options->clear( $flush );
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Migration script to the new storage data structure that is network compatible.
225
+ *
226
+ * IMPORTANT:
227
+ * This method should be executed only after it is determined if this is a network
228
+ * level compatible product activation.
229
+ *
230
+ * @author Vova Feldman (@svovaf)
231
+ * @since 2.0.0
232
+ *
233
+ * @param int $blog_id
234
+ */
235
+ function migrate_to_network( $blog_id = 0 ) {
236
+ if ( ! $this->_is_multisite ) {
237
+ return;
238
+ }
239
+
240
+ $updated = false;
241
+
242
+ $site_options = $this->get_site_options( $blog_id );
243
+
244
+ $keys = $site_options->get_options_keys();
245
+
246
+ foreach ( $keys as $option ) {
247
+ if ( $this->is_site_option( $option ) ||
248
+ // Don't move admin notices to the network storage.
249
+ in_array($option, array(
250
+ // Don't move admin notices to the network storage.
251
+ 'admin_notices',
252
+ // Don't migrate the module specific data, it will be migrated by the FS_Storage.
253
+ 'plugin_data',
254
+ 'theme_data',
255
+ ))
256
+ ) {
257
+ continue;
258
+ }
259
+
260
+ $option_updated = false;
261
+
262
+ // Migrate option to the network storage.
263
+ $site_option = $site_options->get_option( $option );
264
+
265
+ if ( ! $this->_network_options->has_option( $option ) ) {
266
+ // Option not set on the network level, so just set it.
267
+ $this->_network_options->set_option( $option, $site_option, false );
268
+
269
+ $option_updated = true;
270
+ } else {
271
+ // Option already set on the network level, so we need to merge it inelegantly.
272
+ $network_option = $this->_network_options->get_option( $option );
273
+
274
+ if ( is_array( $network_option ) && is_array( $site_option ) ) {
275
+ // Option is an array.
276
+ foreach ( $site_option as $key => $value ) {
277
+ if ( ! isset( $network_option[ $key ] ) ) {
278
+ $network_option[ $key ] = $value;
279
+
280
+ $option_updated = true;
281
+ } else if ( is_array( $network_option[ $key ] ) && is_array( $value ) ) {
282
+ if ( empty( $network_option[ $key ] ) ) {
283
+ $network_option[ $key ] = $value;
284
+
285
+ $option_updated = true;
286
+ } else if ( empty( $value ) ) {
287
+ // Do nothing.
288
+ } else {
289
+ reset($value);
290
+ $first_key = key($value);
291
+ if ( $value[$first_key] instanceof FS_Entity ) {
292
+ // Merge entities by IDs.
293
+ $network_entities_ids = array();
294
+ foreach ( $network_option[ $key ] as $entity ) {
295
+ $network_entities_ids[ $entity->id ] = true;
296
+ }
297
+
298
+ foreach ( $value as $entity ) {
299
+ if ( ! isset( $network_entities_ids[ $entity->id ] ) ) {
300
+ $network_option[ $key ][] = $entity;
301
+
302
+ $option_updated = true;
303
+ }
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ if ( $option_updated ) {
312
+ $this->_network_options->set_option( $option, $network_option, false );
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Remove the option from site level storage.
318
+ *
319
+ * IMPORTANT:
320
+ * The line below is intentionally commented since we want to preserve the option
321
+ * on the site storage level for "downgrade compatibility". Basically, if the user
322
+ * will downgrade to an older version of the plugin with the prev storage structure,
323
+ * it will continue working.
324
+ *
325
+ * @todo After a few releases we can remove this.
326
+ */
327
+ // $site_options->unset_option($option, false);
328
+
329
+ if ( $option_updated ) {
330
+ $updated = true;
331
+ }
332
+ }
333
+
334
+ if ( ! $updated ) {
335
+ return;
336
+ }
337
+
338
+ // Update network level storage.
339
+ $this->_network_options->store();
340
+ // $site_options->store();
341
+ }
342
+
343
+
344
+ #--------------------------------------------------------------------------------
345
+ #region Helper Methods
346
+ #--------------------------------------------------------------------------------
347
+
348
+ /**
349
+ * We don't want to load the map right away since it's not even needed in a non-MS environment.
350
+ *
351
+ * @author Vova Feldman (@svovaf)
352
+ * @since 2.0.0
353
+ */
354
+ private static function load_site_options_map() {
355
+ self::$_SITE_OPTIONS_MAP = array(
356
+ 'sites' => true,
357
+ 'theme_sites' => true,
358
+ 'unique_id' => true,
359
+ 'active_plugins' => true,
360
+ );
361
+ }
362
+
363
+ /**
364
+ * @author Vova Feldman (@svovaf)
365
+ * @since 2.0.0
366
+ *
367
+ * @param string $option
368
+ *
369
+ * @return bool
370
+ */
371
+ private function is_site_option( $option ) {
372
+ if ( WP_FS__ACCOUNTS_OPTION_NAME != $this->_id ) {
373
+ return false;
374
+ }
375
+
376
+ if ( ! isset( self::$_SITE_OPTIONS_MAP ) ) {
377
+ self::load_site_options_map();
378
+ }
379
+
380
+ return isset( self::$_SITE_OPTIONS_MAP[ $option ] );
381
+ }
382
+
383
+ /**
384
+ * @author Vova Feldman (@svovaf)
385
+ * @since 2.0.0
386
+ *
387
+ * @param int $blog_id
388
+ *
389
+ * @return FS_Option_Manager
390
+ */
391
+ private function get_site_options( $blog_id = 0 ) {
392
+ if ( 0 == $blog_id || $blog_id == $this->_blog_id ) {
393
+ return $this->_options;
394
+ }
395
+
396
+ return FS_Option_Manager::get_manager( $this->_id, true, $blog_id );
397
+ }
398
+
399
+ /**
400
+ * Check if an option should be stored on the MS network storage.
401
+ *
402
+ * @author Vova Feldman (@svovaf)
403
+ * @since 2.0.0
404
+ *
405
+ * @param string $option
406
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
407
+ *
408
+ * @return bool
409
+ */
410
+ private function should_use_network_storage( $option, $network_level_or_blog_id = null ) {
411
+ if ( ! $this->_is_multisite ) {
412
+ // Not a multisite environment.
413
+ return false;
414
+ }
415
+
416
+ if ( is_numeric( $network_level_or_blog_id ) ) {
417
+ // Explicitly asked to use a specified blog storage.
418
+ return false;
419
+ }
420
+
421
+ if ( is_bool( $network_level_or_blog_id ) ) {
422
+ // Explicitly specified whether should use the network or blog level storage.
423
+ return $network_level_or_blog_id;
424
+ }
425
+
426
+ // Determine which storage to use based on the option.
427
+ return ! $this->is_site_option( $option );
428
+ }
429
+
430
+ #endregion
431
  }
freemius/includes/class-fs-storage.php CHANGED
@@ -1,532 +1,532 @@
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.2.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Class FS_Storage
15
- *
16
- * A wrapper class for handling network level and single site level storage.
17
- *
18
- * @property bool $is_network_activation
19
- * @property int $network_install_blog_id
20
- * @property object $sync_cron
21
- */
22
- class FS_Storage {
23
- /**
24
- * @var FS_Storage[]
25
- */
26
- private static $_instances = array();
27
- /**
28
- * @var FS_Key_Value_Storage Site level storage.
29
- */
30
- private $_storage;
31
-
32
- /**
33
- * @var FS_Key_Value_Storage Network level storage.
34
- */
35
- private $_network_storage;
36
-
37
- /**
38
- * @var string
39
- */
40
- private $_module_type;
41
-
42
- /**
43
- * @var string
44
- */
45
- private $_module_slug;
46
-
47
- /**
48
- * @var int The ID of the blog that is associated with the current site level options.
49
- */
50
- private $_blog_id = 0;
51
-
52
- /**
53
- * @var bool
54
- */
55
- private $_is_multisite;
56
-
57
- /**
58
- * @var bool
59
- */
60
- private $_is_network_active = false;
61
-
62
- /**
63
- * @var bool
64
- */
65
- private $_is_delegated_connection = false;
66
-
67
- /**
68
- * @var array {
69
- * @key string Option name.
70
- * @value int If 0 store on the network level. If 1, store on the network level only if module was network level activated. If 2, store on the network level only if network activated and NOT delegated the connection.
71
- * }
72
- */
73
- private static $_NETWORK_OPTIONS_MAP;
74
-
75
- /**
76
- * @author Leo Fajardo (@leorw)
77
- *
78
- * @param string $module_type
79
- * @param string $slug
80
- *
81
- * @return FS_Storage
82
- */
83
- static function instance( $module_type, $slug ) {
84
- $key = $module_type . ':' . $slug;
85
-
86
- if ( ! isset( self::$_instances[ $key ] ) ) {
87
- self::$_instances[ $key ] = new FS_Storage( $module_type, $slug );
88
- }
89
-
90
- return self::$_instances[ $key ];
91
- }
92
-
93
- /**
94
- * @author Leo Fajardo (@leorw)
95
- *
96
- * @param string $module_type
97
- * @param string $slug
98
- */
99
- private function __construct( $module_type, $slug ) {
100
- $this->_module_type = $module_type;
101
- $this->_module_slug = $slug;
102
- $this->_is_multisite = is_multisite();
103
-
104
- if ( $this->_is_multisite ) {
105
- $this->_blog_id = get_current_blog_id();
106
- $this->_network_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, true );
107
- }
108
-
109
- $this->_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, $this->_blog_id );
110
- }
111
-
112
- /**
113
- * Tells this storage wrapper class that the context plugin is network active. This flag will affect how values
114
- * are retrieved/stored from/into the storage.
115
- *
116
- * @author Leo Fajardo (@leorw)
117
- *
118
- * @param bool $is_network_active
119
- * @param bool $is_delegated_connection
120
- */
121
- function set_network_active( $is_network_active = true, $is_delegated_connection = false ) {
122
- $this->_is_network_active = $is_network_active;
123
- $this->_is_delegated_connection = $is_delegated_connection;
124
- }
125
-
126
- /**
127
- * Switch the context of the site level storage manager.
128
- *
129
- * @author Vova Feldman (@svovaf)
130
- * @since 2.0.0
131
- *
132
- * @param int $blog_id
133
- */
134
- function set_site_blog_context( $blog_id ) {
135
- $this->_storage = $this->get_site_storage( $blog_id );
136
- $this->_blog_id = $blog_id;
137
- }
138
-
139
- /**
140
- * @author Leo Fajardo (@leorw)
141
- *
142
- * @param string $key
143
- * @param mixed $value
144
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
145
- * @param bool $flush
146
- */
147
- function store( $key, $value, $network_level_or_blog_id = null, $flush = true ) {
148
- if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
149
- $this->_network_storage->store( $key, $value, $flush );
150
- } else {
151
- $storage = $this->get_site_storage( $network_level_or_blog_id );
152
- $storage->store( $key, $value, $flush );
153
- }
154
- }
155
-
156
- /**
157
- * @author Leo Fajardo (@leorw)
158
- *
159
- * @param bool $store
160
- * @param string[] $exceptions Set of keys to keep and not clear.
161
- * @param int|null|bool $network_level_or_blog_id
162
- */
163
- function clear_all( $store = true, $exceptions = array(), $network_level_or_blog_id = null ) {
164
- if ( ! $this->_is_multisite ||
165
- false === $network_level_or_blog_id ||
166
- is_null( $network_level_or_blog_id ) ||
167
- is_numeric( $network_level_or_blog_id )
168
- ) {
169
- $storage = $this->get_site_storage( $network_level_or_blog_id );
170
- $storage->clear_all( $store, $exceptions );
171
- }
172
-
173
- if ( $this->_is_multisite &&
174
- ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
175
- ) {
176
- $this->_network_storage->clear_all( $store, $exceptions );
177
- }
178
- }
179
-
180
- /**
181
- * @author Leo Fajardo (@leorw)
182
- *
183
- * @param string $key
184
- * @param bool $store
185
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
186
- */
187
- function remove( $key, $store = true, $network_level_or_blog_id = null ) {
188
- if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
189
- $this->_network_storage->remove( $key, $store );
190
- } else {
191
- $storage = $this->get_site_storage( $network_level_or_blog_id );
192
- $storage->remove( $key, $store );
193
- }
194
- }
195
-
196
- /**
197
- * @author Leo Fajardo (@leorw)
198
- *
199
- * @param string $key
200
- * @param mixed $default
201
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
202
- *
203
- * @return mixed
204
- */
205
- function get( $key, $default = false, $network_level_or_blog_id = null ) {
206
- if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
207
- return $this->_network_storage->get( $key, $default );
208
- } else {
209
- $storage = $this->get_site_storage( $network_level_or_blog_id );
210
-
211
- return $storage->get( $key, $default );
212
- }
213
- }
214
-
215
- /**
216
- * Multisite activated:
217
- * true: Save network storage.
218
- * int: Save site specific storage.
219
- * false|0: Save current site storage.
220
- * null: Save network and current site storage.
221
- * Site level activated:
222
- * Save site storage.
223
- *
224
- * @author Vova Feldman (@svovaf)
225
- * @since 2.0.0
226
- *
227
- * @param bool|int|null $network_level_or_blog_id
228
- */
229
- function save( $network_level_or_blog_id = null ) {
230
- if ( $this->_is_network_active &&
231
- ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
232
- ) {
233
- $this->_network_storage->save();
234
- }
235
-
236
- if ( ! $this->_is_network_active || true !== $network_level_or_blog_id ) {
237
- $storage = $this->get_site_storage( $network_level_or_blog_id );
238
- $storage->save();
239
- }
240
- }
241
-
242
- /**
243
- * @author Vova Feldman (@svovaf)
244
- * @since 2.0.0
245
- *
246
- * @return string
247
- */
248
- function get_module_slug() {
249
- return $this->_module_slug;
250
- }
251
-
252
- /**
253
- * @author Vova Feldman (@svovaf)
254
- * @since 2.0.0
255
- *
256
- * @return string
257
- */
258
- function get_module_type() {
259
- return $this->_module_type;
260
- }
261
-
262
- /**
263
- * Migration script to the new storage data structure that is network compatible.
264
- *
265
- * IMPORTANT:
266
- * This method should be executed only after it is determined if this is a network
267
- * level compatible product activation.
268
- *
269
- * @author Vova Feldman (@svovaf)
270
- * @since 2.0.0
271
- */
272
- function migrate_to_network() {
273
- if ( ! $this->_is_multisite ) {
274
- return;
275
- }
276
-
277
- $updated = false;
278
-
279
- if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
280
- self::load_network_options_map();
281
- }
282
-
283
- foreach ( self::$_NETWORK_OPTIONS_MAP as $option => $storage_level ) {
284
- if ( ! $this->is_multisite_option( $option ) ) {
285
- continue;
286
- }
287
-
288
- if ( isset( $this->_storage->{$option} ) && ! isset( $this->_network_storage->{$option} ) ) {
289
- // Migrate option to the network storage.
290
- $this->_network_storage->store( $option, $this->_storage->{$option}, false );
291
-
292
- /**
293
- * Remove the option from site level storage.
294
- *
295
- * IMPORTANT:
296
- * The line below is intentionally commented since we want to preserve the option
297
- * on the site storage level for "downgrade compatibility". Basically, if the user
298
- * will downgrade to an older version of the plugin with the prev storage structure,
299
- * it will continue working.
300
- *
301
- * @todo After a few releases we can remove this.
302
- */
303
- // $this->_storage->remove($option, false);
304
-
305
- $updated = true;
306
- }
307
- }
308
-
309
- if ( ! $updated ) {
310
- return;
311
- }
312
-
313
- // Update network level storage.
314
- $this->_network_storage->save();
315
- // $this->_storage->save();
316
- }
317
-
318
- #--------------------------------------------------------------------------------
319
- #region Helper Methods
320
- #--------------------------------------------------------------------------------
321
-
322
- /**
323
- * We don't want to load the map right away since it's not even needed in a non-MS environment.
324
- *
325
- * Example:
326
- * array(
327
- * 'option1' => 0, // Means that the option should always be stored on the network level.
328
- * 'option2' => 1, // Means that the option should be stored on the network level only when the module was network level activated.
329
- * 'option2' => 2, // Means that the option should be stored on the network level only when the module was network level activated AND the connection was NOT delegated.
330
- * 'option3' => 3, // Means that the option should always be stored on the site level.
331
- * )
332
- *
333
- * @author Vova Feldman (@svovaf)
334
- * @since 2.0.0
335
- */
336
- private static function load_network_options_map() {
337
- self::$_NETWORK_OPTIONS_MAP = array(
338
- // Network level options.
339
- 'affiliate_application_data' => 0,
340
- 'beta_data' => 0,
341
- 'connectivity_test' => 0,
342
- 'handle_gdpr_admin_notice' => 0,
343
- 'has_trial_plan' => 0,
344
- 'install_sync_timestamp' => 0,
345
- 'install_sync_cron' => 0,
346
- 'is_anonymous_ms' => 0,
347
- 'is_network_activated' => 0,
348
- 'is_on' => 0,
349
- 'is_plugin_new_install' => 0,
350
- 'network_install_blog_id' => 0,
351
- 'pending_sites_info' => 0,
352
- 'plugin_last_version' => 0,
353
- 'plugin_main_file' => 0,
354
- 'plugin_version' => 0,
355
- 'sdk_downgrade_mode' => 0,
356
- 'sdk_last_version' => 0,
357
- 'sdk_upgrade_mode' => 0,
358
- 'sdk_version' => 0,
359
- 'sticky_optin_added_ms' => 0,
360
- 'subscriptions' => 0,
361
- 'sync_timestamp' => 0,
362
- 'sync_cron' => 0,
363
- 'was_plugin_loaded' => 0,
364
- 'network_user_id' => 0,
365
- 'plugin_upgrade_mode' => 0,
366
- 'plugin_downgrade_mode' => 0,
367
- 'is_network_connected' => 0,
368
- /**
369
- * Special flag that is used when a super-admin upgrades to the new version of the SDK that
370
- * supports network level integration, when the connection decision wasn't made for all of the
371
- * sites in the network.
372
- */
373
- 'is_network_activation' => 0,
374
- 'license_migration' => 0,
375
-
376
- // When network activated, then network level.
377
- 'install_timestamp' => 1,
378
- 'prev_is_premium' => 1,
379
- 'require_license_activation' => 1,
380
-
381
- // If not network activated OR delegated, then site level.
382
- 'activation_timestamp' => 2,
383
- 'expired_license_notice_shown' => 2,
384
- 'is_whitelabeled' => 2,
385
- 'last_license_key' => 2,
386
- 'last_license_user_id' => 2,
387
- 'prev_user_id' => 2,
388
- 'sticky_optin_added' => 2,
389
- 'uninstall_reason' => 2,
390
- 'is_pending_activation' => 2,
391
- 'pending_license_key' => 2,
392
- 'is_extensions_tracking_allowed' => 2,
393
-
394
- // Site level options.
395
- 'is_anonymous' => 3,
396
- );
397
- }
398
-
399
- /**
400
- * This method will and should only be executed when is_multisite() is true.
401
- *
402
- * @author Vova Feldman (@svovaf)
403
- * @since 2.0.0
404
- *
405
- * @param string $key
406
- *
407
- * @return bool|mixed
408
- */
409
- private function is_multisite_option( $key ) {
410
- if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
411
- self::load_network_options_map();
412
- }
413
-
414
- if ( ! isset( self::$_NETWORK_OPTIONS_MAP[ $key ] ) ) {
415
- // Option not found -> use site level storage.
416
- return false;
417
- }
418
-
419
- if ( 0 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
420
- // Option found and set to always use the network level storage on a multisite.
421
- return true;
422
- }
423
-
424
- if ( 3 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
425
- // Option found and set to always use the site level storage on a multisite.
426
- return false;
427
- }
428
-
429
- if ( ! $this->_is_network_active ) {
430
- return false;
431
- }
432
-
433
- if ( 1 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
434
- // Network activated.
435
- return true;
436
- }
437
-
438
- if ( 2 === self::$_NETWORK_OPTIONS_MAP[ $key ] && ! $this->_is_delegated_connection ) {
439
- // Network activated and not delegated.
440
- return true;
441
- }
442
-
443
- return false;
444
- }
445
-
446
- /**
447
- * @author Leo Fajardo
448
- *
449
- * @param string $key
450
- * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
451
- *
452
- * @return bool
453
- */
454
- private function should_use_network_storage( $key, $network_level_or_blog_id = null ) {
455
- if ( ! $this->_is_multisite ) {
456
- // Not a multisite environment.
457
- return false;
458
- }
459
-
460
- if ( is_numeric( $network_level_or_blog_id ) ) {
461
- // Explicitly asked to use a specified blog storage.
462
- return false;
463
- }
464
-
465
- if ( is_bool( $network_level_or_blog_id ) ) {
466
- // Explicitly specified whether should use the network or blog level storage.
467
- return $network_level_or_blog_id;
468
- }
469
-
470
- // Determine which storage to use based on the option.
471
- return $this->is_multisite_option( $key );
472
- }
473
-
474
- /**
475
- * @author Vova Feldman (@svovaf)
476
- * @since 2.0.0
477
- *
478
- * @param int $blog_id
479
- *
480
- * @return \FS_Key_Value_Storage
481
- */
482
- private function get_site_storage( $blog_id = 0 ) {
483
- if ( ! is_numeric( $blog_id ) ||
484
- $blog_id == $this->_blog_id ||
485
- 0 == $blog_id
486
- ) {
487
- return $this->_storage;
488
- }
489
-
490
- return FS_Key_Value_Storage::instance(
491
- $this->_module_type . '_data',
492
- $this->_storage->get_secondary_id(),
493
- $blog_id
494
- );
495
- }
496
-
497
- #endregion
498
-
499
- #--------------------------------------------------------------------------------
500
- #region Magic methods
501
- #--------------------------------------------------------------------------------
502
-
503
- function __set( $k, $v ) {
504
- if ( $this->should_use_network_storage( $k ) ) {
505
- $this->_network_storage->{$k} = $v;
506
- } else {
507
- $this->_storage->{$k} = $v;
508
- }
509
- }
510
-
511
- function __isset( $k ) {
512
- return $this->should_use_network_storage( $k ) ?
513
- isset( $this->_network_storage->{$k} ) :
514
- isset( $this->_storage->{$k} );
515
- }
516
-
517
- function __unset( $k ) {
518
- if ( $this->should_use_network_storage( $k ) ) {
519
- unset( $this->_network_storage->{$k} );
520
- } else {
521
- unset( $this->_storage->{$k} );
522
- }
523
- }
524
-
525
- function __get( $k ) {
526
- return $this->should_use_network_storage( $k ) ?
527
- $this->_network_storage->{$k} :
528
- $this->_storage->{$k};
529
- }
530
-
531
- #endregion
532
  }
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.2.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Class FS_Storage
15
+ *
16
+ * A wrapper class for handling network level and single site level storage.
17
+ *
18
+ * @property bool $is_network_activation
19
+ * @property int $network_install_blog_id
20
+ * @property object $sync_cron
21
+ */
22
+ class FS_Storage {
23
+ /**
24
+ * @var FS_Storage[]
25
+ */
26
+ private static $_instances = array();
27
+ /**
28
+ * @var FS_Key_Value_Storage Site level storage.
29
+ */
30
+ private $_storage;
31
+
32
+ /**
33
+ * @var FS_Key_Value_Storage Network level storage.
34
+ */
35
+ private $_network_storage;
36
+
37
+ /**
38
+ * @var string
39
+ */
40
+ private $_module_type;
41
+
42
+ /**
43
+ * @var string
44
+ */
45
+ private $_module_slug;
46
+
47
+ /**
48
+ * @var int The ID of the blog that is associated with the current site level options.
49
+ */
50
+ private $_blog_id = 0;
51
+
52
+ /**
53
+ * @var bool
54
+ */
55
+ private $_is_multisite;
56
+
57
+ /**
58
+ * @var bool
59
+ */
60
+ private $_is_network_active = false;
61
+
62
+ /**
63
+ * @var bool
64
+ */
65
+ private $_is_delegated_connection = false;
66
+
67
+ /**
68
+ * @var array {
69
+ * @key string Option name.
70
+ * @value int If 0 store on the network level. If 1, store on the network level only if module was network level activated. If 2, store on the network level only if network activated and NOT delegated the connection.
71
+ * }
72
+ */
73
+ private static $_NETWORK_OPTIONS_MAP;
74
+
75
+ /**
76
+ * @author Leo Fajardo (@leorw)
77
+ *
78
+ * @param string $module_type
79
+ * @param string $slug
80
+ *
81
+ * @return FS_Storage
82
+ */
83
+ static function instance( $module_type, $slug ) {
84
+ $key = $module_type . ':' . $slug;
85
+
86
+ if ( ! isset( self::$_instances[ $key ] ) ) {
87
+ self::$_instances[ $key ] = new FS_Storage( $module_type, $slug );
88
+ }
89
+
90
+ return self::$_instances[ $key ];
91
+ }
92
+
93
+ /**
94
+ * @author Leo Fajardo (@leorw)
95
+ *
96
+ * @param string $module_type
97
+ * @param string $slug
98
+ */
99
+ private function __construct( $module_type, $slug ) {
100
+ $this->_module_type = $module_type;
101
+ $this->_module_slug = $slug;
102
+ $this->_is_multisite = is_multisite();
103
+
104
+ if ( $this->_is_multisite ) {
105
+ $this->_blog_id = get_current_blog_id();
106
+ $this->_network_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, true );
107
+ }
108
+
109
+ $this->_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, $this->_blog_id );
110
+ }
111
+
112
+ /**
113
+ * Tells this storage wrapper class that the context plugin is network active. This flag will affect how values
114
+ * are retrieved/stored from/into the storage.
115
+ *
116
+ * @author Leo Fajardo (@leorw)
117
+ *
118
+ * @param bool $is_network_active
119
+ * @param bool $is_delegated_connection
120
+ */
121
+ function set_network_active( $is_network_active = true, $is_delegated_connection = false ) {
122
+ $this->_is_network_active = $is_network_active;
123
+ $this->_is_delegated_connection = $is_delegated_connection;
124
+ }
125
+
126
+ /**
127
+ * Switch the context of the site level storage manager.
128
+ *
129
+ * @author Vova Feldman (@svovaf)
130
+ * @since 2.0.0
131
+ *
132
+ * @param int $blog_id
133
+ */
134
+ function set_site_blog_context( $blog_id ) {
135
+ $this->_storage = $this->get_site_storage( $blog_id );
136
+ $this->_blog_id = $blog_id;
137
+ }
138
+
139
+ /**
140
+ * @author Leo Fajardo (@leorw)
141
+ *
142
+ * @param string $key
143
+ * @param mixed $value
144
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
145
+ * @param bool $flush
146
+ */
147
+ function store( $key, $value, $network_level_or_blog_id = null, $flush = true ) {
148
+ if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
149
+ $this->_network_storage->store( $key, $value, $flush );
150
+ } else {
151
+ $storage = $this->get_site_storage( $network_level_or_blog_id );
152
+ $storage->store( $key, $value, $flush );
153
+ }
154
+ }
155
+
156
+ /**
157
+ * @author Leo Fajardo (@leorw)
158
+ *
159
+ * @param bool $store
160
+ * @param string[] $exceptions Set of keys to keep and not clear.
161
+ * @param int|null|bool $network_level_or_blog_id
162
+ */
163
+ function clear_all( $store = true, $exceptions = array(), $network_level_or_blog_id = null ) {
164
+ if ( ! $this->_is_multisite ||
165
+ false === $network_level_or_blog_id ||
166
+ is_null( $network_level_or_blog_id ) ||
167
+ is_numeric( $network_level_or_blog_id )
168
+ ) {
169
+ $storage = $this->get_site_storage( $network_level_or_blog_id );
170
+ $storage->clear_all( $store, $exceptions );
171
+ }
172
+
173
+ if ( $this->_is_multisite &&
174
+ ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
175
+ ) {
176
+ $this->_network_storage->clear_all( $store, $exceptions );
177
+ }
178
+ }
179
+
180
+ /**
181
+ * @author Leo Fajardo (@leorw)
182
+ *
183
+ * @param string $key
184
+ * @param bool $store
185
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
186
+ */
187
+ function remove( $key, $store = true, $network_level_or_blog_id = null ) {
188
+ if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
189
+ $this->_network_storage->remove( $key, $store );
190
+ } else {
191
+ $storage = $this->get_site_storage( $network_level_or_blog_id );
192
+ $storage->remove( $key, $store );
193
+ }
194
+ }
195
+
196
+ /**
197
+ * @author Leo Fajardo (@leorw)
198
+ *
199
+ * @param string $key
200
+ * @param mixed $default
201
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
202
+ *
203
+ * @return mixed
204
+ */
205
+ function get( $key, $default = false, $network_level_or_blog_id = null ) {
206
+ if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
207
+ return $this->_network_storage->get( $key, $default );
208
+ } else {
209
+ $storage = $this->get_site_storage( $network_level_or_blog_id );
210
+
211
+ return $storage->get( $key, $default );
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Multisite activated:
217
+ * true: Save network storage.
218
+ * int: Save site specific storage.
219
+ * false|0: Save current site storage.
220
+ * null: Save network and current site storage.
221
+ * Site level activated:
222
+ * Save site storage.
223
+ *
224
+ * @author Vova Feldman (@svovaf)
225
+ * @since 2.0.0
226
+ *
227
+ * @param bool|int|null $network_level_or_blog_id
228
+ */
229
+ function save( $network_level_or_blog_id = null ) {
230
+ if ( $this->_is_network_active &&
231
+ ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
232
+ ) {
233
+ $this->_network_storage->save();
234
+ }
235
+
236
+ if ( ! $this->_is_network_active || true !== $network_level_or_blog_id ) {
237
+ $storage = $this->get_site_storage( $network_level_or_blog_id );
238
+ $storage->save();
239
+ }
240
+ }
241
+
242
+ /**
243
+ * @author Vova Feldman (@svovaf)
244
+ * @since 2.0.0
245
+ *
246
+ * @return string
247
+ */
248
+ function get_module_slug() {
249
+ return $this->_module_slug;
250
+ }
251
+
252
+ /**
253
+ * @author Vova Feldman (@svovaf)
254
+ * @since 2.0.0
255
+ *
256
+ * @return string
257
+ */
258
+ function get_module_type() {
259
+ return $this->_module_type;
260
+ }
261
+
262
+ /**
263
+ * Migration script to the new storage data structure that is network compatible.
264
+ *
265
+ * IMPORTANT:
266
+ * This method should be executed only after it is determined if this is a network
267
+ * level compatible product activation.
268
+ *
269
+ * @author Vova Feldman (@svovaf)
270
+ * @since 2.0.0
271
+ */
272
+ function migrate_to_network() {
273
+ if ( ! $this->_is_multisite ) {
274
+ return;
275
+ }
276
+
277
+ $updated = false;
278
+
279
+ if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
280
+ self::load_network_options_map();
281
+ }
282
+
283
+ foreach ( self::$_NETWORK_OPTIONS_MAP as $option => $storage_level ) {
284
+ if ( ! $this->is_multisite_option( $option ) ) {
285
+ continue;
286
+ }
287
+
288
+ if ( isset( $this->_storage->{$option} ) && ! isset( $this->_network_storage->{$option} ) ) {
289
+ // Migrate option to the network storage.
290
+ $this->_network_storage->store( $option, $this->_storage->{$option}, false );
291
+
292
+ /**
293
+ * Remove the option from site level storage.
294
+ *
295
+ * IMPORTANT:
296
+ * The line below is intentionally commented since we want to preserve the option
297
+ * on the site storage level for "downgrade compatibility". Basically, if the user
298
+ * will downgrade to an older version of the plugin with the prev storage structure,
299
+ * it will continue working.
300
+ *
301
+ * @todo After a few releases we can remove this.
302
+ */
303
+ // $this->_storage->remove($option, false);
304
+
305
+ $updated = true;
306
+ }
307
+ }
308
+
309
+ if ( ! $updated ) {
310
+ return;
311
+ }
312
+
313
+ // Update network level storage.
314
+ $this->_network_storage->save();
315
+ // $this->_storage->save();
316
+ }
317
+
318
+ #--------------------------------------------------------------------------------
319
+ #region Helper Methods
320
+ #--------------------------------------------------------------------------------
321
+
322
+ /**
323
+ * We don't want to load the map right away since it's not even needed in a non-MS environment.
324
+ *
325
+ * Example:
326
+ * array(
327
+ * 'option1' => 0, // Means that the option should always be stored on the network level.
328
+ * 'option2' => 1, // Means that the option should be stored on the network level only when the module was network level activated.
329
+ * 'option2' => 2, // Means that the option should be stored on the network level only when the module was network level activated AND the connection was NOT delegated.
330
+ * 'option3' => 3, // Means that the option should always be stored on the site level.
331
+ * )
332
+ *
333
+ * @author Vova Feldman (@svovaf)
334
+ * @since 2.0.0
335
+ */
336
+ private static function load_network_options_map() {
337
+ self::$_NETWORK_OPTIONS_MAP = array(
338
+ // Network level options.
339
+ 'affiliate_application_data' => 0,
340
+ 'beta_data' => 0,
341
+ 'connectivity_test' => 0,
342
+ 'handle_gdpr_admin_notice' => 0,
343
+ 'has_trial_plan' => 0,
344
+ 'install_sync_timestamp' => 0,
345
+ 'install_sync_cron' => 0,
346
+ 'is_anonymous_ms' => 0,
347
+ 'is_network_activated' => 0,
348
+ 'is_on' => 0,
349
+ 'is_plugin_new_install' => 0,
350
+ 'network_install_blog_id' => 0,
351
+ 'pending_sites_info' => 0,
352
+ 'plugin_last_version' => 0,
353
+ 'plugin_main_file' => 0,
354
+ 'plugin_version' => 0,
355
+ 'sdk_downgrade_mode' => 0,
356
+ 'sdk_last_version' => 0,
357
+ 'sdk_upgrade_mode' => 0,
358
+ 'sdk_version' => 0,
359
+ 'sticky_optin_added_ms' => 0,
360
+ 'subscriptions' => 0,
361
+ 'sync_timestamp' => 0,
362
+ 'sync_cron' => 0,
363
+ 'was_plugin_loaded' => 0,
364
+ 'network_user_id' => 0,
365
+ 'plugin_upgrade_mode' => 0,
366
+ 'plugin_downgrade_mode' => 0,
367
+ 'is_network_connected' => 0,
368
+ /**
369
+ * Special flag that is used when a super-admin upgrades to the new version of the SDK that
370
+ * supports network level integration, when the connection decision wasn't made for all of the
371
+ * sites in the network.
372
+ */
373
+ 'is_network_activation' => 0,
374
+ 'license_migration' => 0,
375
+
376
+ // When network activated, then network level.
377
+ 'install_timestamp' => 1,
378
+ 'prev_is_premium' => 1,
379
+ 'require_license_activation' => 1,
380
+
381
+ // If not network activated OR delegated, then site level.
382
+ 'activation_timestamp' => 2,
383
+ 'expired_license_notice_shown' => 2,
384
+ 'is_whitelabeled' => 2,
385
+ 'last_license_key' => 2,
386
+ 'last_license_user_id' => 2,
387
+ 'prev_user_id' => 2,
388
+ 'sticky_optin_added' => 2,
389
+ 'uninstall_reason' => 2,
390
+ 'is_pending_activation' => 2,
391
+ 'pending_license_key' => 2,
392
+ 'is_extensions_tracking_allowed' => 2,
393
+
394
+ // Site level options.
395
+ 'is_anonymous' => 3,
396
+ );
397
+ }
398
+
399
+ /**
400
+ * This method will and should only be executed when is_multisite() is true.
401
+ *
402
+ * @author Vova Feldman (@svovaf)
403
+ * @since 2.0.0
404
+ *
405
+ * @param string $key
406
+ *
407
+ * @return bool|mixed
408
+ */
409
+ private function is_multisite_option( $key ) {
410
+ if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
411
+ self::load_network_options_map();
412
+ }
413
+
414
+ if ( ! isset( self::$_NETWORK_OPTIONS_MAP[ $key ] ) ) {
415
+ // Option not found -> use site level storage.
416
+ return false;
417
+ }
418
+
419
+ if ( 0 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
420
+ // Option found and set to always use the network level storage on a multisite.
421
+ return true;
422
+ }
423
+
424
+ if ( 3 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
425
+ // Option found and set to always use the site level storage on a multisite.
426
+ return false;
427
+ }
428
+
429
+ if ( ! $this->_is_network_active ) {
430
+ return false;
431
+ }
432
+
433
+ if ( 1 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
434
+ // Network activated.
435
+ return true;
436
+ }
437
+
438
+ if ( 2 === self::$_NETWORK_OPTIONS_MAP[ $key ] && ! $this->_is_delegated_connection ) {
439
+ // Network activated and not delegated.
440
+ return true;
441
+ }
442
+
443
+ return false;
444
+ }
445
+
446
+ /**
447
+ * @author Leo Fajardo
448
+ *
449
+ * @param string $key
450
+ * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP).
451
+ *
452
+ * @return bool
453
+ */
454
+ private function should_use_network_storage( $key, $network_level_or_blog_id = null ) {
455
+ if ( ! $this->_is_multisite ) {
456
+ // Not a multisite environment.
457
+ return false;
458
+ }
459
+
460
+ if ( is_numeric( $network_level_or_blog_id ) ) {
461
+ // Explicitly asked to use a specified blog storage.
462
+ return false;
463
+ }
464
+
465
+ if ( is_bool( $network_level_or_blog_id ) ) {
466
+ // Explicitly specified whether should use the network or blog level storage.
467
+ return $network_level_or_blog_id;
468
+ }
469
+
470
+ // Determine which storage to use based on the option.
471
+ return $this->is_multisite_option( $key );
472
+ }
473
+
474
+ /**
475
+ * @author Vova Feldman (@svovaf)
476
+ * @since 2.0.0
477
+ *
478
+ * @param int $blog_id
479
+ *
480
+ * @return \FS_Key_Value_Storage
481
+ */
482
+ private function get_site_storage( $blog_id = 0 ) {
483
+ if ( ! is_numeric( $blog_id ) ||
484
+ $blog_id == $this->_blog_id ||
485
+ 0 == $blog_id
486
+ ) {
487
+ return $this->_storage;
488
+ }
489
+
490
+ return FS_Key_Value_Storage::instance(
491
+ $this->_module_type . '_data',
492
+ $this->_storage->get_secondary_id(),
493
+ $blog_id
494
+ );
495
+ }
496
+
497
+ #endregion
498
+
499
+ #--------------------------------------------------------------------------------
500
+ #region Magic methods
501
+ #--------------------------------------------------------------------------------
502
+
503
+ function __set( $k, $v ) {
504
+ if ( $this->should_use_network_storage( $k ) ) {
505
+ $this->_network_storage->{$k} = $v;
506
+ } else {
507
+ $this->_storage->{$k} = $v;
508
+ }
509
+ }
510
+
511
+ function __isset( $k ) {
512
+ return $this->should_use_network_storage( $k ) ?
513
+ isset( $this->_network_storage->{$k} ) :
514
+ isset( $this->_storage->{$k} );
515
+ }
516
+
517
+ function __unset( $k ) {
518
+ if ( $this->should_use_network_storage( $k ) ) {
519
+ unset( $this->_network_storage->{$k} );
520
+ } else {
521
+ unset( $this->_storage->{$k} );
522
+ }
523
+ }
524
+
525
+ function __get( $k ) {
526
+ return $this->should_use_network_storage( $k ) ?
527
+ $this->_network_storage->{$k} :
528
+ $this->_storage->{$k};
529
+ }
530
+
531
+ #endregion
532
  }
freemius/includes/entities/class-fs-site.php CHANGED
@@ -102,6 +102,14 @@
102
  * @var bool
103
  */
104
  public $is_uninstalled = false;
 
 
 
 
 
 
 
 
105
 
106
  /**
107
  * @param stdClass|bool $site
@@ -233,4 +241,13 @@
233
  function is_tracking_prohibited() {
234
  return ! $this->is_tracking_allowed();
235
  }
 
 
 
 
 
 
 
 
 
236
  }
102
  * @var bool
103
  */
104
  public $is_uninstalled = false;
105
+ /**
106
+ * @author Edgar Melkonyan
107
+ *
108
+ * @since 2.4.2
109
+ *
110
+ * @var bool
111
+ */
112
+ public $is_beta;
113
 
114
  /**
115
  * @param stdClass|bool $site
241
  function is_tracking_prohibited() {
242
  return ! $this->is_tracking_allowed();
243
  }
244
+
245
+ /**
246
+ * @author Edgar Melkonyan
247
+ *
248
+ * @return bool
249
+ */
250
+ function is_beta() {
251
+ return ( isset( $this->is_beta ) && true === $this->is_beta );
252
+ }
253
  }
freemius/includes/entities/class-fs-user.php CHANGED
@@ -31,13 +31,6 @@
31
  */
32
  public $is_verified;
33
  /**
34
- * @author Leo Fajardo (@leorw)
35
- * @since 2.3.0
36
- *
37
- * @var bool
38
- */
39
- public $is_beta;
40
- /**
41
  * @var string|null
42
  */
43
  public $customer_id;
@@ -63,16 +56,6 @@
63
  return ( isset( $this->is_verified ) && true === $this->is_verified );
64
  }
65
 
66
- /**
67
- * @author Leo Fajardo (@leorw)
68
- * @since 2.3.0
69
- *
70
- * @return bool
71
- */
72
- function is_beta() {
73
- return ( isset( $this->is_beta ) && true === $this->is_beta );
74
- }
75
-
76
  static function get_type() {
77
  return 'user';
78
  }
31
  */
32
  public $is_verified;
33
  /**
 
 
 
 
 
 
 
34
  * @var string|null
35
  */
36
  public $customer_id;
56
  return ( isset( $this->is_verified ) && true === $this->is_verified );
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
59
  static function get_type() {
60
  return 'user';
61
  }
freemius/includes/fs-core-functions.php CHANGED
@@ -1,1416 +1,1416 @@
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.0.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- if ( ! function_exists( 'fs_dummy' ) ) {
14
- function fs_dummy() {
15
- }
16
- }
17
-
18
- /* Url.
19
- --------------------------------------------------------------------------------------------*/
20
- if ( ! function_exists( 'fs_get_url_daily_cache_killer' ) ) {
21
- function fs_get_url_daily_cache_killer() {
22
- return date( '\YY\Mm\Dd' );
23
- }
24
- }
25
-
26
- /* Templates / Views.
27
- --------------------------------------------------------------------------------------------*/
28
- if ( ! function_exists( 'fs_get_template_path' ) ) {
29
- function fs_get_template_path( $path ) {
30
- return WP_FS__DIR_TEMPLATES . '/' . trim( $path, '/' );
31
- }
32
-
33
- function fs_include_template( $path, &$params = null ) {
34
- $VARS = &$params;
35
- include fs_get_template_path( $path );
36
- }
37
-
38
- function fs_include_once_template( $path, &$params = null ) {
39
- $VARS = &$params;
40
- include_once fs_get_template_path( $path );
41
- }
42
-
43
- function fs_require_template( $path, &$params = null ) {
44
- $VARS = &$params;
45
- require fs_get_template_path( $path );
46
- }
47
-
48
- function fs_require_once_template( $path, &$params = null ) {
49
- $VARS = &$params;
50
- require_once fs_get_template_path( $path );
51
- }
52
-
53
- function fs_get_template( $path, &$params = null ) {
54
- ob_start();
55
-
56
- $VARS = &$params;
57
- require fs_get_template_path( $path );
58
-
59
- return ob_get_clean();
60
- }
61
- }
62
-
63
- /* Scripts and styles including.
64
- --------------------------------------------------------------------------------------------*/
65
-
66
- if ( ! function_exists( 'fs_asset_url' ) ) {
67
- /**
68
- * Generates an absolute URL to the given path. This function ensures that the URL will be correct whether the asset
69
- * is inside a plugin's folder or a theme's folder.
70
- *
71
- * Examples:
72
- * 1. "themes" folder
73
- * Path: C:/xampp/htdocs/fswp/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
74
- * URL: http://fswp:8080/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
75
- *
76
- * 2. "plugins" folder
77
- * Path: C:/xampp/htdocs/fswp/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
78
- * URL: http://fswp:8080/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
79
- *
80
- * @author Leo Fajardo (@leorw)
81
- * @since 1.2.2
82
- *
83
- * @param string $asset_abs_path Asset's absolute path.
84
- *
85
- * @return string Asset's URL.
86
- */
87
- function fs_asset_url( $asset_abs_path ) {
88
- $wp_content_dir = fs_normalize_path( WP_CONTENT_DIR );
89
- $asset_abs_path = fs_normalize_path( $asset_abs_path );
90
-
91
- if ( 0 === strpos( $asset_abs_path, $wp_content_dir ) ) {
92
- // Handle both theme and plugin assets located in the standard directories.
93
- $asset_rel_path = str_replace( $wp_content_dir, '', $asset_abs_path );
94
- $asset_url = content_url( fs_normalize_path( $asset_rel_path ) );
95
- } else {
96
- $wp_plugins_dir = fs_normalize_path( WP_PLUGIN_DIR );
97
- if ( 0 === strpos( $asset_abs_path, $wp_plugins_dir ) ) {
98
- // Try to handle plugin assets that may be located in a non-standard plugins directory.
99
- $asset_rel_path = str_replace( $wp_plugins_dir, '', $asset_abs_path );
100
- $asset_url = plugins_url( fs_normalize_path( $asset_rel_path ) );
101
- } else {
102
- // Try to handle theme assets that may be located in a non-standard themes directory.
103
- $active_theme_stylesheet = get_stylesheet();
104
- $wp_themes_dir = fs_normalize_path( trailingslashit( get_theme_root( $active_theme_stylesheet ) ) );
105
- $asset_rel_path = str_replace( $wp_themes_dir, '', fs_normalize_path( $asset_abs_path ) );
106
- $asset_url = trailingslashit( get_theme_root_uri( $active_theme_stylesheet ) ) . fs_normalize_path( $asset_rel_path );
107
- }
108
- }
109
-
110
- return $asset_url;
111
- }
112
- }
113
-
114
- if ( ! function_exists( 'fs_enqueue_local_style' ) ) {
115
- function fs_enqueue_local_style( $handle, $path, $deps = array(), $ver = false, $media = 'all' ) {
116
- wp_enqueue_style( $handle, fs_asset_url( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ), $deps, $ver, $media );
117
- }
118
- }
119
-
120
- if ( ! function_exists( 'fs_enqueue_local_script' ) ) {
121
- function fs_enqueue_local_script( $handle, $path, $deps = array(), $ver = false, $in_footer = 'all' ) {
122
- wp_enqueue_script( $handle, fs_asset_url( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ), $deps, $ver, $in_footer );
123
- }
124
- }
125
-
126
- if ( ! function_exists( 'fs_img_url' ) ) {
127
- function fs_img_url( $path, $img_dir = WP_FS__DIR_IMG ) {
128
- return ( fs_asset_url( $img_dir . '/' . trim( $path, '/' ) ) );
129
- }
130
- }
131
-
132
- #--------------------------------------------------------------------------------
133
- #region Request handlers.
134
- #--------------------------------------------------------------------------------
135
-
136
- if ( ! function_exists( 'fs_request_get' ) ) {
137
- /**
138
- * A helper method to fetch GET/POST user input with an optional default value when the input is not set.
139
- * @author Vova Feldman (@svovaf)
140
- *
141
- * @param string $key
142
- * @param mixed $def
143
- * @param string|bool $type Since 1.2.1.7 - when set to 'get' will look for the value passed via querystring, when
144
- * set to 'post' will look for the value passed via the POST request's body, otherwise,
145
- * will check if the parameter was passed in any of the two.
146
- *
147
- * @return mixed
148
- */
149
- function fs_request_get( $key, $def = false, $type = false ) {
150
- if ( is_string( $type ) ) {
151
- $type = strtolower( $type );
152
- }
153
-
154
- /**
155
- * Note to WordPress.org Reviewers:
156
- * This is a helper method to fetch GET/POST user input with an optional default value when the input is not set. The actual sanitization is done in the scope of the function's usage.
157
- */
158
- switch ( $type ) {
159
- case 'post':
160
- $value = isset( $_POST[ $key ] ) ? $_POST[ $key ] : $def;
161
- break;
162
- case 'get':
163
- $value = isset( $_GET[ $key ] ) ? $_GET[ $key ] : $def;
164
- break;
165
- default:
166
- $value = isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $def;
167
- break;
168
- }
169
-
170
- return $value;
171
- }
172
- }
173
-
174
- if ( ! function_exists( 'fs_request_has' ) ) {
175
- function fs_request_has( $key ) {
176
- return isset( $_REQUEST[ $key ] );
177
- }
178
- }
179
-
180
- if ( ! function_exists( 'fs_request_get_bool' ) ) {
181
- /**
182
- * A helper method to fetch GET/POST user boolean input with an optional default value when the input is not set.
183
- *
184
- * @author Vova Feldman (@svovaf)
185
- *
186
- * @param string $key
187
- * @param bool $def
188
- *
189
- * @return bool|mixed
190
- */
191
- function fs_request_get_bool( $key, $def = false ) {
192
- $val = fs_request_get( $key, null );
193
-
194
- if ( is_null( $val ) ) {
195
- return $def;
196
- }
197
-
198
- if ( is_bool( $val ) ) {
199
- return $val;
200
- } else if ( is_numeric( $val ) ) {
201
- if ( 1 == $val ) {
202
- return true;
203
- } else if ( 0 == $val ) {
204
- return false;
205
- }
206
- } else if ( is_string( $val ) ) {
207
- $val = strtolower( $val );
208
-
209
- if ( 'true' === $val ) {
210
- return true;
211
- } else if ( 'false' === $val ) {
212
- return false;
213
- }
214
- }
215
-
216
- return $def;
217
- }
218
- }
219
-
220
- if ( ! function_exists( 'fs_request_is_post' ) ) {
221
- function fs_request_is_post() {
222
- return ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) );
223
- }
224
- }
225
-
226
- if ( ! function_exists( 'fs_request_is_get' ) ) {
227
- function fs_request_is_get() {
228
- return ( 'get' === strtolower( $_SERVER['REQUEST_METHOD'] ) );
229
- }
230
- }
231
-
232
- if ( ! function_exists( 'fs_get_action' ) ) {
233
- function fs_get_action( $action_key = 'action' ) {
234
- if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
235
- return strtolower( $_REQUEST[ $action_key ] );
236
- }
237
-
238
- if ( 'action' == $action_key ) {
239
- $action_key = 'fs_action';
240
-
241
- if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
242
- return strtolower( $_REQUEST[ $action_key ] );
243
- }
244
- }
245
-
246
- return false;
247
- }
248
- }
249
-
250
- if ( ! function_exists( 'fs_request_is_action' ) ) {
251
- function fs_request_is_action( $action, $action_key = 'action' ) {
252
- return ( strtolower( $action ) === fs_get_action( $action_key ) );
253
- }
254
- }
255
-
256
- if ( ! function_exists( 'fs_request_is_action_secure' ) ) {
257
- /**
258
- * @author Vova Feldman (@svovaf)
259
- * @since 1.0.0
260
- *
261
- * @since 1.2.1.5 Allow nonce verification.
262
- *
263
- * @param string $action
264
- * @param string $action_key
265
- * @param string $nonce_key
266
- *
267
- * @return bool
268
- */
269
- function fs_request_is_action_secure(
270
- $action,
271
- $action_key = 'action',
272
- $nonce_key = 'nonce'
273
- ) {
274
- if ( strtolower( $action ) !== fs_get_action( $action_key ) ) {
275
- return false;
276
- }
277
-
278
- $nonce = ! empty( $_REQUEST[ $nonce_key ] ) ?
279
- $_REQUEST[ $nonce_key ] :
280
- '';
281
-
282
- if ( empty( $nonce ) ||
283
- ( false === wp_verify_nonce( $nonce, $action ) )
284
- ) {
285
- return false;
286
- }
287
-
288
- return true;
289
- }
290
- }
291
-
292
- #endregion
293
-
294
- if ( ! function_exists( 'fs_is_plugin_page' ) ) {
295
- function fs_is_plugin_page( $page_slug ) {
296
- return ( is_admin() && $page_slug === fs_request_get( 'page' ) );
297
- }
298
- }
299
-
300
- if ( ! function_exists( 'fs_get_raw_referer' ) ) {
301
- /**
302
- * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer.
303
- *
304
- * Do not use for redirects, use {@see wp_get_referer()} instead.
305
- *
306
- * @since 1.2.3
307
- *
308
- * @return string|false Referer URL on success, false on failure.
309
- */
310
- function fs_get_raw_referer() {
311
- if ( function_exists( 'wp_get_raw_referer' ) ) {
312
- return wp_get_raw_referer();
313
- }
314
- if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
315
- return wp_unslash( $_REQUEST['_wp_http_referer'] );
316
- } else if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
317
- return wp_unslash( $_SERVER['HTTP_REFERER'] );
318
- }
319
-
320
- return false;
321
- }
322
- }
323
-
324
- /* Core UI.
325
- --------------------------------------------------------------------------------------------*/
326
- if ( ! function_exists( 'fs_ui_action_button' ) ) {
327
- /**
328
- * @param number $module_id
329
- * @param string $page
330
- * @param string $action
331
- * @param string $title
332
- * @param string $button_class
333
- * @param array $params
334
- * @param bool $is_primary
335
- * @param bool $is_small
336
- * @param string|bool $icon_class Optional class for an icon (since 1.1.7).
337
- * @param string|bool $confirmation Optional confirmation message before submit (since 1.1.7).
338
- * @param string $method Since 1.1.7
339
- *
340
- * @uses fs_ui_get_action_button()
341
- */
342
- function fs_ui_action_button(
343
- $module_id,
344
- $page,
345
- $action,
346
- $title,
347
- $button_class = '',
348
- $params = array(),
349
- $is_primary = true,
350
- $is_small = false,
351
- $icon_class = false,
352
- $confirmation = false,
353
- $method = 'GET'
354
- ) {
355
- echo fs_ui_get_action_button(
356
- $module_id,
357
- $page,
358
- $action,
359
- $title,
360
- $button_class,
361
- $params,
362
- $is_primary,
363
- $is_small,
364
- $icon_class,
365
- $confirmation,
366
- $method
367
- );
368
- }
369
- }
370
-
371
- if ( ! function_exists( 'fs_ui_get_action_button' ) ) {
372
- /**
373
- * @author Vova Feldman (@svovaf)
374
- * @since 1.1.7
375
- *
376
- * @param number $module_id
377
- * @param string $page
378
- * @param string $action
379
- * @param string $title
380
- * @param string $button_class
381
- * @param array $params
382
- * @param bool $is_primary
383
- * @param bool $is_small
384
- * @param string|bool $icon_class Optional class for an icon.
385
- * @param string|bool $confirmation Optional confirmation message before submit.
386
- * @param string $method
387
- *
388
- * @return string
389
- */
390
- function fs_ui_get_action_button(
391
- $module_id,
392
- $page,
393
- $action,
394
- $title,
395
- $button_class = '',
396
- $params = array(),
397
- $is_primary = true,
398
- $is_small = false,
399
- $icon_class = false,
400
- $confirmation = false,
401
- $method = 'GET'
402
- ) {
403
- // Prepend icon (if set).
404
- $title = ( is_string( $icon_class ) ? '<i class="' . $icon_class . '"></i> ' : '' ) . $title;
405
-
406
- if ( is_string( $confirmation ) ) {
407
- return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="if (confirm(\'%s\')) this.parentNode.submit(); return false;">%s</a></form>',
408
- freemius( $module_id )->_get_admin_page_url( $page, $params ),
409
- $method,
410
- $action,
411
- wp_nonce_field( $action, '_wpnonce', true, false ),
412
- 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
413
- $confirmation,
414
- $title
415
- );
416
- } else if ( 'GET' !== strtoupper( $method ) ) {
417
- return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="this.parentNode.submit(); return false;">%s</a></form>',
418
- freemius( $module_id )->_get_admin_page_url( $page, $params ),
419
- $method,
420
- $action,
421
- wp_nonce_field( $action, '_wpnonce', true, false ),
422
- 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
423
- $title
424
- );
425
- } else {
426
- return sprintf( '<a href="%s" class="%s">%s</a></form>',
427
- wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ),
428
- 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
429
- $title
430
- );
431
- }
432
- }
433
-
434
- function fs_ui_action_link( $module_id, $page, $action, $title, $params = array() ) {
435
- ?><a class=""
436
- href="<?php echo wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ) ?>"><?php echo $title ?></a><?php
437
- }
438
- }
439
-
440
- if ( ! function_exists( 'fs_get_entity' ) ) {
441
- /**
442
- * @author Leo Fajardo (@leorw)
443
- * @since 2.3.1
444
- *
445
- * @param mixed $entity
446
- * @param string $class
447
- *
448
- * @return FS_Plugin|FS_User|FS_Site|FS_Plugin_License|FS_Plugin_Plan|FS_Plugin_Tag|FS_Subscription
449
- */
450
- function fs_get_entity( $entity, $class ) {
451
- if ( ! is_object( $entity ) || $entity instanceof $class ) {
452
- return $entity;
453
- }
454
-
455
- return new $class( $entity );
456
- }
457
- }
458
-
459
- if ( ! function_exists( 'fs_get_entities' ) ) {
460
- /**
461
- * @author Leo Fajardo (@leorw)
462
- * @since 2.3.1
463
- *
464
- * @param mixed $entities
465
- * @param string $class_name
466
- *
467
- * @return FS_Plugin[]|FS_User[]|FS_Site[]|FS_Plugin_License[]|FS_Plugin_Plan[]|FS_Plugin_Tag[]|FS_Subscription[]
468
- */
469
- function fs_get_entities( $entities, $class_name ) {
470
- if ( ! is_array( $entities ) || empty( $entities ) ) {
471
- return $entities;
472
- }
473
-
474
- // Get first element.
475
- $first_array_element = reset( $entities );
476
-
477
- if ( $first_array_element instanceof $class_name ) {
478
- /**
479
- * If the first element of the array is an instance of the context class, assume that all other
480
- * elements are instances of the class.
481
- */
482
- return $entities;
483
- }
484
-
485
- if (
486
- is_array( $first_array_element ) &&
487
- ! empty( $first_array_element )
488
- ) {
489
- $first_array_element = reset( $first_array_element );
490
-
491
- if ( $first_array_element instanceof $class_name ) {
492
- /**
493
- * If the first element of the `$entities` array is an array whose first element is an instance of the
494
- * context class, assume that all other objects are instances of the class.
495
- */
496
- return $entities;
497
- }
498
- }
499
-
500
- foreach ( $entities as $key => $entities_or_entity ) {
501
- if ( is_array( $entities_or_entity ) ) {
502
- $entities[ $key ] = fs_get_entities( $entities_or_entity, $class_name );
503
- } else {
504
- $entities[ $key ] = fs_get_entity( $entities_or_entity, $class_name );
505
- }
506
- }
507
-
508
- return $entities;
509
- }
510
- }
511
-
512
- if ( ! function_exists( 'fs_nonce_url' ) ) {
513
- /**
514
- * Retrieve URL with nonce added to URL query.
515
- *
516
- * Originally was using `wp_nonce_url()` but the new version
517
- * changed the return value to escaped URL, that's not the expected
518
- * behaviour.
519
- *
520
- * @author Vova Feldman (@svovaf)
521
- * @since ~1.1.3
522
- *
523
- * @param string $actionurl URL to add nonce action.
524
- * @param int|string $action Optional. Nonce action name. Default -1.
525
- * @param string $name Optional. Nonce name. Default '_wpnonce'.
526
- *
527
- * @return string Escaped URL with nonce action added.
528
- */
529
- function fs_nonce_url( $actionurl, $action = - 1, $name = '_wpnonce' ) {
530
- return add_query_arg( $name, wp_create_nonce( $action ), $actionurl );
531
- }
532
- }
533
-
534
- if ( ! function_exists( 'fs_starts_with' ) ) {
535
- /**
536
- * Check if string starts with.
537
- *
538
- * @author Vova Feldman (@svovaf)
539
- * @since 1.1.3
540
- *
541
- * @param string $haystack
542
- * @param string $needle
543
- *
544
- * @return bool
545
- */
546
- function fs_starts_with( $haystack, $needle ) {
547
- $length = strlen( $needle );
548
-
549
- return ( substr( $haystack, 0, $length ) === $needle );
550
- }
551
- }
552
-
553
- if ( ! function_exists( 'fs_ends_with' ) ) {
554
- /**
555
- * Check if string ends with.
556
- *
557
- * @author Vova Feldman (@svovaf)
558
- * @since 2.0.0
559
- *
560
- * @param string $haystack
561
- * @param string $needle
562
- *
563
- * @return bool
564
- */
565
- function fs_ends_with( $haystack, $needle ) {
566
- $length = strlen( $needle );
567
- $start = $length * - 1; // negative
568
-
569
- return ( substr( $haystack, $start ) === $needle );
570
- }
571
- }
572
-
573
- if ( ! function_exists( 'fs_strip_url_protocol' ) ) {
574
- function fs_strip_url_protocol( $url ) {
575
- if ( ! fs_starts_with( $url, 'http' ) ) {
576
- return $url;
577
- }
578
-
579
- $protocol_pos = strpos( $url, '://' );
580
-
581
- if ( $protocol_pos > 5 ) {
582
- return $url;
583
- }
584
-
585
- return substr( $url, $protocol_pos + 3 );
586
- }
587
- }
588
-
589
- #region Url Canonization ------------------------------------------------------------------
590
-
591
- if ( ! function_exists( 'fs_canonize_url' ) ) {
592
- /**
593
- * @author Vova Feldman (@svovaf)
594
- * @since 1.1.3
595
- *
596
- * @param string $url
597
- * @param bool $omit_host
598
- * @param array $ignore_params
599
- *
600
- * @return string
601
- */
602
- function fs_canonize_url( $url, $omit_host = false, $ignore_params = array() ) {
603
- $parsed_url = parse_url( strtolower( $url ) );
604
-
605
- // if ( ! isset( $parsed_url['host'] ) ) {
606
- // return $url;
607
- // }
608
-
609
- $canonical = ( ( $omit_host || ! isset( $parsed_url['host'] ) ) ? '' : $parsed_url['host'] ) . $parsed_url['path'];
610
-
611
- if ( isset( $parsed_url['query'] ) ) {
612
- parse_str( $parsed_url['query'], $queryString );
613
- $canonical .= '?' . fs_canonize_query_string( $queryString, $ignore_params );
614
- }
615
-
616
- return $canonical;
617
- }
618
- }
619
-
620
- if ( ! function_exists( 'fs_canonize_query_string' ) ) {
621
- /**
622
- * @author Vova Feldman (@svovaf)
623
- * @since 1.1.3
624
- *
625
- * @param array $params
626
- * @param array $ignore_params
627
- * @param bool $params_prefix
628
- *
629
- * @return string
630
- */
631
- function fs_canonize_query_string( array $params, array &$ignore_params, $params_prefix = false ) {
632
- if ( ! is_array( $params ) || 0 === count( $params ) ) {
633
- return '';
634
- }
635
-
636
- // Url encode both keys and values
637
- $keys = fs_urlencode_rfc3986( array_keys( $params ) );
638
- $values = fs_urlencode_rfc3986( array_values( $params ) );
639
- $params = array_combine( $keys, $values );
640
-
641
- // Parameters are sorted by name, using lexicographical byte value ordering.
642
- // Ref: Spec: 9.1.1 (1)
643
- uksort( $params, 'strcmp' );
644
-
645
- $pairs = array();
646
- foreach ( $params as $parameter => $value ) {
647
- $lower_param = strtolower( $parameter );
648
-
649
- // Skip ignore params.
650
- if ( in_array( $lower_param, $ignore_params ) ||
651
- ( false !== $params_prefix && fs_starts_with( $lower_param, $params_prefix ) )
652
- ) {
653
- continue;
654
- }
655
-
656
- if ( is_array( $value ) ) {
657
- // If two or more parameters share the same name, they are sorted by their value
658
- // Ref: Spec: 9.1.1 (1)
659
- natsort( $value );
660
- foreach ( $value as $duplicate_value ) {
661
- $pairs[] = $lower_param . '=' . $duplicate_value;
662
- }
663
- } else {
664
- $pairs[] = $lower_param . '=' . $value;
665
- }
666
- }
667
-
668
- if ( 0 === count( $pairs ) ) {
669
- return '';
670
- }
671
-
672
- return implode( "&", $pairs );
673
- }
674
- }
675
-
676
- if ( ! function_exists( 'fs_urlencode_rfc3986' ) ) {
677
- /**
678
- * @author Vova Feldman (@svovaf)
679
- * @since 1.1.3
680
- *
681
- * @param string|string[] $input
682
- *
683
- * @return array|mixed|string
684
- */
685
- function fs_urlencode_rfc3986( $input ) {
686
- if ( is_array( $input ) ) {
687
- return array_map( 'fs_urlencode_rfc3986', $input );
688
- } else if ( is_scalar( $input ) ) {
689
- return str_replace( '+', ' ', str_replace( '%7E', '~', rawurlencode( $input ) ) );
690
- }
691
-
692
- return '';
693
- }
694
- }
695
-
696
- #endregion Url Canonization ------------------------------------------------------------------
697
-
698
- if ( ! function_exists( 'fs_download_image' ) ) {
699
- /**
700
- * @author Vova Feldman (@svovaf)
701
- *
702
- * @since 1.2.2 Changed to usage of WP_Filesystem_Direct.
703
- *
704
- * @param string $from URL
705
- * @param string $to File path.
706
- *
707
- * @return bool Is successfully downloaded.
708
- */
709
- function fs_download_image( $from, $to ) {
710
- $dir = dirname( $to );
711
-
712
- if ( 'direct' !== get_filesystem_method( array(), $dir ) ) {
713
- return false;
714
- }
715
-
716
- if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
717
- require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
718
- require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
719
- }
720
-
721
- $fs = new WP_Filesystem_Direct( '' );
722
- $tmpfile = download_url( $from );
723
-
724
- if ( $tmpfile instanceof WP_Error ) {
725
- // Issue downloading the file.
726
- return false;
727
- }
728
-
729
- $fs->copy( $tmpfile, $to );
730
- $fs->delete( $tmpfile );
731
-
732
- return true;
733
- }
734
- }
735
-
736
- /* General Utilities
737
- --------------------------------------------------------------------------------------------*/
738
-
739
- if ( ! function_exists( 'fs_sort_by_priority' ) ) {
740
- /**
741
- * Sorts an array by the value of the priority key.
742
- *
743
- * @author Daniel Iser (@danieliser)
744
- * @since 1.1.7
745
- *
746
- * @param $a
747
- * @param $b
748
- *
749
- * @return int
750
- */
751
- function fs_sort_by_priority( $a, $b ) {
752
-
753
- // If b has a priority and a does not, b wins.
754
- if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) {
755
- return 1;
756
- } // If b has a priority and a does not, b wins.
757
- elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) {
758
- return - 1;
759
- } // If neither has a priority or both priorities are equal its a tie.
760
- elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) {
761
- return 0;
762
- }
763
-
764
- // If both have priority return the winner.
765
- return ( $a['priority'] < $b['priority'] ) ? - 1 : 1;
766
- }
767
- }
768
-
769
- #--------------------------------------------------------------------------------
770
- #region Localization
771
- #--------------------------------------------------------------------------------
772
-
773
- if ( ! function_exists( 'fs_text' ) ) {
774
- /**
775
- * Retrieve a translated text by key.
776
- *
777
- * @author Vova Feldman (@svovaf)
778
- * @since 1.2.1.7
779
- *
780
- * @param string $key
781
- * @param string $slug
782
- *
783
- * @return string
784
- *
785
- * @global $fs_text , $fs_text_overrides
786
- */
787
- function fs_text( $key, $slug = 'freemius' ) {
788
- global $fs_text,
789
- $fs_module_info_text,
790
- $fs_text_overrides;
791
-
792
- if ( isset( $fs_text_overrides[ $slug ] ) ) {
793
- if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
794
- return $fs_text_overrides[ $slug ][ $key ];
795
- }
796
-
797
- $lower_key = strtolower( $key );
798
- if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
799
- return $fs_text_overrides[ $slug ][ $lower_key ];
800
- }
801
- }
802
-
803
- if ( ! isset( $fs_text ) ) {
804
- $dir = defined( 'WP_FS__DIR_INCLUDES' ) ?
805
- WP_FS__DIR_INCLUDES :
806
- dirname( __FILE__ );
807
-
808
- require_once $dir . '/i18n.php';
809
- }
810
-
811
- if ( isset( $fs_text[ $key ] ) ) {
812
- return $fs_text[ $key ];
813
- }
814
-
815
- if ( isset( $fs_module_info_text[ $key ] ) ) {
816
- return $fs_module_info_text[ $key ];
817
- }
818
-
819
- return $key;
820
- }
821
-
822
- #region Private
823
-
824
- /**
825
- * Retrieve an inline translated text by key with a context.
826
- *
827
- * @author Vova Feldman (@svovaf)
828
- * @since 1.2.3
829
- *
830
- * @param string $text Translatable string.
831
- * @param string $context Context information for the translators.
832
- * @param string $key String key for overrides.
833
- * @param string $slug Module slug for overrides.
834
- *
835
- * @return string
836
- *
837
- * @global $fs_text_overrides
838
- */
839
- function _fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
840
- list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
841
-
842
- // Avoid misleading Theme Check warning.
843
- $fn = 'translate_with_gettext_context';
844
-
845
- return $fn( $text, $context, $text_domain );
846
- }
847
-
848
- #endregion
849
-
850
- /**
851
- * Retrieve an inline translated text by key with a context.
852
- *
853
- * @author Vova Feldman (@svovaf)
854
- * @since 1.2.3
855
- *
856
- * @param string $text Translatable string.
857
- * @param string $context Context information for the translators.
858
- * @param string $key String key for overrides.
859
- * @param string $slug Module slug for overrides.
860
- *
861
- * @return string
862
- *
863
- * @global $fs_text_overrides
864
- */
865
- function fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
866
- return _fs_text_x_inline( $text, $context, $key, $slug );
867
- }
868
-
869
- /**
870
- * Output a translated text by key.
871
- *
872
- * @author Vova Feldman (@svovaf)
873
- * @since 1.2.1.7
874
- *
875
- * @param string $key
876
- * @param string $slug
877
- */
878
- function fs_echo( $key, $slug = 'freemius' ) {
879
- echo fs_text( $key, $slug );
880
- }
881
-
882
- /**
883
- * Output an inline translated text.
884
- *
885
- * @author Vova Feldman (@svovaf)
886
- * @since 1.2.3
887
- *
888
- * @param string $text Translatable string.
889
- * @param string $key String key for overrides.
890
- * @param string $slug Module slug for overrides.
891
- */
892
- function fs_echo_inline( $text, $key = '', $slug = 'freemius' ) {
893
- echo _fs_text_inline( $text, $key, $slug );
894
- }
895
-
896
- /**
897
- * Output an inline translated text with a context.
898
- *
899
- * @author Vova Feldman (@svovaf)
900
- * @since 1.2.3
901
- *
902
- * @param string $text Translatable string.
903
- * @param string $context Context information for the translators.
904
- * @param string $key String key for overrides.
905
- * @param string $slug Module slug for overrides.
906
- */
907
- function fs_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
908
- echo _fs_text_x_inline( $text, $context, $key, $slug );
909
- }
910
- }
911
-
912
- if ( ! function_exists( 'fs_text_override' ) ) {
913
- /**
914
- * Get a translatable text override if exists, or `false`.
915
- *
916
- * @author Vova Feldman (@svovaf)
917
- * @since 1.2.1.7
918
- *
919
- * @param string $text Translatable string.
920
- * @param string $key String key for overrides.
921
- * @param string $slug Module slug for overrides.
922
- *
923
- * @return string|false
924
- */
925
- function fs_text_override( $text, $key, $slug ) {
926
- global $fs_text_overrides;
927
-
928
- /**
929
- * Check if string is overridden.
930
- */
931
- if ( ! isset( $fs_text_overrides[ $slug ] ) ) {
932
- return false;
933
- }
934
-
935
- if ( empty( $key ) ) {
936
- $key = strtolower( str_replace( ' ', '-', $text ) );
937
- }
938
-
939
- if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
940
- return $fs_text_overrides[ $slug ][ $key ];
941
- }
942
-
943
- $lower_key = strtolower( $key );
944
- if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
945
- return $fs_text_overrides[ $slug ][ $lower_key ];
946
- }
947
-
948
- return false;
949
- }
950
- }
951
-
952
- if ( ! function_exists( 'fs_text_and_domain' ) ) {
953
- /**
954
- * Get a translatable text and its text domain.
955
- *
956
- * When the text is overridden by the module, returns the overridden text and the text domain of the module. Otherwise, returns the original text and 'freemius' as the text domain.
957
- *
958
- * @author Vova Feldman (@svovaf)
959
- * @since 1.2.1.7
960
- *
961
- * @param string $text Translatable string.
962
- * @param string $key String key for overrides.
963
- * @param string $slug Module slug for overrides.
964
- *
965
- * @return string[]
966
- */
967
- function fs_text_and_domain( $text, $key, $slug ) {
968
- $override = fs_text_override( $text, $key, $slug );
969
-
970
- if ( false === $override ) {
971
- // No override, use FS text domain.
972
- $text_domain = 'freemius';
973
- } else {
974
- // Found an override.
975
- $text = $override;
976
- // Use the module's text domain.
977
- $text_domain = $slug;
978
- }
979
-
980
- return array( $text, $text_domain );
981
- }
982
- }
983
-
984
- if ( ! function_exists( '_fs_text_inline' ) ) {
985
- /**
986
- * Retrieve an inline translated text by key.
987
- *
988
- * @author Vova Feldman (@svovaf)
989
- * @since 1.2.3
990
- *
991
- * @param string $text Translatable string.
992
- * @param string $key String key for overrides.
993
- * @param string $slug Module slug for overrides.
994
- *
995
- * @return string
996
- *
997
- * @global $fs_text_overrides
998
- */
999
- function _fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
1000
- list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
1001
-
1002
- // Avoid misleading Theme Check warning.
1003
- $fn = 'translate';
1004
-
1005
- return $fn( $text, $text_domain );
1006
- }
1007
- }
1008
-
1009
- if ( ! function_exists( 'fs_text_inline' ) ) {
1010
- /**
1011
- * Retrieve an inline translated text by key.
1012
- *
1013
- * @author Vova Feldman (@svovaf)
1014
- * @since 1.2.3
1015
- *
1016
- * @param string $text Translatable string.
1017
- * @param string $key String key for overrides.
1018
- * @param string $slug Module slug for overrides.
1019
- *
1020
- * @return string
1021
- *
1022
- * @global $fs_text_overrides
1023
- */
1024
- function fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
1025
- return _fs_text_inline( $text, $key, $slug );
1026
- }
1027
- }
1028
-
1029
- if ( ! function_exists( 'fs_esc_attr' ) ) {
1030
- /**
1031
- * @author Vova Feldman
1032
- * @since 1.2.1.6
1033
- *
1034
- * @param string $key
1035
- * @param string $slug
1036
- *
1037
- * @return string
1038
- */
1039
- function fs_esc_attr( $key, $slug ) {
1040
- return esc_attr( fs_text( $key, $slug ) );
1041
- }
1042
- }
1043
-
1044
- if ( ! function_exists( 'fs_esc_attr_inline' ) ) {
1045
- /**
1046
- * @author Vova Feldman (@svovaf)
1047
- * @since 1.2.3
1048
- *
1049
- * @param string $text Translatable string.
1050
- * @param string $key String key for overrides.
1051
- * @param string $slug Module slug for overrides.
1052
- *
1053
- * @return string
1054
- */
1055
- function fs_esc_attr_inline( $text, $key = '', $slug = 'freemius' ) {
1056
- return esc_attr( _fs_text_inline( $text, $key, $slug ) );
1057
- }
1058
- }
1059
-
1060
- if ( ! function_exists( 'fs_esc_attr_x_inline' ) ) {
1061
- /**
1062
- * @author Vova Feldman (@svovaf)
1063
- * @since 1.2.3
1064
- *
1065
- * @param string $text Translatable string.
1066
- * @param string $context Context information for the translators.
1067
- * @param string $key String key for overrides.
1068
- * @param string $slug Module slug for overrides.
1069
- *
1070
- * @return string
1071
- */
1072
- function fs_esc_attr_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1073
- return esc_attr( _fs_text_x_inline( $text, $context, $key, $slug ) );
1074
- }
1075
- }
1076
-
1077
- if ( ! function_exists( 'fs_esc_attr_echo' ) ) {
1078
- /**
1079
- * @author Vova Feldman
1080
- * @since 1.2.1.6
1081
- *
1082
- * @param string $key
1083
- * @param string $slug
1084
- */
1085
- function fs_esc_attr_echo( $key, $slug ) {
1086
- echo esc_attr( fs_text( $key, $slug ) );
1087
- }
1088
- }
1089
-
1090
- if ( ! function_exists( 'fs_esc_attr_echo_inline' ) ) {
1091
- /**
1092
- * @author Vova Feldman (@svovaf)
1093
- * @since 1.2.3
1094
- *
1095
- * @param string $text Translatable string.
1096
- * @param string $key String key for overrides.
1097
- * @param string $slug Module slug for overrides.
1098
- */
1099
- function fs_esc_attr_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1100
- echo esc_attr( _fs_text_inline( $text, $key, $slug ) );
1101
- }
1102
- }
1103
-
1104
- if ( ! function_exists( 'fs_esc_js' ) ) {
1105
- /**
1106
- * @author Vova Feldman
1107
- * @since 1.2.1.6
1108
- *
1109
- * @param string $key
1110
- * @param string $slug
1111
- *
1112
- * @return string
1113
- */
1114
- function fs_esc_js( $key, $slug ) {
1115
- return esc_js( fs_text( $key, $slug ) );
1116
- }
1117
- }
1118
-
1119
- if ( ! function_exists( 'fs_esc_js_inline' ) ) {
1120
- /**
1121
- * @author Vova Feldman (@svovaf)
1122
- * @since 1.2.3
1123
- *
1124
- * @param string $text Translatable string.
1125
- * @param string $key String key for overrides.
1126
- * @param string $slug Module slug for overrides.
1127
- *
1128
- * @return string
1129
- */
1130
- function fs_esc_js_inline( $text, $key = '', $slug = 'freemius' ) {
1131
- return esc_js( _fs_text_inline( $text, $key, $slug ) );
1132
- }
1133
- }
1134
-
1135
- if ( ! function_exists( 'fs_esc_js_x_inline' ) ) {
1136
- /**
1137
- * @author Vova Feldman (@svovaf)
1138
- * @since 1.2.3
1139
- *
1140
- * @param string $text Translatable string.
1141
- * @param string $context Context information for the translators.
1142
- * @param string $key String key for overrides.
1143
- * @param string $slug Module slug for overrides.
1144
- *
1145
- * @return string
1146
- */
1147
- function fs_esc_js_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1148
- return esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
1149
- }
1150
- }
1151
-
1152
- if ( ! function_exists( 'fs_esc_js_echo_x_inline' ) ) {
1153
- /**
1154
- * @author Vova Feldman (@svovaf)
1155
- * @since 1.2.3
1156
- *
1157
- * @param string $text Translatable string.
1158
- * @param string $context Context information for the translators.
1159
- * @param string $key String key for overrides.
1160
- * @param string $slug Module slug for overrides.
1161
- *
1162
- * @return string
1163
- */
1164
- function fs_esc_js_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1165
- echo esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
1166
- }
1167
- }
1168
-
1169
- if ( ! function_exists( 'fs_esc_js_echo' ) ) {
1170
- /**
1171
- * @author Vova Feldman
1172
- * @since 1.2.1.6
1173
- *
1174
- * @param string $key
1175
- * @param string $slug
1176
- */
1177
- function fs_esc_js_echo( $key, $slug ) {
1178
- echo esc_js( fs_text( $key, $slug ) );
1179
- }
1180
- }
1181
-
1182
- if ( ! function_exists( 'fs_esc_js_echo_inline' ) ) {
1183
- /**
1184
- * @author Vova Feldman (@svovaf)
1185
- * @since 1.2.3
1186
- *
1187
- * @param string $text Translatable string.
1188
- * @param string $key String key for overrides.
1189
- * @param string $slug Module slug for overrides.
1190
- */
1191
- function fs_esc_js_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1192
- echo esc_js( _fs_text_inline( $text, $key, $slug ) );
1193
- }
1194
- }
1195
-
1196
- if ( ! function_exists( 'fs_json_encode_echo' ) ) {
1197
- /**
1198
- * @author Vova Feldman
1199
- * @since 1.2.1.6
1200
- *
1201
- * @param string $key
1202
- * @param string $slug
1203
- */
1204
- function fs_json_encode_echo( $key, $slug ) {
1205
- echo json_encode( fs_text( $key, $slug ) );
1206
- }
1207
- }
1208
-
1209
- if ( ! function_exists( 'fs_json_encode_echo_inline' ) ) {
1210
- /**
1211
- * @author Vova Feldman (@svovaf)
1212
- * @since 1.2.3
1213
- *
1214
- * @param string $text Translatable string.
1215
- * @param string $key String key for overrides.
1216
- * @param string $slug Module slug for overrides.
1217
- */
1218
- function fs_json_encode_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1219
- echo json_encode( _fs_text_inline( $text, $key, $slug ) );
1220
- }
1221
- }
1222
-
1223
- if ( ! function_exists( 'fs_esc_html' ) ) {
1224
- /**
1225
- * @author Vova Feldman
1226
- * @since 1.2.1.6
1227
- *
1228
- * @param string $key
1229
- * @param string $slug
1230
- *
1231
- * @return string
1232
- */
1233
- function fs_esc_html( $key, $slug ) {
1234
- return esc_html( fs_text( $key, $slug ) );
1235
- }
1236
- }
1237
-
1238
- if ( ! function_exists( 'fs_esc_html_inline' ) ) {
1239
- /**
1240
- * @author Vova Feldman (@svovaf)
1241
- * @since 1.2.3
1242
- *
1243
- * @param string $text Translatable string.
1244
- * @param string $key String key for overrides.
1245
- * @param string $slug Module slug for overrides.
1246
- *
1247
- * @return string
1248
- */
1249
- function fs_esc_html_inline( $text, $key = '', $slug = 'freemius' ) {
1250
- return esc_html( _fs_text_inline( $text, $key, $slug ) );
1251
- }
1252
- }
1253
-
1254
- if ( ! function_exists( 'fs_esc_html_x_inline' ) ) {
1255
- /**
1256
- * @author Vova Feldman (@svovaf)
1257
- * @since 1.2.3
1258
- *
1259
- * @param string $text Translatable string.
1260
- * @param string $context Context information for the translators.
1261
- * @param string $key String key for overrides.
1262
- * @param string $slug Module slug for overrides.
1263
- *
1264
- * @return string
1265
- */
1266
- function fs_esc_html_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1267
- return esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) );
1268
- }
1269
- }
1270
-
1271
- if ( ! function_exists( 'fs_esc_html_echo_x_inline' ) ) {
1272
- /**
1273
- * @author Vova Feldman (@svovaf)
1274
- * @since 1.2.3
1275
- *
1276
- * @param string $text Translatable string.
1277
- * @param string $context Context information for the translators.
1278
- * @param string $key String key for overrides.
1279
- * @param string $slug Module slug for overrides.
1280
- */
1281
- function fs_esc_html_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1282
- echo esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) );
1283
- }
1284
- }
1285
-
1286
- if ( ! function_exists( 'fs_esc_html_echo' ) ) {
1287
- /**
1288
- * @author Vova Feldman
1289
- * @since 1.2.1.6
1290
- *
1291
- * @param string $key
1292
- * @param string $slug
1293
- */
1294
- function fs_esc_html_echo( $key, $slug ) {
1295
- echo esc_html( fs_text( $key, $slug ) );
1296
- }
1297
- }
1298
-
1299
- if ( ! function_exists( 'fs_esc_html_echo_inline' ) ) {
1300
- /**
1301
- * @author Vova Feldman (@svovaf)
1302
- * @since 1.2.3
1303
- *
1304
- * @param string $text Translatable string.
1305
- * @param string $key String key for overrides.
1306
- * @param string $slug Module slug for overrides.
1307
- */
1308
- function fs_esc_html_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1309
- echo esc_html( _fs_text_inline( $text, $key, $slug ) );
1310
- }
1311
- }
1312
-
1313
- if ( ! function_exists( 'fs_override_i18n' ) ) {
1314
- /**
1315
- * Override default i18n text phrases.
1316
- *
1317
- * @author Vova Feldman (@svovaf)
1318
- * @since 1.1.6
1319
- *
1320
- * @param array[string]string $key_value
1321
- * @param string $slug
1322
- *
1323
- * @global $fs_text_overrides
1324
- */
1325
- function fs_override_i18n( array $key_value, $slug = 'freemius' ) {
1326
- global $fs_text_overrides;
1327
-
1328
- if ( ! isset( $fs_text_overrides[ $slug ] ) ) {
1329
- $fs_text_overrides[ $slug ] = array();
1330
- }
1331
-
1332
- foreach ( $key_value as $key => $value ) {
1333
- $fs_text_overrides[ $slug ][ $key ] = $value;
1334
- }
1335
- }
1336
- }
1337
-
1338
- #endregion
1339
-
1340
- #--------------------------------------------------------------------------------
1341
- #region Multisite Network
1342
- #--------------------------------------------------------------------------------
1343
-
1344
- if ( ! function_exists( 'fs_is_plugin_uninstall' ) ) {
1345
- /**
1346
- * @author Vova Feldman (@svovaf)
1347
- * @since 2.0.0
1348
- */
1349
- function fs_is_plugin_uninstall() {
1350
- return (
1351
- defined( 'WP_UNINSTALL_PLUGIN' ) ||
1352
- ( 0 < did_action( 'update_option_uninstall_plugins' ) )
1353
- );
1354
- }
1355
- }
1356
-
1357
- if ( ! function_exists( 'fs_is_network_admin' ) ) {
1358
- /**
1359
- * Unlike is_network_admin(), this one will also work properly when
1360
- * the context execution is WP AJAX handler, and during plugin
1361
- * uninstall.
1362
- *
1363
- * @author Vova Feldman (@svovaf)
1364
- * @since 2.0.0
1365
- */
1366
- function fs_is_network_admin() {
1367
- return (
1368
- WP_FS__IS_NETWORK_ADMIN ||
1369
- ( is_multisite() && fs_is_plugin_uninstall() )
1370
- );
1371
- }
1372
- }
1373
-
1374
- if ( ! function_exists( 'fs_is_blog_admin' ) ) {
1375
- /**
1376
- * Unlike is_blog_admin(), this one will also work properly when
1377
- * the context execution is WP AJAX handler, and during plugin
1378
- * uninstall.
1379
- *
1380
- * @author Vova Feldman (@svovaf)
1381
- * @since 2.0.0
1382
- */
1383
- function fs_is_blog_admin() {
1384
- return (
1385
- WP_FS__IS_BLOG_ADMIN ||
1386
- ( ! is_multisite() && fs_is_plugin_uninstall() )
1387
- );
1388
- }
1389
- }
1390
-
1391
- #endregion
1392
-
1393
- if ( ! function_exists( 'fs_apply_filter' ) ) {
1394
- /**
1395
- * Apply filter for specific plugin.
1396
- *
1397
- * @author Vova Feldman (@svovaf)
1398
- * @since 1.0.9
1399
- *
1400
- * @param string $module_unique_affix Module's unique affix.
1401
- * @param string $tag The name of the filter hook.
1402
- * @param mixed $value The value on which the filters hooked to `$tag` are applied on.
1403
- *
1404
- * @return mixed The filtered value after all hooked functions are applied to it.
1405
- *
1406
- * @uses apply_filters()
1407
- */
1408
- function fs_apply_filter( $module_unique_affix, $tag, $value ) {
1409
- $args = func_get_args();
1410
-
1411
- return call_user_func_array( 'apply_filters', array_merge(
1412
- array( "fs_{$tag}_{$module_unique_affix}" ),
1413
- array_slice( $args, 2 ) )
1414
- );
1415
- }
1416
  }
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.0.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ if ( ! function_exists( 'fs_dummy' ) ) {
14
+ function fs_dummy() {
15
+ }
16
+ }
17
+
18
+ /* Url.
19
+ --------------------------------------------------------------------------------------------*/
20
+ if ( ! function_exists( 'fs_get_url_daily_cache_killer' ) ) {
21
+ function fs_get_url_daily_cache_killer() {
22
+ return date( '\YY\Mm\Dd' );
23
+ }
24
+ }
25
+
26
+ /* Templates / Views.
27
+ --------------------------------------------------------------------------------------------*/
28
+ if ( ! function_exists( 'fs_get_template_path' ) ) {
29
+ function fs_get_template_path( $path ) {
30
+ return WP_FS__DIR_TEMPLATES . '/' . trim( $path, '/' );
31
+ }
32
+
33
+ function fs_include_template( $path, &$params = null ) {
34
+ $VARS = &$params;
35
+ include fs_get_template_path( $path );
36
+ }
37
+
38
+ function fs_include_once_template( $path, &$params = null ) {
39
+ $VARS = &$params;
40
+ include_once fs_get_template_path( $path );
41
+ }
42
+
43
+ function fs_require_template( $path, &$params = null ) {
44
+ $VARS = &$params;
45
+ require fs_get_template_path( $path );
46
+ }
47
+
48
+ function fs_require_once_template( $path, &$params = null ) {
49
+ $VARS = &$params;
50
+ require_once fs_get_template_path( $path );
51
+ }
52
+
53
+ function fs_get_template( $path, &$params = null ) {
54
+ ob_start();
55
+
56
+ $VARS = &$params;
57
+ require fs_get_template_path( $path );
58
+
59
+ return ob_get_clean();
60
+ }
61
+ }
62
+
63
+ /* Scripts and styles including.
64
+ --------------------------------------------------------------------------------------------*/
65
+
66
+ if ( ! function_exists( 'fs_asset_url' ) ) {
67
+ /**
68
+ * Generates an absolute URL to the given path. This function ensures that the URL will be correct whether the asset
69
+ * is inside a plugin's folder or a theme's folder.
70
+ *
71
+ * Examples:
72
+ * 1. "themes" folder
73
+ * Path: C:/xampp/htdocs/fswp/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
74
+ * URL: http://fswp:8080/wp-content/themes/twentytwelve/freemius/assets/css/admin/common.css
75
+ *
76
+ * 2. "plugins" folder
77
+ * Path: C:/xampp/htdocs/fswp/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
78
+ * URL: http://fswp:8080/wp-content/plugins/rating-widget-premium/freemius/assets/css/admin/common.css
79
+ *
80
+ * @author Leo Fajardo (@leorw)
81
+ * @since 1.2.2
82
+ *
83
+ * @param string $asset_abs_path Asset's absolute path.
84
+ *
85
+ * @return string Asset's URL.
86
+ */
87
+ function fs_asset_url( $asset_abs_path ) {
88
+ $wp_content_dir = fs_normalize_path( WP_CONTENT_DIR );
89
+ $asset_abs_path = fs_normalize_path( $asset_abs_path );
90
+
91
+ if ( 0 === strpos( $asset_abs_path, $wp_content_dir ) ) {
92
+ // Handle both theme and plugin assets located in the standard directories.
93
+ $asset_rel_path = str_replace( $wp_content_dir, '', $asset_abs_path );
94
+ $asset_url = content_url( fs_normalize_path( $asset_rel_path ) );
95
+ } else {
96
+ $wp_plugins_dir = fs_normalize_path( WP_PLUGIN_DIR );
97
+ if ( 0 === strpos( $asset_abs_path, $wp_plugins_dir ) ) {
98
+ // Try to handle plugin assets that may be located in a non-standard plugins directory.
99
+ $asset_rel_path = str_replace( $wp_plugins_dir, '', $asset_abs_path );
100
+ $asset_url = plugins_url( fs_normalize_path( $asset_rel_path ) );
101
+ } else {
102
+ // Try to handle theme assets that may be located in a non-standard themes directory.
103
+ $active_theme_stylesheet = get_stylesheet();
104
+ $wp_themes_dir = fs_normalize_path( trailingslashit( get_theme_root( $active_theme_stylesheet ) ) );
105
+ $asset_rel_path = str_replace( $wp_themes_dir, '', fs_normalize_path( $asset_abs_path ) );
106
+ $asset_url = trailingslashit( get_theme_root_uri( $active_theme_stylesheet ) ) . fs_normalize_path( $asset_rel_path );
107
+ }
108
+ }
109
+
110
+ return $asset_url;
111
+ }
112
+ }
113
+
114
+ if ( ! function_exists( 'fs_enqueue_local_style' ) ) {
115
+ function fs_enqueue_local_style( $handle, $path, $deps = array(), $ver = false, $media = 'all' ) {
116
+ wp_enqueue_style( $handle, fs_asset_url( WP_FS__DIR_CSS . '/' . trim( $path, '/' ) ), $deps, $ver, $media );
117
+ }
118
+ }
119
+
120
+ if ( ! function_exists( 'fs_enqueue_local_script' ) ) {
121
+ function fs_enqueue_local_script( $handle, $path, $deps = array(), $ver = false, $in_footer = 'all' ) {
122
+ wp_enqueue_script( $handle, fs_asset_url( WP_FS__DIR_JS . '/' . trim( $path, '/' ) ), $deps, $ver, $in_footer );
123
+ }
124
+ }
125
+
126
+ if ( ! function_exists( 'fs_img_url' ) ) {
127
+ function fs_img_url( $path, $img_dir = WP_FS__DIR_IMG ) {
128
+ return ( fs_asset_url( $img_dir . '/' . trim( $path, '/' ) ) );
129
+ }
130
+ }
131
+
132
+ #--------------------------------------------------------------------------------
133
+ #region Request handlers.
134
+ #--------------------------------------------------------------------------------
135
+
136
+ if ( ! function_exists( 'fs_request_get' ) ) {
137
+ /**
138
+ * A helper method to fetch GET/POST user input with an optional default value when the input is not set.
139
+ * @author Vova Feldman (@svovaf)
140
+ *
141
+ * @param string $key
142
+ * @param mixed $def
143
+ * @param string|bool $type Since 1.2.1.7 - when set to 'get' will look for the value passed via querystring, when
144
+ * set to 'post' will look for the value passed via the POST request's body, otherwise,
145
+ * will check if the parameter was passed in any of the two.
146
+ *
147
+ * @return mixed
148
+ */
149
+ function fs_request_get( $key, $def = false, $type = false ) {
150
+ if ( is_string( $type ) ) {
151
+ $type = strtolower( $type );
152
+ }
153
+
154
+ /**
155
+ * Note to WordPress.org Reviewers:
156
+ * This is a helper method to fetch GET/POST user input with an optional default value when the input is not set. The actual sanitization is done in the scope of the function's usage.
157
+ */
158
+ switch ( $type ) {
159
+ case 'post':
160
+ $value = isset( $_POST[ $key ] ) ? $_POST[ $key ] : $def;
161
+ break;
162
+ case 'get':
163
+ $value = isset( $_GET[ $key ] ) ? $_GET[ $key ] : $def;
164
+ break;
165
+ default:
166
+ $value = isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $def;
167
+ break;
168
+ }
169
+
170
+ return $value;
171
+ }
172
+ }
173
+
174
+ if ( ! function_exists( 'fs_request_has' ) ) {
175
+ function fs_request_has( $key ) {
176
+ return isset( $_REQUEST[ $key ] );
177
+ }
178
+ }
179
+
180
+ if ( ! function_exists( 'fs_request_get_bool' ) ) {
181
+ /**
182
+ * A helper method to fetch GET/POST user boolean input with an optional default value when the input is not set.
183
+ *
184
+ * @author Vova Feldman (@svovaf)
185
+ *
186
+ * @param string $key
187
+ * @param bool $def
188
+ *
189
+ * @return bool|mixed
190
+ */
191
+ function fs_request_get_bool( $key, $def = false ) {
192
+ $val = fs_request_get( $key, null );
193
+
194
+ if ( is_null( $val ) ) {
195
+ return $def;
196
+ }
197
+
198
+ if ( is_bool( $val ) ) {
199
+ return $val;
200
+ } else if ( is_numeric( $val ) ) {
201
+ if ( 1 == $val ) {
202
+ return true;
203
+ } else if ( 0 == $val ) {
204
+ return false;
205
+ }
206
+ } else if ( is_string( $val ) ) {
207
+ $val = strtolower( $val );
208
+
209
+ if ( 'true' === $val ) {
210
+ return true;
211
+ } else if ( 'false' === $val ) {
212
+ return false;
213
+ }
214
+ }
215
+
216
+ return $def;
217
+ }
218
+ }
219
+
220
+ if ( ! function_exists( 'fs_request_is_post' ) ) {
221
+ function fs_request_is_post() {
222
+ return ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) );
223
+ }
224
+ }
225
+
226
+ if ( ! function_exists( 'fs_request_is_get' ) ) {
227
+ function fs_request_is_get() {
228
+ return ( 'get' === strtolower( $_SERVER['REQUEST_METHOD'] ) );
229
+ }
230
+ }
231
+
232
+ if ( ! function_exists( 'fs_get_action' ) ) {
233
+ function fs_get_action( $action_key = 'action' ) {
234
+ if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
235
+ return strtolower( $_REQUEST[ $action_key ] );
236
+ }
237
+
238
+ if ( 'action' == $action_key ) {
239
+ $action_key = 'fs_action';
240
+
241
+ if ( ! empty( $_REQUEST[ $action_key ] ) && is_string( $_REQUEST[ $action_key ] ) ) {
242
+ return strtolower( $_REQUEST[ $action_key ] );
243
+ }
244
+ }
245
+
246
+ return false;
247
+ }
248
+ }
249
+
250
+ if ( ! function_exists( 'fs_request_is_action' ) ) {
251
+ function fs_request_is_action( $action, $action_key = 'action' ) {
252
+ return ( strtolower( $action ) === fs_get_action( $action_key ) );
253
+ }
254
+ }
255
+
256
+ if ( ! function_exists( 'fs_request_is_action_secure' ) ) {
257
+ /**
258
+ * @author Vova Feldman (@svovaf)
259
+ * @since 1.0.0
260
+ *
261
+ * @since 1.2.1.5 Allow nonce verification.
262
+ *
263
+ * @param string $action
264
+ * @param string $action_key
265
+ * @param string $nonce_key
266
+ *
267
+ * @return bool
268
+ */
269
+ function fs_request_is_action_secure(
270
+ $action,
271
+ $action_key = 'action',
272
+ $nonce_key = 'nonce'
273
+ ) {
274
+ if ( strtolower( $action ) !== fs_get_action( $action_key ) ) {
275
+ return false;
276
+ }
277
+
278
+ $nonce = ! empty( $_REQUEST[ $nonce_key ] ) ?
279
+ $_REQUEST[ $nonce_key ] :
280
+ '';
281
+
282
+ if ( empty( $nonce ) ||
283
+ ( false === wp_verify_nonce( $nonce, $action ) )
284
+ ) {
285
+ return false;
286
+ }
287
+
288
+ return true;
289
+ }
290
+ }
291
+
292
+ #endregion
293
+
294
+ if ( ! function_exists( 'fs_is_plugin_page' ) ) {
295
+ function fs_is_plugin_page( $page_slug ) {
296
+ return ( is_admin() && $page_slug === fs_request_get( 'page' ) );
297
+ }
298
+ }
299
+
300
+ if ( ! function_exists( 'fs_get_raw_referer' ) ) {
301
+ /**
302
+ * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer.
303
+ *
304
+ * Do not use for redirects, use {@see wp_get_referer()} instead.
305
+ *
306
+ * @since 1.2.3
307
+ *
308
+ * @return string|false Referer URL on success, false on failure.
309
+ */
310
+ function fs_get_raw_referer() {
311
+ if ( function_exists( 'wp_get_raw_referer' ) ) {
312
+ return wp_get_raw_referer();
313
+ }
314
+ if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
315
+ return wp_unslash( $_REQUEST['_wp_http_referer'] );
316
+ } else if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
317
+ return wp_unslash( $_SERVER['HTTP_REFERER'] );
318
+ }
319
+
320
+ return false;
321
+ }
322
+ }
323
+
324
+ /* Core UI.
325
+ --------------------------------------------------------------------------------------------*/
326
+ if ( ! function_exists( 'fs_ui_action_button' ) ) {
327
+ /**
328
+ * @param number $module_id
329
+ * @param string $page
330
+ * @param string $action
331
+ * @param string $title
332
+ * @param string $button_class
333
+ * @param array $params
334
+ * @param bool $is_primary
335
+ * @param bool $is_small
336
+ * @param string|bool $icon_class Optional class for an icon (since 1.1.7).
337
+ * @param string|bool $confirmation Optional confirmation message before submit (since 1.1.7).
338
+ * @param string $method Since 1.1.7
339
+ *
340
+ * @uses fs_ui_get_action_button()
341
+ */
342
+ function fs_ui_action_button(
343
+ $module_id,
344
+ $page,
345
+ $action,
346
+ $title,
347
+ $button_class = '',
348
+ $params = array(),
349
+ $is_primary = true,
350
+ $is_small = false,
351
+ $icon_class = false,
352
+ $confirmation = false,
353
+ $method = 'GET'
354
+ ) {
355
+ echo fs_ui_get_action_button(
356
+ $module_id,
357
+ $page,
358
+ $action,
359
+ $title,
360
+ $button_class,
361
+ $params,
362
+ $is_primary,
363
+ $is_small,
364
+ $icon_class,
365
+ $confirmation,
366
+ $method
367
+ );
368
+ }
369
+ }
370
+
371
+ if ( ! function_exists( 'fs_ui_get_action_button' ) ) {
372
+ /**
373
+ * @author Vova Feldman (@svovaf)
374
+ * @since 1.1.7
375
+ *
376
+ * @param number $module_id
377
+ * @param string $page
378
+ * @param string $action
379
+ * @param string $title
380
+ * @param string $button_class
381
+ * @param array $params
382
+ * @param bool $is_primary
383
+ * @param bool $is_small
384
+ * @param string|bool $icon_class Optional class for an icon.
385
+ * @param string|bool $confirmation Optional confirmation message before submit.
386
+ * @param string $method
387
+ *
388
+ * @return string
389
+ */
390
+ function fs_ui_get_action_button(
391
+ $module_id,
392
+ $page,
393
+ $action,
394
+ $title,
395
+ $button_class = '',
396
+ $params = array(),
397
+ $is_primary = true,
398
+ $is_small = false,
399
+ $icon_class = false,
400
+ $confirmation = false,
401
+ $method = 'GET'
402
+ ) {
403
+ // Prepend icon (if set).
404
+ $title = ( is_string( $icon_class ) ? '<i class="' . $icon_class . '"></i> ' : '' ) . $title;
405
+
406
+ if ( is_string( $confirmation ) ) {
407
+ return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="if (confirm(\'%s\')) this.parentNode.submit(); return false;">%s</a></form>',
408
+ freemius( $module_id )->_get_admin_page_url( $page, $params ),
409
+ $method,
410
+ $action,
411
+ wp_nonce_field( $action, '_wpnonce', true, false ),
412
+ 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
413
+ $confirmation,
414
+ $title
415
+ );
416
+ } else if ( 'GET' !== strtoupper( $method ) ) {
417
+ return sprintf( '<form action="%s" method="%s"><input type="hidden" name="fs_action" value="%s">%s<a href="#" class="%s" onclick="this.parentNode.submit(); return false;">%s</a></form>',
418
+ freemius( $module_id )->_get_admin_page_url( $page, $params ),
419
+ $method,
420
+ $action,
421
+ wp_nonce_field( $action, '_wpnonce', true, false ),
422
+ 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
423
+ $title
424
+ );
425
+ } else {
426
+ return sprintf( '<a href="%s" class="%s">%s</a></form>',
427
+ wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ),
428
+ 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ),
429
+ $title
430
+ );
431
+ }
432
+ }
433
+
434
+ function fs_ui_action_link( $module_id, $page, $action, $title, $params = array() ) {
435
+ ?><a class=""
436
+ href="<?php echo wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ) ?>"><?php echo $title ?></a><?php
437
+ }
438
+ }
439
+
440
+ if ( ! function_exists( 'fs_get_entity' ) ) {
441
+ /**
442
+ * @author Leo Fajardo (@leorw)
443
+ * @since 2.3.1
444
+ *
445
+ * @param mixed $entity
446
+ * @param string $class
447
+ *
448
+ * @return FS_Plugin|FS_User|FS_Site|FS_Plugin_License|FS_Plugin_Plan|FS_Plugin_Tag|FS_Subscription
449
+ */
450
+ function fs_get_entity( $entity, $class ) {
451
+ if ( ! is_object( $entity ) || $entity instanceof $class ) {
452
+ return $entity;
453
+ }
454
+
455
+ return new $class( $entity );
456
+ }
457
+ }
458
+
459
+ if ( ! function_exists( 'fs_get_entities' ) ) {
460
+ /**
461
+ * @author Leo Fajardo (@leorw)
462
+ * @since 2.3.1
463
+ *
464
+ * @param mixed $entities
465
+ * @param string $class_name
466
+ *
467
+ * @return FS_Plugin[]|FS_User[]|FS_Site[]|FS_Plugin_License[]|FS_Plugin_Plan[]|FS_Plugin_Tag[]|FS_Subscription[]
468
+ */
469
+ function fs_get_entities( $entities, $class_name ) {
470
+ if ( ! is_array( $entities ) || empty( $entities ) ) {
471
+ return $entities;
472
+ }
473
+
474
+ // Get first element.
475
+ $first_array_element = reset( $entities );
476
+
477
+ if ( $first_array_element instanceof $class_name ) {
478
+ /**
479
+ * If the first element of the array is an instance of the context class, assume that all other
480
+ * elements are instances of the class.
481
+ */
482
+ return $entities;
483
+ }
484
+
485
+ if (
486
+ is_array( $first_array_element ) &&
487
+ ! empty( $first_array_element )
488
+ ) {
489
+ $first_array_element = reset( $first_array_element );
490
+
491
+ if ( $first_array_element instanceof $class_name ) {
492
+ /**
493
+ * If the first element of the `$entities` array is an array whose first element is an instance of the
494
+ * context class, assume that all other objects are instances of the class.
495
+ */
496
+ return $entities;
497
+ }
498
+ }
499
+
500
+ foreach ( $entities as $key => $entities_or_entity ) {
501
+ if ( is_array( $entities_or_entity ) ) {
502
+ $entities[ $key ] = fs_get_entities( $entities_or_entity, $class_name );
503
+ } else {
504
+ $entities[ $key ] = fs_get_entity( $entities_or_entity, $class_name );
505
+ }
506
+ }
507
+
508
+ return $entities;
509
+ }
510
+ }
511
+
512
+ if ( ! function_exists( 'fs_nonce_url' ) ) {
513
+ /**
514
+ * Retrieve URL with nonce added to URL query.
515
+ *
516
+ * Originally was using `wp_nonce_url()` but the new version
517
+ * changed the return value to escaped URL, that's not the expected
518
+ * behaviour.
519
+ *
520
+ * @author Vova Feldman (@svovaf)
521
+ * @since ~1.1.3
522
+ *
523
+ * @param string $actionurl URL to add nonce action.
524
+ * @param int|string $action Optional. Nonce action name. Default -1.
525
+ * @param string $name Optional. Nonce name. Default '_wpnonce'.
526
+ *
527
+ * @return string Escaped URL with nonce action added.
528
+ */
529
+ function fs_nonce_url( $actionurl, $action = - 1, $name = '_wpnonce' ) {
530
+ return add_query_arg( $name, wp_create_nonce( $action ), $actionurl );
531
+ }
532
+ }
533
+
534
+ if ( ! function_exists( 'fs_starts_with' ) ) {
535
+ /**
536
+ * Check if string starts with.
537
+ *
538
+ * @author Vova Feldman (@svovaf)
539
+ * @since 1.1.3
540
+ *
541
+ * @param string $haystack
542
+ * @param string $needle
543
+ *
544
+ * @return bool
545
+ */
546
+ function fs_starts_with( $haystack, $needle ) {
547
+ $length = strlen( $needle );
548
+
549
+ return ( substr( $haystack, 0, $length ) === $needle );
550
+ }
551
+ }
552
+
553
+ if ( ! function_exists( 'fs_ends_with' ) ) {
554
+ /**
555
+ * Check if string ends with.
556
+ *
557
+ * @author Vova Feldman (@svovaf)
558
+ * @since 2.0.0
559
+ *
560
+ * @param string $haystack
561
+ * @param string $needle
562
+ *
563
+ * @return bool
564
+ */
565
+ function fs_ends_with( $haystack, $needle ) {
566
+ $length = strlen( $needle );
567
+ $start = $length * - 1; // negative
568
+
569
+ return ( substr( $haystack, $start ) === $needle );
570
+ }
571
+ }
572
+
573
+ if ( ! function_exists( 'fs_strip_url_protocol' ) ) {
574
+ function fs_strip_url_protocol( $url ) {
575
+ if ( ! fs_starts_with( $url, 'http' ) ) {
576
+ return $url;
577
+ }
578
+
579
+ $protocol_pos = strpos( $url, '://' );
580
+
581
+ if ( $protocol_pos > 5 ) {
582
+ return $url;
583
+ }
584
+
585
+ return substr( $url, $protocol_pos + 3 );
586
+ }
587
+ }
588
+
589
+ #region Url Canonization ------------------------------------------------------------------
590
+
591
+ if ( ! function_exists( 'fs_canonize_url' ) ) {
592
+ /**
593
+ * @author Vova Feldman (@svovaf)
594
+ * @since 1.1.3
595
+ *
596
+ * @param string $url
597
+ * @param bool $omit_host
598
+ * @param array $ignore_params
599
+ *
600
+ * @return string
601
+ */
602
+ function fs_canonize_url( $url, $omit_host = false, $ignore_params = array() ) {
603
+ $parsed_url = parse_url( strtolower( $url ) );
604
+
605
+ // if ( ! isset( $parsed_url['host'] ) ) {
606
+ // return $url;
607
+ // }
608
+
609
+ $canonical = ( ( $omit_host || ! isset( $parsed_url['host'] ) ) ? '' : $parsed_url['host'] ) . $parsed_url['path'];
610
+
611
+ if ( isset( $parsed_url['query'] ) ) {
612
+ parse_str( $parsed_url['query'], $queryString );
613
+ $canonical .= '?' . fs_canonize_query_string( $queryString, $ignore_params );
614
+ }
615
+
616
+ return $canonical;
617
+ }
618
+ }
619
+
620
+ if ( ! function_exists( 'fs_canonize_query_string' ) ) {
621
+ /**
622
+ * @author Vova Feldman (@svovaf)
623
+ * @since 1.1.3
624
+ *
625
+ * @param array $params
626
+ * @param array $ignore_params
627
+ * @param bool $params_prefix
628
+ *
629
+ * @return string
630
+ */
631
+ function fs_canonize_query_string( array $params, array &$ignore_params, $params_prefix = false ) {
632
+ if ( ! is_array( $params ) || 0 === count( $params ) ) {
633
+ return '';
634
+ }
635
+
636
+ // Url encode both keys and values
637
+ $keys = fs_urlencode_rfc3986( array_keys( $params ) );
638
+ $values = fs_urlencode_rfc3986( array_values( $params ) );
639
+ $params = array_combine( $keys, $values );
640
+
641
+ // Parameters are sorted by name, using lexicographical byte value ordering.
642
+ // Ref: Spec: 9.1.1 (1)
643
+ uksort( $params, 'strcmp' );
644
+
645
+ $pairs = array();
646
+ foreach ( $params as $parameter => $value ) {
647
+ $lower_param = strtolower( $parameter );
648
+
649
+ // Skip ignore params.
650
+ if ( in_array( $lower_param, $ignore_params ) ||
651
+ ( false !== $params_prefix && fs_starts_with( $lower_param, $params_prefix ) )
652
+ ) {
653
+ continue;
654
+ }
655
+
656
+ if ( is_array( $value ) ) {
657
+ // If two or more parameters share the same name, they are sorted by their value
658
+ // Ref: Spec: 9.1.1 (1)
659
+ natsort( $value );
660
+ foreach ( $value as $duplicate_value ) {
661
+ $pairs[] = $lower_param . '=' . $duplicate_value;
662
+ }
663
+ } else {
664
+ $pairs[] = $lower_param . '=' . $value;
665
+ }
666
+ }
667
+
668
+ if ( 0 === count( $pairs ) ) {
669
+ return '';
670
+ }
671
+
672
+ return implode( "&", $pairs );
673
+ }
674
+ }
675
+
676
+ if ( ! function_exists( 'fs_urlencode_rfc3986' ) ) {
677
+ /**
678
+ * @author Vova Feldman (@svovaf)
679
+ * @since 1.1.3
680
+ *
681
+ * @param string|string[] $input
682
+ *
683
+ * @return array|mixed|string
684
+ */
685
+ function fs_urlencode_rfc3986( $input ) {
686
+ if ( is_array( $input ) ) {
687
+ return array_map( 'fs_urlencode_rfc3986', $input );
688
+ } else if ( is_scalar( $input ) ) {
689
+ return str_replace( '+', ' ', str_replace( '%7E', '~', rawurlencode( $input ) ) );
690
+ }
691
+
692
+ return '';
693
+ }
694
+ }
695
+
696
+ #endregion Url Canonization ------------------------------------------------------------------
697
+
698
+ if ( ! function_exists( 'fs_download_image' ) ) {
699
+ /**
700
+ * @author Vova Feldman (@svovaf)
701
+ *
702
+ * @since 1.2.2 Changed to usage of WP_Filesystem_Direct.
703
+ *
704
+ * @param string $from URL
705
+ * @param string $to File path.
706
+ *
707
+ * @return bool Is successfully downloaded.
708
+ */
709
+ function fs_download_image( $from, $to ) {
710
+ $dir = dirname( $to );
711
+
712
+ if ( 'direct' !== get_filesystem_method( array(), $dir ) ) {
713
+ return false;
714
+ }
715
+
716
+ if ( ! class_exists( 'WP_Filesystem_Direct' ) ) {
717
+ require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
718
+ require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
719
+ }
720
+
721
+ $fs = new WP_Filesystem_Direct( '' );
722
+ $tmpfile = download_url( $from );
723
+
724
+ if ( $tmpfile instanceof WP_Error ) {
725
+ // Issue downloading the file.
726
+ return false;
727
+ }
728
+
729
+ $fs->copy( $tmpfile, $to );
730
+ $fs->delete( $tmpfile );
731
+
732
+ return true;
733
+ }
734
+ }
735
+
736
+ /* General Utilities
737
+ --------------------------------------------------------------------------------------------*/
738
+
739
+ if ( ! function_exists( 'fs_sort_by_priority' ) ) {
740
+ /**
741
+ * Sorts an array by the value of the priority key.
742
+ *
743
+ * @author Daniel Iser (@danieliser)
744
+ * @since 1.1.7
745
+ *
746
+ * @param $a
747
+ * @param $b
748
+ *
749
+ * @return int
750
+ */
751
+ function fs_sort_by_priority( $a, $b ) {
752
+
753
+ // If b has a priority and a does not, b wins.
754
+ if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) {
755
+ return 1;
756
+ } // If b has a priority and a does not, b wins.
757
+ elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) {
758
+ return - 1;
759
+ } // If neither has a priority or both priorities are equal its a tie.
760
+ elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) {
761
+ return 0;
762
+ }
763
+
764
+ // If both have priority return the winner.
765
+ return ( $a['priority'] < $b['priority'] ) ? - 1 : 1;
766
+ }
767
+ }
768
+
769
+ #--------------------------------------------------------------------------------
770
+ #region Localization
771
+ #--------------------------------------------------------------------------------
772
+
773
+ if ( ! function_exists( 'fs_text' ) ) {
774
+ /**
775
+ * Retrieve a translated text by key.
776
+ *
777
+ * @author Vova Feldman (@svovaf)
778
+ * @since 1.2.1.7
779
+ *
780
+ * @param string $key
781
+ * @param string $slug
782
+ *
783
+ * @return string
784
+ *
785
+ * @global $fs_text , $fs_text_overrides
786
+ */
787
+ function fs_text( $key, $slug = 'freemius' ) {
788
+ global $fs_text,
789
+ $fs_module_info_text,
790
+ $fs_text_overrides;
791
+
792
+ if ( isset( $fs_text_overrides[ $slug ] ) ) {
793
+ if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
794
+ return $fs_text_overrides[ $slug ][ $key ];
795
+ }
796
+
797
+ $lower_key = strtolower( $key );
798
+ if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
799
+ return $fs_text_overrides[ $slug ][ $lower_key ];
800
+ }
801
+ }
802
+
803
+ if ( ! isset( $fs_text ) ) {
804
+ $dir = defined( 'WP_FS__DIR_INCLUDES' ) ?
805
+ WP_FS__DIR_INCLUDES :
806
+ dirname( __FILE__ );
807
+
808
+ require_once $dir . '/i18n.php';
809
+ }
810
+
811
+ if ( isset( $fs_text[ $key ] ) ) {
812
+ return $fs_text[ $key ];
813
+ }
814
+
815
+ if ( isset( $fs_module_info_text[ $key ] ) ) {
816
+ return $fs_module_info_text[ $key ];
817
+ }
818
+
819
+ return $key;
820
+ }
821
+
822
+ #region Private
823
+
824
+ /**
825
+ * Retrieve an inline translated text by key with a context.
826
+ *
827
+ * @author Vova Feldman (@svovaf)
828
+ * @since 1.2.3
829
+ *
830
+ * @param string $text Translatable string.
831
+ * @param string $context Context information for the translators.
832
+ * @param string $key String key for overrides.
833
+ * @param string $slug Module slug for overrides.
834
+ *
835
+ * @return string
836
+ *
837
+ * @global $fs_text_overrides
838
+ */
839
+ function _fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
840
+ list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
841
+
842
+ // Avoid misleading Theme Check warning.
843
+ $fn = 'translate_with_gettext_context';
844
+
845
+ return $fn( $text, $context, $text_domain );
846
+ }
847
+
848
+ #endregion
849
+
850
+ /**
851
+ * Retrieve an inline translated text by key with a context.
852
+ *
853
+ * @author Vova Feldman (@svovaf)
854
+ * @since 1.2.3
855
+ *
856
+ * @param string $text Translatable string.
857
+ * @param string $context Context information for the translators.
858
+ * @param string $key String key for overrides.
859
+ * @param string $slug Module slug for overrides.
860
+ *
861
+ * @return string
862
+ *
863
+ * @global $fs_text_overrides
864
+ */
865
+ function fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
866
+ return _fs_text_x_inline( $text, $context, $key, $slug );
867
+ }
868
+
869
+ /**
870
+ * Output a translated text by key.
871
+ *
872
+ * @author Vova Feldman (@svovaf)
873
+ * @since 1.2.1.7
874
+ *
875
+ * @param string $key
876
+ * @param string $slug
877
+ */
878
+ function fs_echo( $key, $slug = 'freemius' ) {
879
+ echo fs_text( $key, $slug );
880
+ }
881
+
882
+ /**
883
+ * Output an inline translated text.
884
+ *
885
+ * @author Vova Feldman (@svovaf)
886
+ * @since 1.2.3
887
+ *
888
+ * @param string $text Translatable string.
889
+ * @param string $key String key for overrides.
890
+ * @param string $slug Module slug for overrides.
891
+ */
892
+ function fs_echo_inline( $text, $key = '', $slug = 'freemius' ) {
893
+ echo _fs_text_inline( $text, $key, $slug );
894
+ }
895
+
896
+ /**
897
+ * Output an inline translated text with a context.
898
+ *
899
+ * @author Vova Feldman (@svovaf)
900
+ * @since 1.2.3
901
+ *
902
+ * @param string $text Translatable string.
903
+ * @param string $context Context information for the translators.
904
+ * @param string $key String key for overrides.
905
+ * @param string $slug Module slug for overrides.
906
+ */
907
+ function fs_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
908
+ echo _fs_text_x_inline( $text, $context, $key, $slug );
909
+ }
910
+ }
911
+
912
+ if ( ! function_exists( 'fs_text_override' ) ) {
913
+ /**
914
+ * Get a translatable text override if exists, or `false`.
915
+ *
916
+ * @author Vova Feldman (@svovaf)
917
+ * @since 1.2.1.7
918
+ *
919
+ * @param string $text Translatable string.
920
+ * @param string $key String key for overrides.
921
+ * @param string $slug Module slug for overrides.
922
+ *
923
+ * @return string|false
924
+ */
925
+ function fs_text_override( $text, $key, $slug ) {
926
+ global $fs_text_overrides;
927
+
928
+ /**
929
+ * Check if string is overridden.
930
+ */
931
+ if ( ! isset( $fs_text_overrides[ $slug ] ) ) {
932
+ return false;
933
+ }
934
+
935
+ if ( empty( $key ) ) {
936
+ $key = strtolower( str_replace( ' ', '-', $text ) );
937
+ }
938
+
939
+ if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
940
+ return $fs_text_overrides[ $slug ][ $key ];
941
+ }
942
+
943
+ $lower_key = strtolower( $key );
944
+ if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
945
+ return $fs_text_overrides[ $slug ][ $lower_key ];
946
+ }
947
+
948
+ return false;
949
+ }
950
+ }
951
+
952
+ if ( ! function_exists( 'fs_text_and_domain' ) ) {
953
+ /**
954
+ * Get a translatable text and its text domain.
955
+ *
956
+ * When the text is overridden by the module, returns the overridden text and the text domain of the module. Otherwise, returns the original text and 'freemius' as the text domain.
957
+ *
958
+ * @author Vova Feldman (@svovaf)
959
+ * @since 1.2.1.7
960
+ *
961
+ * @param string $text Translatable string.
962
+ * @param string $key String key for overrides.
963
+ * @param string $slug Module slug for overrides.
964
+ *
965
+ * @return string[]
966
+ */
967
+ function fs_text_and_domain( $text, $key, $slug ) {
968
+ $override = fs_text_override( $text, $key, $slug );
969
+
970
+ if ( false === $override ) {
971
+ // No override, use FS text domain.
972
+ $text_domain = 'freemius';
973
+ } else {
974
+ // Found an override.
975
+ $text = $override;
976
+ // Use the module's text domain.
977
+ $text_domain = $slug;
978
+ }
979
+
980
+ return array( $text, $text_domain );
981
+ }
982
+ }
983
+
984
+ if ( ! function_exists( '_fs_text_inline' ) ) {
985
+ /**
986
+ * Retrieve an inline translated text by key.
987
+ *
988
+ * @author Vova Feldman (@svovaf)
989
+ * @since 1.2.3
990
+ *
991
+ * @param string $text Translatable string.
992
+ * @param string $key String key for overrides.
993
+ * @param string $slug Module slug for overrides.
994
+ *
995
+ * @return string
996
+ *
997
+ * @global $fs_text_overrides
998
+ */
999
+ function _fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
1000
+ list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug );
1001
+
1002
+ // Avoid misleading Theme Check warning.
1003
+ $fn = 'translate';
1004
+
1005
+ return $fn( $text, $text_domain );
1006
+ }
1007
+ }
1008
+
1009
+ if ( ! function_exists( 'fs_text_inline' ) ) {
1010
+ /**
1011
+ * Retrieve an inline translated text by key.
1012
+ *
1013
+ * @author Vova Feldman (@svovaf)
1014
+ * @since 1.2.3
1015
+ *
1016
+ * @param string $text Translatable string.
1017
+ * @param string $key String key for overrides.
1018
+ * @param string $slug Module slug for overrides.
1019
+ *
1020
+ * @return string
1021
+ *
1022
+ * @global $fs_text_overrides
1023
+ */
1024
+ function fs_text_inline( $text, $key = '', $slug = 'freemius' ) {
1025
+ return _fs_text_inline( $text, $key, $slug );
1026
+ }
1027
+ }
1028
+
1029
+ if ( ! function_exists( 'fs_esc_attr' ) ) {
1030
+ /**
1031
+ * @author Vova Feldman
1032
+ * @since 1.2.1.6
1033
+ *
1034
+ * @param string $key
1035
+ * @param string $slug
1036
+ *
1037
+ * @return string
1038
+ */
1039
+ function fs_esc_attr( $key, $slug ) {
1040
+ return esc_attr( fs_text( $key, $slug ) );
1041
+ }
1042
+ }
1043
+
1044
+ if ( ! function_exists( 'fs_esc_attr_inline' ) ) {
1045
+ /**
1046
+ * @author Vova Feldman (@svovaf)
1047
+ * @since 1.2.3
1048
+ *
1049
+ * @param string $text Translatable string.
1050
+ * @param string $key String key for overrides.
1051
+ * @param string $slug Module slug for overrides.
1052
+ *
1053
+ * @return string
1054
+ */
1055
+ function fs_esc_attr_inline( $text, $key = '', $slug = 'freemius' ) {
1056
+ return esc_attr( _fs_text_inline( $text, $key, $slug ) );
1057
+ }
1058
+ }
1059
+
1060
+ if ( ! function_exists( 'fs_esc_attr_x_inline' ) ) {
1061
+ /**
1062
+ * @author Vova Feldman (@svovaf)
1063
+ * @since 1.2.3
1064
+ *
1065
+ * @param string $text Translatable string.
1066
+ * @param string $context Context information for the translators.
1067
+ * @param string $key String key for overrides.
1068
+ * @param string $slug Module slug for overrides.
1069
+ *
1070
+ * @return string
1071
+ */
1072
+ function fs_esc_attr_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1073
+ return esc_attr( _fs_text_x_inline( $text, $context, $key, $slug ) );
1074
+ }
1075
+ }
1076
+
1077
+ if ( ! function_exists( 'fs_esc_attr_echo' ) ) {
1078
+ /**
1079
+ * @author Vova Feldman
1080
+ * @since 1.2.1.6
1081
+ *
1082
+ * @param string $key
1083
+ * @param string $slug
1084
+ */
1085
+ function fs_esc_attr_echo( $key, $slug ) {
1086
+ echo esc_attr( fs_text( $key, $slug ) );
1087
+ }
1088
+ }
1089
+
1090
+ if ( ! function_exists( 'fs_esc_attr_echo_inline' ) ) {
1091
+ /**
1092
+ * @author Vova Feldman (@svovaf)
1093
+ * @since 1.2.3
1094
+ *
1095
+ * @param string $text Translatable string.
1096
+ * @param string $key String key for overrides.
1097
+ * @param string $slug Module slug for overrides.
1098
+ */
1099
+ function fs_esc_attr_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1100
+ echo esc_attr( _fs_text_inline( $text, $key, $slug ) );
1101
+ }
1102
+ }
1103
+
1104
+ if ( ! function_exists( 'fs_esc_js' ) ) {
1105
+ /**
1106
+ * @author Vova Feldman
1107
+ * @since 1.2.1.6
1108
+ *
1109
+ * @param string $key
1110
+ * @param string $slug
1111
+ *
1112
+ * @return string
1113
+ */
1114
+ function fs_esc_js( $key, $slug ) {
1115
+ return esc_js( fs_text( $key, $slug ) );
1116
+ }
1117
+ }
1118
+
1119
+ if ( ! function_exists( 'fs_esc_js_inline' ) ) {
1120
+ /**
1121
+ * @author Vova Feldman (@svovaf)
1122
+ * @since 1.2.3
1123
+ *
1124
+ * @param string $text Translatable string.
1125
+ * @param string $key String key for overrides.
1126
+ * @param string $slug Module slug for overrides.
1127
+ *
1128
+ * @return string
1129
+ */
1130
+ function fs_esc_js_inline( $text, $key = '', $slug = 'freemius' ) {
1131
+ return esc_js( _fs_text_inline( $text, $key, $slug ) );
1132
+ }
1133
+ }
1134
+
1135
+ if ( ! function_exists( 'fs_esc_js_x_inline' ) ) {
1136
+ /**
1137
+ * @author Vova Feldman (@svovaf)
1138
+ * @since 1.2.3
1139
+ *
1140
+ * @param string $text Translatable string.
1141
+ * @param string $context Context information for the translators.
1142
+ * @param string $key String key for overrides.
1143
+ * @param string $slug Module slug for overrides.
1144
+ *
1145
+ * @return string
1146
+ */
1147
+ function fs_esc_js_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1148
+ return esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
1149
+ }
1150
+ }
1151
+
1152
+ if ( ! function_exists( 'fs_esc_js_echo_x_inline' ) ) {
1153
+ /**
1154
+ * @author Vova Feldman (@svovaf)
1155
+ * @since 1.2.3
1156
+ *
1157
+ * @param string $text Translatable string.
1158
+ * @param string $context Context information for the translators.
1159
+ * @param string $key String key for overrides.
1160
+ * @param string $slug Module slug for overrides.
1161
+ *
1162
+ * @return string
1163
+ */
1164
+ function fs_esc_js_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1165
+ echo esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) );
1166
+ }
1167
+ }
1168
+
1169
+ if ( ! function_exists( 'fs_esc_js_echo' ) ) {
1170
+ /**
1171
+ * @author Vova Feldman
1172
+ * @since 1.2.1.6
1173
+ *
1174
+ * @param string $key
1175
+ * @param string $slug
1176
+ */
1177
+ function fs_esc_js_echo( $key, $slug ) {
1178
+ echo esc_js( fs_text( $key, $slug ) );
1179
+ }
1180
+ }
1181
+
1182
+ if ( ! function_exists( 'fs_esc_js_echo_inline' ) ) {
1183
+ /**
1184
+ * @author Vova Feldman (@svovaf)
1185
+ * @since 1.2.3
1186
+ *
1187
+ * @param string $text Translatable string.
1188
+ * @param string $key String key for overrides.
1189
+ * @param string $slug Module slug for overrides.
1190
+ */
1191
+ function fs_esc_js_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1192
+ echo esc_js( _fs_text_inline( $text, $key, $slug ) );
1193
+ }
1194
+ }
1195
+
1196
+ if ( ! function_exists( 'fs_json_encode_echo' ) ) {
1197
+ /**
1198
+ * @author Vova Feldman
1199
+ * @since 1.2.1.6
1200
+ *
1201
+ * @param string $key
1202
+ * @param string $slug
1203
+ */
1204
+ function fs_json_encode_echo( $key, $slug ) {
1205
+ echo json_encode( fs_text( $key, $slug ) );
1206
+ }
1207
+ }
1208
+
1209
+ if ( ! function_exists( 'fs_json_encode_echo_inline' ) ) {
1210
+ /**
1211
+ * @author Vova Feldman (@svovaf)
1212
+ * @since 1.2.3
1213
+ *
1214
+ * @param string $text Translatable string.
1215
+ * @param string $key String key for overrides.
1216
+ * @param string $slug Module slug for overrides.
1217
+ */
1218
+ function fs_json_encode_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1219
+ echo json_encode( _fs_text_inline( $text, $key, $slug ) );
1220
+ }
1221
+ }
1222
+
1223
+ if ( ! function_exists( 'fs_esc_html' ) ) {
1224
+ /**
1225
+ * @author Vova Feldman
1226
+ * @since 1.2.1.6
1227
+ *
1228
+ * @param string $key
1229
+ * @param string $slug
1230
+ *
1231
+ * @return string
1232
+ */
1233
+ function fs_esc_html( $key, $slug ) {
1234
+ return esc_html( fs_text( $key, $slug ) );
1235
+ }
1236
+ }
1237
+
1238
+ if ( ! function_exists( 'fs_esc_html_inline' ) ) {
1239
+ /**
1240
+ * @author Vova Feldman (@svovaf)
1241
+ * @since 1.2.3
1242
+ *
1243
+ * @param string $text Translatable string.
1244
+ * @param string $key String key for overrides.
1245
+ * @param string $slug Module slug for overrides.
1246
+ *
1247
+ * @return string
1248
+ */
1249
+ function fs_esc_html_inline( $text, $key = '', $slug = 'freemius' ) {
1250
+ return esc_html( _fs_text_inline( $text, $key, $slug ) );
1251
+ }
1252
+ }
1253
+
1254
+ if ( ! function_exists( 'fs_esc_html_x_inline' ) ) {
1255
+ /**
1256
+ * @author Vova Feldman (@svovaf)
1257
+ * @since 1.2.3
1258
+ *
1259
+ * @param string $text Translatable string.
1260
+ * @param string $context Context information for the translators.
1261
+ * @param string $key String key for overrides.
1262
+ * @param string $slug Module slug for overrides.
1263
+ *
1264
+ * @return string
1265
+ */
1266
+ function fs_esc_html_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1267
+ return esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) );
1268
+ }
1269
+ }
1270
+
1271
+ if ( ! function_exists( 'fs_esc_html_echo_x_inline' ) ) {
1272
+ /**
1273
+ * @author Vova Feldman (@svovaf)
1274
+ * @since 1.2.3
1275
+ *
1276
+ * @param string $text Translatable string.
1277
+ * @param string $context Context information for the translators.
1278
+ * @param string $key String key for overrides.
1279
+ * @param string $slug Module slug for overrides.
1280
+ */
1281
+ function fs_esc_html_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) {
1282
+ echo esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) );
1283
+ }
1284
+ }
1285
+
1286
+ if ( ! function_exists( 'fs_esc_html_echo' ) ) {
1287
+ /**
1288
+ * @author Vova Feldman
1289
+ * @since 1.2.1.6
1290
+ *
1291
+ * @param string $key
1292
+ * @param string $slug
1293
+ */
1294
+ function fs_esc_html_echo( $key, $slug ) {
1295
+ echo esc_html( fs_text( $key, $slug ) );
1296
+ }
1297
+ }
1298
+
1299
+ if ( ! function_exists( 'fs_esc_html_echo_inline' ) ) {
1300
+ /**
1301
+ * @author Vova Feldman (@svovaf)
1302
+ * @since 1.2.3
1303
+ *
1304
+ * @param string $text Translatable string.
1305
+ * @param string $key String key for overrides.
1306
+ * @param string $slug Module slug for overrides.
1307
+ */
1308
+ function fs_esc_html_echo_inline( $text, $key = '', $slug = 'freemius' ) {
1309
+ echo esc_html( _fs_text_inline( $text, $key, $slug ) );
1310
+ }
1311
+ }
1312
+
1313
+ if ( ! function_exists( 'fs_override_i18n' ) ) {
1314
+ /**
1315
+ * Override default i18n text phrases.
1316
+ *
1317
+ * @author Vova Feldman (@svovaf)
1318
+ * @since 1.1.6
1319
+ *
1320
+ * @param array[string]string $key_value
1321
+ * @param string $slug
1322
+ *
1323
+ * @global $fs_text_overrides
1324
+ */
1325
+ function fs_override_i18n( array $key_value, $slug = 'freemius' ) {
1326
+ global $fs_text_overrides;
1327
+
1328
+ if ( ! isset( $fs_text_overrides[ $slug ] ) ) {
1329
+ $fs_text_overrides[ $slug ] = array();
1330
+ }
1331
+
1332
+ foreach ( $key_value as $key => $value ) {
1333
+ $fs_text_overrides[ $slug ][ $key ] = $value;
1334
+ }
1335
+ }
1336
+ }
1337
+
1338
+ #endregion
1339
+
1340
+ #--------------------------------------------------------------------------------
1341
+ #region Multisite Network
1342
+ #--------------------------------------------------------------------------------
1343
+
1344
+ if ( ! function_exists( 'fs_is_plugin_uninstall' ) ) {
1345
+ /**
1346
+ * @author Vova Feldman (@svovaf)
1347
+ * @since 2.0.0
1348
+ */
1349
+ function fs_is_plugin_uninstall() {
1350
+ return (
1351
+ defined( 'WP_UNINSTALL_PLUGIN' ) ||
1352
+ ( 0 < did_action( 'update_option_uninstall_plugins' ) )
1353
+ );
1354
+ }
1355
+ }
1356
+
1357
+ if ( ! function_exists( 'fs_is_network_admin' ) ) {
1358
+ /**
1359
+ * Unlike is_network_admin(), this one will also work properly when
1360
+ * the context execution is WP AJAX handler, and during plugin
1361
+ * uninstall.
1362
+ *
1363
+ * @author Vova Feldman (@svovaf)
1364
+ * @since 2.0.0
1365
+ */
1366
+ function fs_is_network_admin() {
1367
+ return (
1368
+ WP_FS__IS_NETWORK_ADMIN ||
1369
+ ( is_multisite() && fs_is_plugin_uninstall() )
1370
+ );
1371
+ }
1372
+ }
1373
+
1374
+ if ( ! function_exists( 'fs_is_blog_admin' ) ) {
1375
+ /**
1376
+ * Unlike is_blog_admin(), this one will also work properly when
1377
+ * the context execution is WP AJAX handler, and during plugin
1378
+ * uninstall.
1379
+ *
1380
+ * @author Vova Feldman (@svovaf)
1381
+ * @since 2.0.0
1382
+ */
1383
+ function fs_is_blog_admin() {
1384
+ return (
1385
+ WP_FS__IS_BLOG_ADMIN ||
1386
+ ( ! is_multisite() && fs_is_plugin_uninstall() )
1387
+ );
1388
+ }
1389
+ }
1390
+
1391
+ #endregion
1392
+
1393
+ if ( ! function_exists( 'fs_apply_filter' ) ) {
1394
+ /**
1395
+ * Apply filter for specific plugin.
1396
+ *
1397
+ * @author Vova Feldman (@svovaf)
1398
+ * @since 1.0.9
1399
+ *
1400
+ * @param string $module_unique_affix Module's unique affix.
1401
+ * @param string $tag The name of the filter hook.
1402
+ * @param mixed $value The value on which the filters hooked to `$tag` are applied on.
1403
+ *
1404
+ * @return mixed The filtered value after all hooked functions are applied to it.
1405
+ *
1406
+ * @uses apply_filters()
1407
+ */
1408
+ function fs_apply_filter( $module_unique_affix, $tag, $value ) {
1409
+ $args = func_get_args();
1410
+
1411
+ return call_user_func_array( 'apply_filters', array_merge(
1412
+ array( "fs_{$tag}_{$module_unique_affix}" ),
1413
+ array_slice( $args, 2 ) )
1414
+ );
1415
+ }
1416
  }
freemius/includes/managers/class-fs-admin-notice-manager.php CHANGED
@@ -175,7 +175,12 @@
175
  *
176
  */
177
  function dismiss_notice_ajax_callback() {
178
- $this->_sticky_storage->remove( $_POST['message_id'] );
 
 
 
 
 
179
  wp_die();
180
  }
181
 
@@ -469,4 +474,4 @@
469
  }
470
 
471
  #endregion
472
- }
175
  *
176
  */
177
  function dismiss_notice_ajax_callback() {
178
+ check_admin_referer( 'fs_dismiss_notice_action' );
179
+
180
+ if ( ! is_numeric( $_POST['message_id'] ) ) {
181
+ $this->_sticky_storage->remove( $_POST['message_id'] );
182
+ }
183
+
184
  wp_die();
185
  }
186
 
474
  }
475
 
476
  #endregion
477
+ }
freemius/includes/sdk/Exceptions/ArgumentNotExistException.php CHANGED
@@ -1,4 +1,8 @@
1
  <?php
 
 
 
 
2
  if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) {
3
  exit;
4
  }
@@ -6,4 +10,4 @@
6
  if ( ! class_exists( 'Freemius_ArgumentNotExistException' ) ) {
7
  class Freemius_ArgumentNotExistException extends Freemius_InvalidArgumentException {
8
  }
9
- }
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
  if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) {
7
  exit;
8
  }
10
  if ( ! class_exists( 'Freemius_ArgumentNotExistException' ) ) {
11
  class Freemius_ArgumentNotExistException extends Freemius_InvalidArgumentException {
12
  }
13
+ }
freemius/includes/sdk/Exceptions/EmptyArgumentException.php CHANGED
@@ -1,4 +1,8 @@
1
  <?php
 
 
 
 
2
  if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) {
3
  exit;
4
  }
@@ -6,4 +10,4 @@
6
  if ( ! class_exists( 'Freemius_EmptyArgumentException' ) ) {
7
  class Freemius_EmptyArgumentException extends Freemius_InvalidArgumentException {
8
  }
9
- }
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
  if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) {
7
  exit;
8
  }
10
  if ( ! class_exists( 'Freemius_EmptyArgumentException' ) ) {
11
  class Freemius_EmptyArgumentException extends Freemius_InvalidArgumentException {
12
  }
13
+ }
freemius/includes/sdk/Exceptions/Exception.php CHANGED
@@ -1,4 +1,8 @@
1
  <?php
 
 
 
 
2
  if ( ! class_exists( 'Freemius_Exception' ) ) {
3
  /**
4
  * Thrown when an API call returns an exception.
@@ -71,4 +75,4 @@
71
  return $str . $this->getMessage();
72
  }
73
  }
74
- }
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
  if ( ! class_exists( 'Freemius_Exception' ) ) {
7
  /**
8
  * Thrown when an API call returns an exception.
75
  return $str . $this->getMessage();
76
  }
77
  }
78
+ }
freemius/includes/sdk/Exceptions/InvalidArgumentException.php CHANGED
@@ -1,8 +1,12 @@
1
  <?php
 
 
 
 
2
  if ( ! class_exists( 'Freemius_Exception' ) ) {
3
  exit;
4
  }
5
 
6
  if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) {
7
  class Freemius_InvalidArgumentException extends Freemius_Exception { }
8
- }
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
  if ( ! class_exists( 'Freemius_Exception' ) ) {
7
  exit;
8
  }
9
 
10
  if ( ! class_exists( 'Freemius_InvalidArgumentException' ) ) {
11
  class Freemius_InvalidArgumentException extends Freemius_Exception { }
12
+ }
freemius/includes/sdk/Exceptions/OAuthException.php CHANGED
@@ -1,4 +1,8 @@
1
  <?php
 
 
 
 
2
  if ( ! class_exists( 'Freemius_Exception' ) ) {
3
  exit;
4
  }
@@ -9,4 +13,4 @@
9
  parent::__construct( $pResult );
10
  }
11
  }
12
- }
1
  <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
  if ( ! class_exists( 'Freemius_Exception' ) ) {
7
  exit;
8
  }
13
  parent::__construct( $pResult );
14
  }
15
  }
16
+ }
freemius/includes/sdk/FreemiusBase.php CHANGED
@@ -1,215 +1,219 @@
1
- <?php
2
- /**
3
- * Copyright 2014 Freemius, Inc.
4
- *
5
- * Licensed under the GPL v2 (the "License"); you may
6
- * not use this file except in compliance with the License. You may obtain
7
- * a copy of the License at
8
- *
9
- * http://choosealicense.com/licenses/gpl-v2/
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
- * License for the specific language governing permissions and limitations
15
- * under the License.
16
- */
17
-
18
- if ( ! defined( 'FS_API__VERSION' ) ) {
19
- define( 'FS_API__VERSION', '1' );
20
- }
21
- if ( ! defined( 'FS_SDK__PATH' ) ) {
22
- define( 'FS_SDK__PATH', dirname( __FILE__ ) );
23
- }
24
- if ( ! defined( 'FS_SDK__EXCEPTIONS_PATH' ) ) {
25
- define( 'FS_SDK__EXCEPTIONS_PATH', FS_SDK__PATH . '/Exceptions/' );
26
- }
27
-
28
- if ( ! function_exists( 'json_decode' ) ) {
29
- throw new Exception( 'Freemius needs the JSON PHP extension.' );
30
- }
31
-
32
- // Include all exception files.
33
- $exceptions = array(
34
- 'Exception',
35
- 'InvalidArgumentException',
36
- 'ArgumentNotExistException',
37
- 'EmptyArgumentException',
38
- 'OAuthException'
39
- );
40
-
41
- foreach ( $exceptions as $e ) {
42
- require_once FS_SDK__EXCEPTIONS_PATH . $e . '.php';
43
- }
44
-
45
- if ( class_exists( 'Freemius_Api_Base' ) ) {
46
- return;
47
- }
48
-
49
- abstract class Freemius_Api_Base {
50
- const VERSION = '1.0.4';
51
- const FORMAT = 'json';
52
-
53
- protected $_id;
54
- protected $_public;
55
- protected $_secret;
56
- protected $_scope;
57
- protected $_isSandbox;
58
-
59
- /**
60
- * @param string $pScope 'app', 'developer', 'plugin', 'user' or 'install'.
61
- * @param number $pID Element's id.
62
- * @param string $pPublic Public key.
63
- * @param string $pSecret Element's secret key.
64
- * @param bool $pIsSandbox Whether or not to run API in sandbox mode.
65
- */
66
- public function Init( $pScope, $pID, $pPublic, $pSecret, $pIsSandbox = false ) {
67
- $this->_id = $pID;
68
- $this->_public = $pPublic;
69
- $this->_secret = $pSecret;
70
- $this->_scope = $pScope;
71
- $this->_isSandbox = $pIsSandbox;
72
- }
73
-
74
- public function IsSandbox() {
75
- return $this->_isSandbox;
76
- }
77
-
78
- function CanonizePath( $pPath ) {
79
- $pPath = trim( $pPath, '/' );
80
- $query_pos = strpos( $pPath, '?' );
81
- $query = '';
82
-
83
- if ( false !== $query_pos ) {
84
- $query = substr( $pPath, $query_pos );
85
- $pPath = substr( $pPath, 0, $query_pos );
86
- }
87
-
88
- // Trim '.json' suffix.
89
- $format_length = strlen( '.' . self::FORMAT );
90
- $start = $format_length * ( - 1 ); //negative
91
- if ( substr( strtolower( $pPath ), $start ) === ( '.' . self::FORMAT ) ) {
92
- $pPath = substr( $pPath, 0, strlen( $pPath ) - $format_length );
93
- }
94
-
95
- switch ( $this->_scope ) {
96
- case 'app':
97
- $base = '/apps/' . $this->_id;
98
- break;
99
- case 'developer':
100
- $base = '/developers/' . $this->_id;
101
- break;
102
- case 'user':
103
- $base = '/users/' . $this->_id;
104
- break;
105
- case 'plugin':
106
- $base = '/plugins/' . $this->_id;
107
- break;
108
- case 'install':
109
- $base = '/installs/' . $this->_id;
110
- break;
111
- default:
112
- throw new Freemius_Exception( 'Scope not implemented.' );
113
- }
114
-
115
- return '/v' . FS_API__VERSION . $base .
116
- ( ! empty( $pPath ) ? '/' : '' ) . $pPath .
117
- ( ( false === strpos( $pPath, '.' ) ) ? '.' . self::FORMAT : '' ) . $query;
118
- }
119
-
120
- abstract function MakeRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array() );
121
-
122
- /**
123
- * @param string $pPath
124
- * @param string $pMethod
125
- * @param array $pParams
126
- *
127
- * @return object[]|object|null
128
- */
129
- private function _Api( $pPath, $pMethod = 'GET', $pParams = array() ) {
130
- $pMethod = strtoupper( $pMethod );
131
-
132
- try {
133
- $result = $this->MakeRequest( $pPath, $pMethod, $pParams );
134
- } catch ( Freemius_Exception $e ) {
135
- // Map to error object.
136
- $result = (object) $e->getResult();
137
- } catch ( Exception $e ) {
138
- // Map to error object.
139
- $result = (object) array(
140
- 'error' => (object) array(
141
- 'type' => 'Unknown',
142
- 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')',
143
- 'code' => 'unknown',
144
- 'http' => 402
145
- )
146
- );
147
- }
148
-
149
- return $result;
150
- }
151
-
152
- public function Api( $pPath, $pMethod = 'GET', $pParams = array() ) {
153
- return $this->_Api( $this->CanonizePath( $pPath ), $pMethod, $pParams );
154
- }
155
-
156
- /**
157
- * Base64 decoding that does not need to be urldecode()-ed.
158
- *
159
- * Exactly the same as PHP base64 encode except it uses
160
- * `-` instead of `+`
161
- * `_` instead of `/`
162
- * No padded =
163
- *
164
- * @param string $input Base64UrlEncoded() string
165
- *
166
- * @return string
167
- */
168
- protected static function Base64UrlDecode( $input ) {
169
- /**
170
- * IMPORTANT NOTE:
171
- * This is a hack suggested by @otto42 and @greenshady from
172
- * the theme's review team. The usage of base64 for API
173
- * signature encoding was approved in a Slack meeting
174
- * held on Tue (10/25 2016).
175
- *
176
- * @todo Remove this hack once the base64 error is removed from the Theme Check.
177
- *
178
- * @since 1.2.2
179
- * @author Vova Feldman (@svovaf)
180
- */
181
- $fn = 'base64' . '_decode';
182
- return $fn( strtr( $input, '-_', '+/' ) );
183
- }
184
-
185
- /**
186
- * Base64 encoding that does not need to be urlencode()ed.
187
- *
188
- * Exactly the same as base64 encode except it uses
189
- * `-` instead of `+
190
- * `_` instead of `/`
191
- *
192
- * @param string $input string
193
- *
194
- * @return string Base64 encoded string
195
- */
196
- protected static function Base64UrlEncode( $input ) {
197
- /**
198
- * IMPORTANT NOTE:
199
- * This is a hack suggested by @otto42 and @greenshady from
200
- * the theme's review team. The usage of base64 for API
201
- * signature encoding was approved in a Slack meeting
202
- * held on Tue (10/25 2016).
203
- *
204
- * @todo Remove this hack once the base64 error is removed from the Theme Check.
205
- *
206
- * @since 1.2.2
207
- * @author Vova Feldman (@svovaf)
208
- */
209
- $fn = 'base64' . '_encode';
210
- $str = strtr( $fn( $input ), '+/', '-_' );
211
- $str = str_replace( '=', '', $str );
212
-
213
- return $str;
214
- }
215
- }
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2014 Freemius, Inc.
4
+ *
5
+ * Licensed under the GPL v2 (the "License"); you may
6
+ * not use this file except in compliance with the License. You may obtain
7
+ * a copy of the License at
8
+ *
9
+ * http://choosealicense.com/licenses/gpl-v2/
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations
15
+ * under the License.
16
+ */
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ if ( ! defined( 'FS_API__VERSION' ) ) {
23
+ define( 'FS_API__VERSION', '1' );
24
+ }
25
+ if ( ! defined( 'FS_SDK__PATH' ) ) {
26
+ define( 'FS_SDK__PATH', dirname( __FILE__ ) );
27
+ }
28
+ if ( ! defined( 'FS_SDK__EXCEPTIONS_PATH' ) ) {
29
+ define( 'FS_SDK__EXCEPTIONS_PATH', FS_SDK__PATH . '/Exceptions/' );
30
+ }
31
+
32
+ if ( ! function_exists( 'json_decode' ) ) {
33
+ throw new Exception( 'Freemius needs the JSON PHP extension.' );
34
+ }
35
+
36
+ // Include all exception files.
37
+ $exceptions = array(
38
+ 'Exception',
39
+ 'InvalidArgumentException',
40
+ 'ArgumentNotExistException',
41
+ 'EmptyArgumentException',
42
+ 'OAuthException'
43
+ );
44
+
45
+ foreach ( $exceptions as $e ) {
46
+ require_once FS_SDK__EXCEPTIONS_PATH . $e . '.php';
47
+ }
48
+
49
+ if ( class_exists( 'Freemius_Api_Base' ) ) {
50
+ return;
51
+ }
52
+
53
+ abstract class Freemius_Api_Base {
54
+ const VERSION = '1.0.4';
55
+ const FORMAT = 'json';
56
+
57
+ protected $_id;
58
+ protected $_public;
59
+ protected $_secret;
60
+ protected $_scope;
61
+ protected $_isSandbox;
62
+
63
+ /**
64
+ * @param string $pScope 'app', 'developer', 'plugin', 'user' or 'install'.
65
+ * @param number $pID Element's id.
66
+ * @param string $pPublic Public key.
67
+ * @param string $pSecret Element's secret key.
68
+ * @param bool $pIsSandbox Whether or not to run API in sandbox mode.
69
+ */
70
+ public function Init( $pScope, $pID, $pPublic, $pSecret, $pIsSandbox = false ) {
71
+ $this->_id = $pID;
72
+ $this->_public = $pPublic;
73
+ $this->_secret = $pSecret;
74
+ $this->_scope = $pScope;
75
+ $this->_isSandbox = $pIsSandbox;
76
+ }
77
+
78
+ public function IsSandbox() {
79
+ return $this->_isSandbox;
80
+ }
81
+
82
+ function CanonizePath( $pPath ) {
83
+ $pPath = trim( $pPath, '/' );
84
+ $query_pos = strpos( $pPath, '?' );
85
+ $query = '';
86
+
87
+ if ( false !== $query_pos ) {
88
+ $query = substr( $pPath, $query_pos );
89
+ $pPath = substr( $pPath, 0, $query_pos );
90
+ }
91
+
92
+ // Trim '.json' suffix.
93
+ $format_length = strlen( '.' . self::FORMAT );
94
+ $start = $format_length * ( - 1 ); //negative
95
+ if ( substr( strtolower( $pPath ), $start ) === ( '.' . self::FORMAT ) ) {
96
+ $pPath = substr( $pPath, 0, strlen( $pPath ) - $format_length );
97
+ }
98
+
99
+ switch ( $this->_scope ) {
100
+ case 'app':
101
+ $base = '/apps/' . $this->_id;
102
+ break;
103
+ case 'developer':
104
+ $base = '/developers/' . $this->_id;
105
+ break;
106
+ case 'user':
107
+ $base = '/users/' . $this->_id;
108
+ break;
109
+ case 'plugin':
110
+ $base = '/plugins/' . $this->_id;
111
+ break;
112
+ case 'install':
113
+ $base = '/installs/' . $this->_id;
114
+ break;
115
+ default:
116
+ throw new Freemius_Exception( 'Scope not implemented.' );
117
+ }
118
+
119
+ return '/v' . FS_API__VERSION . $base .
120
+ ( ! empty( $pPath ) ? '/' : '' ) . $pPath .
121
+ ( ( false === strpos( $pPath, '.' ) ) ? '.' . self::FORMAT : '' ) . $query;
122
+ }
123
+
124
+ abstract function MakeRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array() );
125
+
126
+ /**
127
+ * @param string $pPath
128
+ * @param string $pMethod
129
+ * @param array $pParams
130
+ *
131
+ * @return object[]|object|null
132
+ */
133
+ private function _Api( $pPath, $pMethod = 'GET', $pParams = array() ) {
134
+ $pMethod = strtoupper( $pMethod );
135
+
136
+ try {
137
+ $result = $this->MakeRequest( $pPath, $pMethod, $pParams );
138
+ } catch ( Freemius_Exception $e ) {
139
+ // Map to error object.
140
+ $result = (object) $e->getResult();
141
+ } catch ( Exception $e ) {
142
+ // Map to error object.
143
+ $result = (object) array(
144
+ 'error' => (object) array(
145
+ 'type' => 'Unknown',
146
+ 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')',
147
+ 'code' => 'unknown',
148
+ 'http' => 402
149
+ )
150
+ );
151
+ }
152
+
153
+ return $result;
154
+ }
155
+
156
+ public function Api( $pPath, $pMethod = 'GET', $pParams = array() ) {
157
+ return $this->_Api( $this->CanonizePath( $pPath ), $pMethod, $pParams );
158
+ }
159
+
160
+ /**
161
+ * Base64 decoding that does not need to be urldecode()-ed.
162
+ *
163
+ * Exactly the same as PHP base64 encode except it uses
164
+ * `-` instead of `+`
165
+ * `_` instead of `/`
166
+ * No padded =
167
+ *
168
+ * @param string $input Base64UrlEncoded() string
169
+ *
170
+ * @return string
171
+ */
172
+ protected static function Base64UrlDecode( $input ) {
173
+ /**
174
+ * IMPORTANT NOTE:
175
+ * This is a hack suggested by @otto42 and @greenshady from
176
+ * the theme's review team. The usage of base64 for API
177
+ * signature encoding was approved in a Slack meeting
178
+ * held on Tue (10/25 2016).
179
+ *
180
+ * @todo Remove this hack once the base64 error is removed from the Theme Check.
181
+ *
182
+ * @since 1.2.2
183
+ * @author Vova Feldman (@svovaf)
184
+ */
185
+ $fn = 'base64' . '_decode';
186
+ return $fn( strtr( $input, '-_', '+/' ) );
187
+ }
188
+
189
+ /**
190
+ * Base64 encoding that does not need to be urlencode()ed.
191
+ *
192
+ * Exactly the same as base64 encode except it uses
193
+ * `-` instead of `+
194
+ * `_` instead of `/`
195
+ *
196
+ * @param string $input string
197
+ *
198
+ * @return string Base64 encoded string
199
+ */
200
+ protected static function Base64UrlEncode( $input ) {
201
+ /**
202
+ * IMPORTANT NOTE:
203
+ * This is a hack suggested by @otto42 and @greenshady from
204
+ * the theme's review team. The usage of base64 for API
205
+ * signature encoding was approved in a Slack meeting
206
+ * held on Tue (10/25 2016).
207
+ *
208
+ * @todo Remove this hack once the base64 error is removed from the Theme Check.
209
+ *
210
+ * @since 1.2.2
211
+ * @author Vova Feldman (@svovaf)
212
+ */
213
+ $fn = 'base64' . '_encode';
214
+ $str = strtr( $fn( $input ), '+/', '-_' );
215
+ $str = str_replace( '=', '', $str );
216
+
217
+ return $str;
218
+ }
219
+ }
freemius/includes/sdk/FreemiusWordPress.php CHANGED
@@ -14,6 +14,9 @@
14
  * License for the specific language governing permissions and limitations
15
  * under the License.
16
  */
 
 
 
17
 
18
  require_once dirname( __FILE__ ) . '/FreemiusBase.php';
19
 
@@ -709,4 +712,4 @@
709
  }
710
 
711
  #endregion
712
- }
14
  * License for the specific language governing permissions and limitations
15
  * under the License.
16
  */
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
 
21
  require_once dirname( __FILE__ ) . '/FreemiusBase.php';
22
 
712
  }
713
 
714
  #endregion
715
+ }
freemius/languages/freemius-cs_CZ.mo CHANGED
Binary file
freemius/languages/freemius-da_DK.mo CHANGED
Binary file
freemius/languages/freemius-en.mo CHANGED
Binary file
freemius/languages/freemius-es_ES.mo CHANGED
Binary file
freemius/languages/freemius-fr_FR.mo CHANGED
Binary file
freemius/languages/freemius-he_IL.mo CHANGED
Binary file
freemius/languages/freemius-hu_HU.mo CHANGED
Binary file
freemius/languages/freemius-it_IT.mo CHANGED
Binary file
freemius/languages/freemius-ja.mo CHANGED
Binary file
freemius/languages/freemius-nl_NL.mo CHANGED
Binary file
freemius/languages/freemius-ru_RU.mo CHANGED
Binary file
freemius/languages/freemius-ta.mo CHANGED
Binary file
freemius/languages/freemius-zh_CN.mo CHANGED
Binary file
freemius/languages/freemius.pot CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2020 freemius
2
  # This file is distributed under the same license as the freemius package.
3
  msgid ""
4
  msgstr ""
@@ -16,795 +16,795 @@ msgstr ""
16
  "X-Poedit-SourceCharset: UTF-8\n"
17
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18
 
19
- #: includes/class-freemius.php:1912, templates/account.php:910
20
  msgid "An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned."
21
  msgstr ""
22
 
23
- #: includes/class-freemius.php:1919
24
  msgid "Would you like to proceed with the update?"
25
  msgstr ""
26
 
27
- #: includes/class-freemius.php:2131
28
  msgid "Freemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error."
29
  msgstr ""
30
 
31
- #: includes/class-freemius.php:2133
32
  msgid "Error"
33
  msgstr ""
34
 
35
- #: includes/class-freemius.php:2533
36
  msgid "I found a better %s"
37
  msgstr ""
38
 
39
- #: includes/class-freemius.php:2535
40
  msgid "What's the %s's name?"
41
  msgstr ""
42
 
43
- #: includes/class-freemius.php:2541
44
  msgid "It's a temporary %s. I'm just debugging an issue."
45
  msgstr ""
46
 
47
- #: includes/class-freemius.php:2543
48
  msgid "Deactivation"
49
  msgstr ""
50
 
51
- #: includes/class-freemius.php:2544
52
  msgid "Theme Switch"
53
  msgstr ""
54
 
55
- #: includes/class-freemius.php:2553, templates/forms/resend-key.php:24, templates/forms/user-change.php:29
56
  msgid "Other"
57
  msgstr ""
58
 
59
- #: includes/class-freemius.php:2561
60
  msgid "I no longer need the %s"
61
  msgstr ""
62
 
63
- #: includes/class-freemius.php:2568
64
  msgid "I only needed the %s for a short period"
65
  msgstr ""
66
 
67
- #: includes/class-freemius.php:2574
68
  msgid "The %s broke my site"
69
  msgstr ""
70
 
71
- #: includes/class-freemius.php:2581
72
  msgid "The %s suddenly stopped working"
73
  msgstr ""
74
 
75
- #: includes/class-freemius.php:2591
76
  msgid "I can't pay for it anymore"
77
  msgstr ""
78
 
79
- #: includes/class-freemius.php:2593
80
  msgid "What price would you feel comfortable paying?"
81
  msgstr ""
82
 
83
- #: includes/class-freemius.php:2599
84
  msgid "I don't like to share my information with you"
85
  msgstr ""
86
 
87
- #: includes/class-freemius.php:2620
88
  msgid "The %s didn't work"
89
  msgstr ""
90
 
91
- #: includes/class-freemius.php:2630
92
  msgid "I couldn't understand how to make it work"
93
  msgstr ""
94
 
95
- #: includes/class-freemius.php:2638
96
  msgid "The %s is great, but I need specific feature that you don't support"
97
  msgstr ""
98
 
99
- #: includes/class-freemius.php:2640
100
  msgid "What feature?"
101
  msgstr ""
102
 
103
- #: includes/class-freemius.php:2644
104
  msgid "The %s is not working"
105
  msgstr ""
106
 
107
- #: includes/class-freemius.php:2646
108
  msgid "Kindly share what didn't work so we can fix it for future users..."
109
  msgstr ""
110
 
111
- #: includes/class-freemius.php:2650
112
  msgid "It's not what I was looking for"
113
  msgstr ""
114
 
115
- #: includes/class-freemius.php:2652
116
  msgid "What you've been looking for?"
117
  msgstr ""
118
 
119
- #: includes/class-freemius.php:2656
120
  msgid "The %s didn't work as expected"
121
  msgstr ""
122
 
123
- #: includes/class-freemius.php:2658
124
  msgid "What did you expect?"
125
  msgstr ""
126
 
127
- #: includes/class-freemius.php:3513, templates/debug.php:20
128
  msgid "Freemius Debug"
129
  msgstr ""
130
 
131
- #: includes/class-freemius.php:4265
132
  msgid "I don't know what is cURL or how to install it, help me!"
133
  msgstr ""
134
 
135
- #: includes/class-freemius.php:4267
136
  msgid "We'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update."
137
  msgstr ""
138
 
139
- #: includes/class-freemius.php:4274
140
  msgid "Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again."
141
  msgstr ""
142
 
143
- #: includes/class-freemius.php:4379
144
  msgid "Yes - do your thing"
145
  msgstr ""
146
 
147
- #: includes/class-freemius.php:4384
148
  msgid "No - just deactivate"
149
  msgstr ""
150
 
151
- #: includes/class-freemius.php:4429, includes/class-freemius.php:4923, includes/class-freemius.php:6182, includes/class-freemius.php:13357, includes/class-freemius.php:14075, includes/class-freemius.php:17526, includes/class-freemius.php:17631, includes/class-freemius.php:17806, includes/class-freemius.php:20040, includes/class-freemius.php:20398, includes/class-freemius.php:20408, includes/class-freemius.php:21079, includes/class-freemius.php:21985, includes/class-freemius.php:22118, includes/class-freemius.php:22274, templates/add-ons.php:57
152
  msgctxt "exclamation"
153
  msgid "Oops"
154
  msgstr ""
155
 
156
- #: includes/class-freemius.php:4498
157
  msgid "Thank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience."
158
  msgstr ""
159
 
160
- #: includes/class-freemius.php:4920
161
  msgctxt "addonX cannot run without pluginY"
162
  msgid "%s cannot run without %s."
163
  msgstr ""
164
 
165
- #: includes/class-freemius.php:4921
166
  msgctxt "addonX cannot run..."
167
  msgid "%s cannot run without the plugin."
168
  msgstr ""
169
 
170
- #: includes/class-freemius.php:5120, includes/class-freemius.php:5145, includes/class-freemius.php:21150
171
  msgid "Unexpected API error. Please contact the %s's author with the following error."
172
  msgstr ""
173
 
174
- #: includes/class-freemius.php:5848
175
  msgid "Premium %s version was successfully activated."
176
  msgstr ""
177
 
178
- #: includes/class-freemius.php:5860, includes/class-freemius.php:7762
179
  msgctxt "Used to express elation, enthusiasm, or triumph (especially in electronic communication)."
180
  msgid "W00t"
181
  msgstr ""
182
 
183
- #: includes/class-freemius.php:5875
184
  msgid "You have a %s license."
185
  msgstr ""
186
 
187
- #: includes/class-freemius.php:5879, includes/class-freemius.php:16925, includes/class-freemius.php:16936, includes/class-freemius.php:20309, includes/class-freemius.php:20659, includes/class-freemius.php:20728, includes/class-freemius.php:20900
188
  msgctxt "interjection expressing joy or exuberance"
189
  msgid "Yee-haw"
190
  msgstr ""
191
 
192
- #: includes/class-freemius.php:6165
193
  msgid "%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license."
194
  msgstr ""
195
 
196
- #: includes/class-freemius.php:6169
197
  msgid "%s is a premium only add-on. You have to purchase a license first before activating the plugin."
198
  msgstr ""
199
 
200
- #: includes/class-freemius.php:6178, templates/add-ons.php:186, templates/account/partials/addon.php:381
201
  msgid "More information about %s"
202
  msgstr ""
203
 
204
- #: includes/class-freemius.php:6179
205
  msgid "Purchase License"
206
  msgstr ""
207
 
208
- #: includes/class-freemius.php:7118, templates/connect.php:171
209
  msgid "You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to %s."
210
  msgstr ""
211
 
212
- #: includes/class-freemius.php:7122
213
  msgid "start the trial"
214
  msgstr ""
215
 
216
- #: includes/class-freemius.php:7123, templates/connect.php:175
217
  msgid "complete the install"
218
  msgstr ""
219
 
220
- #: includes/class-freemius.php:7241
221
  msgid "You are just one step away - %s"
222
  msgstr ""
223
 
224
- #: includes/class-freemius.php:7244
225
  msgctxt "%s - plugin name. As complete \"PluginX\" activation now"
226
  msgid "Complete \"%s\" Activation Now"
227
  msgstr ""
228
 
229
- #: includes/class-freemius.php:7322
230
  msgid "We made a few tweaks to the %s, %s"
231
  msgstr ""
232
 
233
- #: includes/class-freemius.php:7326
234
  msgid "Opt in to make \"%s\" better!"
235
  msgstr ""
236
 
237
- #: includes/class-freemius.php:7761
238
  msgid "The upgrade of %s was successfully completed."
239
  msgstr ""
240
 
241
- #: includes/class-freemius.php:10243, includes/class-fs-plugin-updater.php:1099, includes/class-fs-plugin-updater.php:1294, includes/class-fs-plugin-updater.php:1301, templates/auto-installation.php:32
242
  msgid "Add-On"
243
  msgstr ""
244
 
245
- #: includes/class-freemius.php:10245, templates/account.php:392, templates/account.php:400, templates/debug.php:358, templates/debug.php:549
246
  msgid "Plugin"
247
  msgstr ""
248
 
249
- #: includes/class-freemius.php:10246, templates/account.php:393, templates/account.php:401, templates/debug.php:358, templates/debug.php:549, templates/forms/deactivation/form.php:71
250
  msgid "Theme"
251
  msgstr ""
252
 
253
- #: includes/class-freemius.php:13176
254
  msgid "An unknown error has occurred while trying to toggle the license's white-label mode."
255
  msgstr ""
256
 
257
- #: includes/class-freemius.php:13190
258
  msgid "Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s."
259
  msgstr ""
260
 
261
- #: includes/class-freemius.php:13195
262
  msgid "User Dashboard"
263
  msgstr ""
264
 
265
- #: includes/class-freemius.php:13196
266
  msgid "revert it now"
267
  msgstr ""
268
 
269
- #: includes/class-freemius.php:13255
270
  msgid "An unknown error has occurred while trying to set the user's beta mode."
271
  msgstr ""
272
 
273
- #: includes/class-freemius.php:13328
274
  msgid "Invalid new user ID or email address."
275
  msgstr ""
276
 
277
- #: includes/class-freemius.php:13358, includes/class-freemius.php:22229
278
  msgid "Sorry, we could not complete the email update. Another user with the same email is already registered."
279
  msgstr ""
280
 
281
- #: includes/class-freemius.php:13359, includes/class-freemius.php:22230
282
  msgid "If you would like to give up the ownership of the %s's account to %s click the Change Ownership button."
283
  msgstr ""
284
 
285
- #: includes/class-freemius.php:13366, includes/class-freemius.php:22237
286
  msgid "Change Ownership"
287
  msgstr ""
288
 
289
- #: includes/class-freemius.php:13942
290
  msgid "Invalid site details collection."
291
  msgstr ""
292
 
293
- #: includes/class-freemius.php:14062
294
  msgid "We couldn't find your email address in the system, are you sure it's the right address?"
295
  msgstr ""
296
 
297
- #: includes/class-freemius.php:14064
298
  msgid "We can't see any active licenses associated with that email address, are you sure it's the right address?"
299
  msgstr ""
300
 
301
- #: includes/class-freemius.php:14338
302
  msgid "Account is pending activation."
303
  msgstr ""
304
 
305
- #: includes/class-freemius.php:14450, templates/forms/premium-versions-upgrade-handler.php:47
306
  msgid "Buy a license now"
307
  msgstr ""
308
 
309
- #: includes/class-freemius.php:14462, templates/forms/premium-versions-upgrade-handler.php:46
310
  msgid "Renew your license now"
311
  msgstr ""
312
 
313
- #: includes/class-freemius.php:14466
314
  msgid "%s to access version %s security & feature updates, and support."
315
  msgstr ""
316
 
317
- #: includes/class-freemius.php:16907
318
  msgid "%s activation was successfully completed."
319
  msgstr ""
320
 
321
- #: includes/class-freemius.php:16921
322
  msgid "Your account was successfully activated with the %s plan."
323
  msgstr ""
324
 
325
- #: includes/class-freemius.php:16932, includes/class-freemius.php:20724
326
  msgid "Your trial has been successfully started."
327
  msgstr ""
328
 
329
- #: includes/class-freemius.php:17524, includes/class-freemius.php:17629, includes/class-freemius.php:17804
330
  msgid "Couldn't activate %s."
331
  msgstr ""
332
 
333
- #: includes/class-freemius.php:17525, includes/class-freemius.php:17630, includes/class-freemius.php:17805
334
  msgid "Please contact us with the following message:"
335
  msgstr ""
336
 
337
- #: includes/class-freemius.php:17626, templates/forms/data-debug-mode.php:162
338
  msgid "An unknown error has occurred."
339
  msgstr ""
340
 
341
- #: includes/class-freemius.php:18162, includes/class-freemius.php:23310
342
  msgid "Upgrade"
343
  msgstr ""
344
 
345
- #: includes/class-freemius.php:18168
346
  msgid "Start Trial"
347
  msgstr ""
348
 
349
- #: includes/class-freemius.php:18170
350
  msgid "Pricing"
351
  msgstr ""
352
 
353
- #: includes/class-freemius.php:18250, includes/class-freemius.php:18252
354
  msgid "Affiliation"
355
  msgstr ""
356
 
357
- #: includes/class-freemius.php:18280, includes/class-freemius.php:18282, templates/account.php:240, templates/debug.php:324
358
  msgid "Account"
359
  msgstr ""
360
 
361
- #: includes/class-freemius.php:18296, includes/class-freemius.php:18298, includes/customizer/class-fs-customizer-support-section.php:60
362
  msgid "Contact Us"
363
  msgstr ""
364
 
365
- #: includes/class-freemius.php:18309, includes/class-freemius.php:18311, includes/class-freemius.php:23324, templates/account.php:119, templates/account/partials/addon.php:44
366
  msgid "Add-Ons"
367
  msgstr ""
368
 
369
- #: includes/class-freemius.php:18345
370
  msgctxt "ASCII arrow left icon"
371
  msgid "&#x2190;"
372
  msgstr ""
373
 
374
- #: includes/class-freemius.php:18345
375
  msgctxt "ASCII arrow right icon"
376
  msgid "&#x27a4;"
377
  msgstr ""
378
 
379
- #: includes/class-freemius.php:18347, templates/pricing.php:109
380
  msgctxt "noun"
381
  msgid "Pricing"
382
  msgstr ""
383
 
384
- #: includes/class-freemius.php:18560, includes/customizer/class-fs-customizer-support-section.php:67
385
  msgid "Support Forum"
386
  msgstr ""
387
 
388
- #: includes/class-freemius.php:19534
389
  msgid "Your email has been successfully verified - you are AWESOME!"
390
  msgstr ""
391
 
392
- #: includes/class-freemius.php:19535
393
  msgctxt "a positive response"
394
  msgid "Right on"
395
  msgstr ""
396
 
397
- #: includes/class-freemius.php:20041
398
  msgid "seems like the key you entered doesn't match our records."
399
  msgstr ""
400
 
401
- #: includes/class-freemius.php:20065
402
  msgid "Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the \"Stop Debug\" link."
403
  msgstr ""
404
 
405
- #: includes/class-freemius.php:20300
406
  msgid "Your %s Add-on plan was successfully upgraded."
407
  msgstr ""
408
 
409
- #: includes/class-freemius.php:20302
410
  msgid "%s Add-on was successfully purchased."
411
  msgstr ""
412
 
413
- #: includes/class-freemius.php:20305
414
  msgid "Download the latest version"
415
  msgstr ""
416
 
417
- #: includes/class-freemius.php:20391
418
  msgid "Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$s"
419
  msgstr ""
420
 
421
- #: includes/class-freemius.php:20397, includes/class-freemius.php:20407, includes/class-freemius.php:20859, includes/class-freemius.php:20948
422
  msgid "Error received from the server:"
423
  msgstr ""
424
 
425
- #: includes/class-freemius.php:20407
426
  msgid "It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again."
427
  msgstr ""
428
 
429
- #: includes/class-freemius.php:20621, includes/class-freemius.php:20864, includes/class-freemius.php:20919, includes/class-freemius.php:21026
430
  msgctxt "something somebody says when they are thinking about what you have just said."
431
  msgid "Hmm"
432
  msgstr ""
433
 
434
- #: includes/class-freemius.php:20634
435
  msgid "It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry."
436
  msgstr ""
437
 
438
- #: includes/class-freemius.php:20635, templates/account.php:121, templates/add-ons.php:250, templates/account/partials/addon.php:46
439
  msgctxt "trial period"
440
  msgid "Trial"
441
  msgstr ""
442
 
443
- #: includes/class-freemius.php:20640
444
  msgid "I have upgraded my account but when I try to Sync the License, the plan remains %s."
445
  msgstr ""
446
 
447
- #: includes/class-freemius.php:20644, includes/class-freemius.php:20703
448
  msgid "Please contact us here"
449
  msgstr ""
450
 
451
- #: includes/class-freemius.php:20655
452
  msgid "Your plan was successfully activated."
453
  msgstr ""
454
 
455
- #: includes/class-freemius.php:20656
456
  msgid "Your plan was successfully upgraded."
457
  msgstr ""
458
 
459
- #: includes/class-freemius.php:20673
460
  msgid "Your plan was successfully changed to %s."
461
  msgstr ""
462
 
463
- #: includes/class-freemius.php:20689
464
  msgid "Your license has expired. You can still continue using the free %s forever."
465
  msgstr ""
466
 
467
- #: includes/class-freemius.php:20691
468
  msgid "Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
469
  msgstr ""
470
 
471
- #: includes/class-freemius.php:20699
472
  msgid "Your license has been cancelled. If you think it's a mistake, please contact support."
473
  msgstr ""
474
 
475
- #: includes/class-freemius.php:20712
476
  msgid "Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support."
477
  msgstr ""
478
 
479
- #: includes/class-freemius.php:20738
480
  msgid "Your free trial has expired. You can still continue using all our free features."
481
  msgstr ""
482
 
483
- #: includes/class-freemius.php:20740
484
  msgid "Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
485
  msgstr ""
486
 
487
- #: includes/class-freemius.php:20855
488
  msgid "It looks like the license could not be activated."
489
  msgstr ""
490
 
491
- #: includes/class-freemius.php:20897
492
  msgid "Your license was successfully activated."
493
  msgstr ""
494
 
495
- #: includes/class-freemius.php:20923
496
  msgid "It looks like your site currently doesn't have an active license."
497
  msgstr ""
498
 
499
- #: includes/class-freemius.php:20947
500
  msgid "It looks like the license deactivation failed."
501
  msgstr ""
502
 
503
- #: includes/class-freemius.php:20976
504
  msgid "Your %s license was successfully deactivated."
505
  msgstr ""
506
 
507
- #: includes/class-freemius.php:20977
508
  msgid "Your license was successfully deactivated, you are back to the %s plan."
509
  msgstr ""
510
 
511
- #: includes/class-freemius.php:20980
512
  msgid "O.K"
513
  msgstr ""
514
 
515
- #: includes/class-freemius.php:21033
516
  msgid "Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes."
517
  msgstr ""
518
 
519
- #: includes/class-freemius.php:21042
520
  msgid "Your subscription was successfully cancelled. Your %s plan license will expire in %s."
521
  msgstr ""
522
 
523
- #: includes/class-freemius.php:21084
524
  msgid "You are already running the %s in a trial mode."
525
  msgstr ""
526
 
527
- #: includes/class-freemius.php:21095
528
  msgid "You already utilized a trial before."
529
  msgstr ""
530
 
531
- #: includes/class-freemius.php:21109
532
  msgid "Plan %s do not exist, therefore, can't start a trial."
533
  msgstr ""
534
 
535
- #: includes/class-freemius.php:21120
536
  msgid "Plan %s does not support a trial period."
537
  msgstr ""
538
 
539
- #: includes/class-freemius.php:21131
540
  msgid "None of the %s's plans supports a trial period."
541
  msgstr ""
542
 
543
- #: includes/class-freemius.php:21181
544
  msgid "It looks like you are not in trial mode anymore so there's nothing to cancel :)"
545
  msgstr ""
546
 
547
- #: includes/class-freemius.php:21217
548
  msgid "Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes."
549
  msgstr ""
550
 
551
- #: includes/class-freemius.php:21236
552
  msgid "Your %s free trial was successfully cancelled."
553
  msgstr ""
554
 
555
- #: includes/class-freemius.php:21552
556
  msgid "Version %s was released."
557
  msgstr ""
558
 
559
- #: includes/class-freemius.php:21552
560
  msgid "Please download %s."
561
  msgstr ""
562
 
563
- #: includes/class-freemius.php:21559
564
  msgid "the latest %s version here"
565
  msgstr ""
566
 
567
- #: includes/class-freemius.php:21564
568
  msgid "New"
569
  msgstr ""
570
 
571
- #: includes/class-freemius.php:21569
572
  msgid "Seems like you got the latest release."
573
  msgstr ""
574
 
575
- #: includes/class-freemius.php:21570
576
  msgid "You are all good!"
577
  msgstr ""
578
 
579
- #: includes/class-freemius.php:21873
580
  msgid "Verification mail was just sent to %s. If you can't find it after 5 min, please check your spam box."
581
  msgstr ""
582
 
583
- #: includes/class-freemius.php:22013
584
  msgid "Site successfully opted in."
585
  msgstr ""
586
 
587
- #: includes/class-freemius.php:22014, includes/class-freemius.php:23020
588
  msgid "Awesome"
589
  msgstr ""
590
 
591
- #: includes/class-freemius.php:22030, templates/forms/optout.php:41
592
  msgid "We appreciate your help in making the %s better by letting us track some usage data."
593
  msgstr ""
594
 
595
- #: includes/class-freemius.php:22031
596
  msgid "Thank you!"
597
  msgstr ""
598
 
599
- #: includes/class-freemius.php:22038
600
  msgid "We will no longer be sending any usage data of %s on %s to %s."
601
  msgstr ""
602
 
603
- #: includes/class-freemius.php:22196
604
  msgid "Please check your mailbox, you should receive an email via %s to confirm the ownership change. From security reasons, you must confirm the change within the next 15 min. If you cannot find the email, please check your spam folder."
605
  msgstr ""
606
 
607
- #: includes/class-freemius.php:22202
608
  msgid "Thanks for confirming the ownership change. An email was just sent to %s for final approval."
609
  msgstr ""
610
 
611
- #: includes/class-freemius.php:22207
612
  msgid "%s is the new owner of the account."
613
  msgstr ""
614
 
615
- #: includes/class-freemius.php:22209
616
  msgctxt "as congratulations"
617
  msgid "Congrats"
618
  msgstr ""
619
 
620
- #: includes/class-freemius.php:22245
621
  msgid "Your email was successfully updated. You should receive an email with confirmation instructions in few moments."
622
  msgstr ""
623
 
624
- #: includes/class-freemius.php:22257
625
  msgid "Please provide your full name."
626
  msgstr ""
627
 
628
- #: includes/class-freemius.php:22262
629
  msgid "Your name was successfully updated."
630
  msgstr ""
631
 
632
- #: includes/class-freemius.php:22323
633
  msgid "You have successfully updated your %s."
634
  msgstr ""
635
 
636
- #: includes/class-freemius.php:22382
637
  msgid "Is this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin."
638
  msgstr ""
639
 
640
- #: includes/class-freemius.php:22385
641
  msgid "Click here"
642
  msgstr ""
643
 
644
- #: includes/class-freemius.php:22483
645
  msgid "Just letting you know that the add-ons information of %s is being pulled from an external server."
646
  msgstr ""
647
 
648
- #: includes/class-freemius.php:22484
649
  msgctxt "advance notice of something that will need attention."
650
  msgid "Heads up"
651
  msgstr ""
652
 
653
- #: includes/class-freemius.php:23060
654
  msgctxt "exclamation"
655
  msgid "Hey"
656
  msgstr ""
657
 
658
- #: includes/class-freemius.php:23060
659
  msgid "How do you like %s so far? Test all our %s premium features with a %d-day free trial."
660
  msgstr ""
661
 
662
- #: includes/class-freemius.php:23068
663
  msgid "No commitment for %s days - cancel anytime!"
664
  msgstr ""
665
 
666
- #: includes/class-freemius.php:23069
667
  msgid "No credit card required"
668
  msgstr ""
669
 
670
- #: includes/class-freemius.php:23076, templates/forms/trial-start.php:53
671
  msgctxt "call to action"
672
  msgid "Start free trial"
673
  msgstr ""
674
 
675
- #: includes/class-freemius.php:23153
676
  msgid "Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!"
677
  msgstr ""
678
 
679
- #: includes/class-freemius.php:23162
680
  msgid "Learn more"
681
  msgstr ""
682
 
683
- #: includes/class-freemius.php:23348, templates/account.php:556, templates/account.php:706, templates/connect.php:179, templates/connect.php:456, templates/forms/license-activation.php:27, templates/account/partials/addon.php:321
684
  msgid "Activate License"
685
  msgstr ""
686
 
687
- #: includes/class-freemius.php:23349, templates/account.php:650, templates/account.php:705, templates/account/partials/addon.php:322, templates/account/partials/site.php:271
688
  msgid "Change License"
689
  msgstr ""
690
 
691
- #: includes/class-freemius.php:23462, templates/account/partials/site.php:169
692
  msgid "Opt Out"
693
  msgstr ""
694
 
695
- #: includes/class-freemius.php:23464, includes/class-freemius.php:23470, templates/account/partials/site.php:49, templates/account/partials/site.php:169
696
  msgid "Opt In"
697
  msgstr ""
698
 
699
- #: includes/class-freemius.php:23700
700
  msgid " The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"
701
  msgstr ""
702
 
703
- #: includes/class-freemius.php:23708
704
  msgid "Activate %s features"
705
  msgstr ""
706
 
707
- #: includes/class-freemius.php:23721
708
  msgid "Please follow these steps to complete the upgrade"
709
  msgstr ""
710
 
711
- #: includes/class-freemius.php:23725
712
  msgid "Download the latest %s version"
713
  msgstr ""
714
 
715
- #: includes/class-freemius.php:23729
716
  msgid "Upload and activate the downloaded version"
717
  msgstr ""
718
 
719
- #: includes/class-freemius.php:23731
720
  msgid "How to upload and activate?"
721
  msgstr ""
722
 
723
- #: includes/class-freemius.php:23865
724
  msgid "%sClick here%s to choose the sites where you'd like to activate the license on."
725
  msgstr ""
726
 
727
- #: includes/class-freemius.php:24034
728
  msgid "Auto installation only works for opted-in users."
729
  msgstr ""
730
 
731
- #: includes/class-freemius.php:24044, includes/class-freemius.php:24077, includes/class-fs-plugin-updater.php:1273, includes/class-fs-plugin-updater.php:1287
732
  msgid "Invalid module ID."
733
  msgstr ""
734
 
735
- #: includes/class-freemius.php:24053, includes/class-fs-plugin-updater.php:1309
736
  msgid "Premium version already active."
737
  msgstr ""
738
 
739
- #: includes/class-freemius.php:24060
740
  msgid "You do not have a valid license to access the premium version."
741
  msgstr ""
742
 
743
- #: includes/class-freemius.php:24067
744
  msgid "Plugin is a \"Serviceware\" which means it does not have a premium code version."
745
  msgstr ""
746
 
747
- #: includes/class-freemius.php:24085, includes/class-fs-plugin-updater.php:1308
748
  msgid "Premium add-on version already installed."
749
  msgstr ""
750
 
751
- #: includes/class-freemius.php:24435
752
  msgid "View paid features"
753
  msgstr ""
754
 
755
- #: includes/class-freemius.php:24757
756
  msgid "Thank you so much for using %s and its add-ons!"
757
  msgstr ""
758
 
759
- #: includes/class-freemius.php:24758
760
  msgid "Thank you so much for using %s!"
761
  msgstr ""
762
 
763
- #: includes/class-freemius.php:24764
764
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving the %s."
765
  msgstr ""
766
 
767
- #: includes/class-freemius.php:24768
768
  msgid "Thank you so much for using our products!"
769
  msgstr ""
770
 
771
- #: includes/class-freemius.php:24769
772
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving them."
773
  msgstr ""
774
 
775
- #: includes/class-freemius.php:24788
776
  msgid "%s and its add-ons"
777
  msgstr ""
778
 
779
- #: includes/class-freemius.php:24797
780
  msgid "Products"
781
  msgstr ""
782
 
783
- #: includes/class-freemius.php:24804, templates/connect.php:280
784
  msgid "Yes"
785
  msgstr ""
786
 
787
- #: includes/class-freemius.php:24805, templates/connect.php:281
788
  msgid "send me security & feature updates, educational content and offers."
789
  msgstr ""
790
 
791
- #: includes/class-freemius.php:24806, templates/connect.php:286
792
  msgid "No"
793
  msgstr ""
794
 
795
- #: includes/class-freemius.php:24808, templates/connect.php:288
796
  msgid "do %sNOT%s send me security & feature updates, educational content and offers."
797
  msgstr ""
798
 
799
- #: includes/class-freemius.php:24818
800
  msgid "Due to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)"
801
  msgstr ""
802
 
803
- #: includes/class-freemius.php:24820, templates/connect.php:295
804
  msgid "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:"
805
  msgstr ""
806
 
807
- #: includes/class-freemius.php:25102
808
  msgid "License key is empty."
809
  msgstr ""
810
 
@@ -832,15 +832,15 @@ msgstr ""
832
  msgid "Important Upgrade Notice:"
833
  msgstr ""
834
 
835
- #: includes/class-fs-plugin-updater.php:1338
836
  msgid "Installing plugin: %s"
837
  msgstr ""
838
 
839
- #: includes/class-fs-plugin-updater.php:1379
840
  msgid "Unable to connect to the filesystem. Please confirm your credentials."
841
  msgstr ""
842
 
843
- #: includes/class-fs-plugin-updater.php:1561
844
  msgid "The remote plugin package does not contain a folder with the desired slug and renaming did not work."
845
  msgstr ""
846
 
@@ -861,7 +861,7 @@ msgstr ""
861
  msgid "Install Free Version Update Now"
862
  msgstr ""
863
 
864
- #: includes/fs-plugin-info-dialog.php:745, templates/account.php:639
865
  msgid "Install Update Now"
866
  msgstr ""
867
 
@@ -878,7 +878,7 @@ msgctxt "as download latest version"
878
  msgid "Download Latest Free Version"
879
  msgstr ""
880
 
881
- #: includes/fs-plugin-info-dialog.php:772, templates/account.php:99, templates/add-ons.php:37, templates/account/partials/addon.php:25
882
  msgctxt "as download latest version"
883
  msgid "Download Latest"
884
  msgstr ""
@@ -887,11 +887,11 @@ msgstr ""
887
  msgid "Activate this add-on"
888
  msgstr ""
889
 
890
- #: includes/fs-plugin-info-dialog.php:789, templates/connect.php:453
891
  msgid "Activate Free Version"
892
  msgstr ""
893
 
894
- #: includes/fs-plugin-info-dialog.php:790, templates/account.php:123, templates/add-ons.php:330, templates/account/partials/addon.php:48
895
  msgid "Activate"
896
  msgstr ""
897
 
@@ -1020,7 +1020,7 @@ msgstr ""
1020
  msgid "Details"
1021
  msgstr ""
1022
 
1023
- #: includes/fs-plugin-info-dialog.php:1318, templates/account.php:110, templates/debug.php:201, templates/debug.php:238, templates/debug.php:455, templates/account/partials/addon.php:36
1024
  msgctxt "product version"
1025
  msgid "Version"
1026
  msgstr ""
@@ -1034,7 +1034,7 @@ msgstr ""
1034
  msgid "Last Updated"
1035
  msgstr ""
1036
 
1037
- #: includes/fs-plugin-info-dialog.php:1337, templates/account.php:525
1038
  msgctxt "x-ago"
1039
  msgid "%s ago"
1040
  msgstr ""
@@ -1143,293 +1143,293 @@ msgstr ""
1143
  msgid "Latest Free Version Installed"
1144
  msgstr ""
1145
 
1146
- #: templates/account.php:100, templates/forms/subscription-cancellation.php:96, templates/account/partials/addon.php:26, templates/account/partials/site.php:311
1147
  msgid "Downgrading your plan"
1148
  msgstr ""
1149
 
1150
- #: templates/account.php:101, templates/forms/subscription-cancellation.php:97, templates/account/partials/addon.php:27, templates/account/partials/site.php:312
1151
  msgid "Cancelling the subscription"
1152
  msgstr ""
1153
 
1154
  #. translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription'
1155
- #: templates/account.php:103, templates/forms/subscription-cancellation.php:99, templates/account/partials/site.php:314
1156
  msgid "%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s."
1157
  msgstr ""
1158
 
1159
- #: templates/account.php:104, templates/forms/subscription-cancellation.php:100, templates/account/partials/addon.php:30, templates/account/partials/site.php:315
1160
  msgid "Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price."
1161
  msgstr ""
1162
 
1163
- #: templates/account.php:105, templates/forms/subscription-cancellation.php:106, templates/account/partials/addon.php:31
1164
  msgid "Cancelling the trial will immediately block access to all premium features. Are you sure?"
1165
  msgstr ""
1166
 
1167
- #: templates/account.php:106, templates/forms/subscription-cancellation.php:101, templates/account/partials/addon.php:32, templates/account/partials/site.php:316
1168
  msgid "You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support."
1169
  msgstr ""
1170
 
1171
- #: templates/account.php:107, templates/forms/subscription-cancellation.php:102, templates/account/partials/addon.php:33, templates/account/partials/site.php:317
1172
  msgid "Once your license expires you can still use the Free version but you will NOT have access to the %s features."
1173
  msgstr ""
1174
 
1175
  #. translators: %s: Plan title (e.g. "Professional")
1176
- #: templates/account.php:109, templates/account/partials/activate-license-button.php:31, templates/account/partials/addon.php:35
1177
  msgid "Activate %s Plan"
1178
  msgstr ""
1179
 
1180
  #. translators: %s: Time period (e.g. Auto renews in "2 months")
1181
- #: templates/account.php:112, templates/account/partials/addon.php:38, templates/account/partials/site.php:291
1182
  msgid "Auto renews in %s"
1183
  msgstr ""
1184
 
1185
  #. translators: %s: Time period (e.g. Expires in "2 months")
1186
- #: templates/account.php:114, templates/account/partials/addon.php:40, templates/account/partials/site.php:293
1187
  msgid "Expires in %s"
1188
  msgstr ""
1189
 
1190
- #: templates/account.php:115
1191
  msgctxt "as synchronize license"
1192
  msgid "Sync License"
1193
  msgstr ""
1194
 
1195
- #: templates/account.php:116, templates/account/partials/addon.php:41
1196
  msgid "Cancel Trial"
1197
  msgstr ""
1198
 
1199
- #: templates/account.php:117, templates/account/partials/addon.php:42
1200
  msgid "Change Plan"
1201
  msgstr ""
1202
 
1203
- #: templates/account.php:118, templates/account/partials/addon.php:43
1204
  msgctxt "verb"
1205
  msgid "Upgrade"
1206
  msgstr ""
1207
 
1208
- #: templates/account.php:120, templates/account/partials/addon.php:45, templates/account/partials/site.php:318
1209
  msgctxt "verb"
1210
  msgid "Downgrade"
1211
  msgstr ""
1212
 
1213
- #: templates/account.php:122, templates/add-ons.php:246, templates/plugin-info/features.php:72, templates/account/partials/addon.php:47, templates/account/partials/site.php:33
1214
  msgid "Free"
1215
  msgstr ""
1216
 
1217
- #: templates/account.php:124, templates/debug.php:371, includes/customizer/class-fs-customizer-upsell-control.php:110, templates/account/partials/addon.php:49
1218
  msgctxt "as product pricing plan"
1219
  msgid "Plan"
1220
  msgstr ""
1221
 
1222
- #: templates/account.php:125
1223
  msgid "Bundle Plan"
1224
  msgstr ""
1225
 
1226
- #: templates/account.php:248
1227
  msgid "Free Trial"
1228
  msgstr ""
1229
 
1230
- #: templates/account.php:259
1231
  msgid "Account Details"
1232
  msgstr ""
1233
 
1234
- #: templates/account.php:266, templates/forms/data-debug-mode.php:33
1235
  msgid "Start Debug"
1236
  msgstr ""
1237
 
1238
- #: templates/account.php:268
1239
  msgid "Stop Debug"
1240
  msgstr ""
1241
 
1242
- #: templates/account.php:275
1243
  msgid "Billing & Invoices"
1244
  msgstr ""
1245
 
1246
- #: templates/account.php:286
1247
  msgid "Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the \"Cancel\" button, and first \"Downgrade\" your account. Are you sure you would like to continue with the deletion?"
1248
  msgstr ""
1249
 
1250
- #: templates/account.php:288
1251
  msgid "Deletion is not temporary. Only delete if you no longer want to use this %s anymore. Are you sure you would like to continue with the deletion?"
1252
  msgstr ""
1253
 
1254
- #: templates/account.php:291
1255
  msgid "Delete Account"
1256
  msgstr ""
1257
 
1258
- #: templates/account.php:303, templates/account/partials/addon.php:231, templates/account/partials/deactivate-license-button.php:35
1259
  msgid "Deactivate License"
1260
  msgstr ""
1261
 
1262
- #: templates/account.php:326, templates/forms/subscription-cancellation.php:125
1263
  msgid "Are you sure you want to proceed?"
1264
  msgstr ""
1265
 
1266
- #: templates/account.php:326, templates/account/partials/addon.php:255
1267
  msgid "Cancel Subscription"
1268
  msgstr ""
1269
 
1270
- #: templates/account.php:355, templates/account/partials/addon.php:340
1271
  msgctxt "as synchronize"
1272
  msgid "Sync"
1273
  msgstr ""
1274
 
1275
- #: templates/account.php:370, templates/debug.php:505
1276
  msgid "Name"
1277
  msgstr ""
1278
 
1279
- #: templates/account.php:376, templates/debug.php:506
1280
  msgid "Email"
1281
  msgstr ""
1282
 
1283
- #: templates/account.php:383, templates/debug.php:369, templates/debug.php:555
1284
  msgid "User ID"
1285
  msgstr ""
1286
 
1287
- #: templates/account.php:401, templates/account.php:719, templates/account.php:752, templates/debug.php:236, templates/debug.php:363, templates/debug.php:452, templates/debug.php:504, templates/debug.php:553, templates/debug.php:632, templates/account/payments.php:35, templates/debug/logger.php:21
1288
  msgid "ID"
1289
  msgstr ""
1290
 
1291
- #: templates/account.php:408
1292
  msgid "Site ID"
1293
  msgstr ""
1294
 
1295
- #: templates/account.php:411
1296
  msgid "No ID"
1297
  msgstr ""
1298
 
1299
- #: templates/account.php:416, templates/debug.php:243, templates/debug.php:372, templates/debug.php:456, templates/debug.php:508, templates/account/partials/site.php:227
1300
  msgid "Public Key"
1301
  msgstr ""
1302
 
1303
- #: templates/account.php:422, templates/debug.php:373, templates/debug.php:457, templates/debug.php:509, templates/account/partials/site.php:239
1304
  msgid "Secret Key"
1305
  msgstr ""
1306
 
1307
- #: templates/account.php:425
1308
  msgctxt "as secret encryption key missing"
1309
  msgid "No Secret"
1310
  msgstr ""
1311
 
1312
- #: templates/account.php:452, templates/account/partials/site.php:120, templates/account/partials/site.php:122
1313
  msgid "Trial"
1314
  msgstr ""
1315
 
1316
- #: templates/account.php:479, templates/debug.php:561, templates/account/partials/site.php:260
1317
  msgid "License Key"
1318
  msgstr ""
1319
 
1320
- #: templates/account.php:510
1321
  msgid "Join the Beta program"
1322
  msgstr ""
1323
 
1324
- #: templates/account.php:516
1325
  msgid "not verified"
1326
  msgstr ""
1327
 
1328
- #: templates/account.php:525, templates/account/partials/addon.php:190
1329
  msgid "Expired"
1330
  msgstr ""
1331
 
1332
- #: templates/account.php:585
1333
  msgid "Premium version"
1334
  msgstr ""
1335
 
1336
- #: templates/account.php:587
1337
  msgid "Free version"
1338
  msgstr ""
1339
 
1340
- #: templates/account.php:599
1341
  msgid "Verify Email"
1342
  msgstr ""
1343
 
1344
- #: templates/account.php:613
1345
  msgid "Download %s Version"
1346
  msgstr ""
1347
 
1348
- #: templates/account.php:629
1349
  msgid "Download Paid Version"
1350
  msgstr ""
1351
 
1352
- #: templates/account.php:647, templates/account.php:890, templates/account/partials/site.php:248, templates/account/partials/site.php:270
1353
  msgctxt "verb"
1354
  msgid "Show"
1355
  msgstr ""
1356
 
1357
- #: templates/account.php:662
1358
  msgid "What is your %s?"
1359
  msgstr ""
1360
 
1361
- #: templates/account.php:670, templates/account/billing.php:21
1362
  msgctxt "verb"
1363
  msgid "Edit"
1364
  msgstr ""
1365
 
1366
- #: templates/account.php:674, templates/forms/user-change.php:27
1367
  msgid "Change User"
1368
  msgstr ""
1369
 
1370
- #: templates/account.php:698
1371
  msgid "Sites"
1372
  msgstr ""
1373
 
1374
- #: templates/account.php:711
1375
  msgid "Search by address"
1376
  msgstr ""
1377
 
1378
- #: templates/account.php:720, templates/debug.php:366
1379
  msgid "Address"
1380
  msgstr ""
1381
 
1382
- #: templates/account.php:721
1383
  msgid "License"
1384
  msgstr ""
1385
 
1386
- #: templates/account.php:722
1387
  msgid "Plan"
1388
  msgstr ""
1389
 
1390
- #: templates/account.php:755
1391
  msgctxt "as software license"
1392
  msgid "License"
1393
  msgstr ""
1394
 
1395
- #: templates/account.php:884
1396
  msgctxt "verb"
1397
  msgid "Hide"
1398
  msgstr ""
1399
 
1400
- #: templates/account.php:906, templates/forms/data-debug-mode.php:31
1401
  msgid "Processing"
1402
  msgstr ""
1403
 
1404
- #: templates/account.php:909
1405
  msgid "Get updates for bleeding edge Beta versions of %s."
1406
  msgstr ""
1407
 
1408
- #: templates/account.php:967
1409
  msgid "Cancelling %s"
1410
  msgstr ""
1411
 
1412
- #: templates/account.php:967, templates/account.php:984, templates/forms/subscription-cancellation.php:27, templates/forms/deactivation/form.php:133
1413
  msgid "trial"
1414
  msgstr ""
1415
 
1416
- #: templates/account.php:982, templates/forms/deactivation/form.php:150
1417
  msgid "Cancelling %s..."
1418
  msgstr ""
1419
 
1420
- #: templates/account.php:985, templates/forms/subscription-cancellation.php:28, templates/forms/deactivation/form.php:134
1421
  msgid "subscription"
1422
  msgstr ""
1423
 
1424
- #: templates/account.php:999
1425
  msgid "Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?"
1426
  msgstr ""
1427
 
1428
- #: templates/account.php:1073
1429
  msgid "Disabling white-label mode"
1430
  msgstr ""
1431
 
1432
- #: templates/account.php:1074
1433
  msgid "Enabling white-label mode"
1434
  msgstr ""
1435
 
@@ -1455,7 +1455,7 @@ msgctxt "installed add-on"
1455
  msgid "Installed"
1456
  msgstr ""
1457
 
1458
- #: templates/admin-notice.php:13, templates/forms/license-activation.php:220, templates/forms/resend-key.php:77
1459
  msgctxt "as close a window"
1460
  msgid "Dismiss"
1461
  msgstr ""
@@ -1510,84 +1510,92 @@ msgstr ""
1510
  msgid "Agree & Activate License"
1511
  msgstr ""
1512
 
1513
- #: templates/connect.php:189
1514
- msgid "Thanks for purchasing %s! To get started, please enter your license key:"
1515
  msgstr ""
1516
 
1517
- #: templates/connect.php:196
1518
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s."
1519
  msgstr ""
1520
 
1521
- #: templates/connect.php:197
1522
  msgid "Never miss an important update - opt in to our security and feature updates notifications, and non-sensitive diagnostic tracking with %4$s."
1523
  msgstr ""
1524
 
1525
- #: templates/connect.php:203
1526
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1527
  msgstr ""
1528
 
1529
- #: templates/connect.php:204
1530
  msgid "Never miss an important update - opt in to our security & feature updates notifications, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1531
  msgstr ""
1532
 
1533
- #: templates/connect.php:238
1534
  msgid "We're excited to introduce the Freemius network-level integration."
1535
  msgstr ""
1536
 
1537
- #: templates/connect.php:241
1538
  msgid "During the update process we detected %d site(s) that are still pending license activation."
1539
  msgstr ""
1540
 
1541
- #: templates/connect.php:243
1542
  msgid "If you'd like to use the %s on those sites, please enter your license key below and click the activation button."
1543
  msgstr ""
1544
 
1545
- #: templates/connect.php:245
1546
  msgid "%s's paid features"
1547
  msgstr ""
1548
 
1549
- #: templates/connect.php:250
1550
  msgid "Alternatively, you can skip it for now and activate the license later, in your %s's network-level Account page."
1551
  msgstr ""
1552
 
1553
- #: templates/connect.php:252
1554
  msgid "During the update process we detected %s site(s) in the network that are still pending your attention."
1555
  msgstr ""
1556
 
1557
- #: templates/connect.php:261, templates/forms/data-debug-mode.php:35, templates/forms/license-activation.php:49
1558
  msgid "License key"
1559
  msgstr ""
1560
 
1561
- #: templates/connect.php:264, templates/forms/license-activation.php:22
1562
  msgid "Can't find your license key?"
1563
  msgstr ""
1564
 
1565
- #: templates/connect.php:323, templates/connect.php:695, templates/forms/deactivation/retry-skip.php:20
1566
  msgctxt "verb"
1567
  msgid "Skip"
1568
  msgstr ""
1569
 
1570
- #: templates/connect.php:326
1571
  msgid "Delegate to Site Admins"
1572
  msgstr ""
1573
 
1574
- #: templates/connect.php:326
1575
  msgid "If you click it, this decision will be delegated to the sites administrators."
1576
  msgstr ""
1577
 
1578
- #: templates/connect.php:364
 
 
 
 
1579
  msgid "Your Profile Overview"
1580
  msgstr ""
1581
 
1582
- #: templates/connect.php:365
1583
  msgid "Name and email address"
1584
  msgstr ""
1585
 
1586
- #: templates/connect.php:372
 
 
 
 
1587
  msgid "Your Site Overview"
1588
  msgstr ""
1589
 
1590
- #: templates/connect.php:373
1591
  msgid "Site URL, WP version, PHP info"
1592
  msgstr ""
1593
 
@@ -1595,64 +1603,84 @@ msgstr ""
1595
  msgid "Admin Notices"
1596
  msgstr ""
1597
 
1598
- #: templates/connect.php:380, templates/connect.php:396
1599
  msgid "Updates, announcements, marketing, no spam"
1600
  msgstr ""
1601
 
1602
- #: templates/connect.php:386
1603
- msgid "Current %s Events"
 
 
 
 
1604
  msgstr ""
1605
 
1606
- #: templates/connect.php:387
1607
- msgid "Activation, deactivation and uninstall"
1608
  msgstr ""
1609
 
1610
- #: templates/connect.php:395
1611
  msgid "Newsletter"
1612
  msgstr ""
1613
 
1614
- #: templates/connect.php:403
1615
  msgid "Plugins & Themes"
1616
  msgstr ""
1617
 
1618
- #: templates/connect.php:404
 
 
 
 
 
 
 
 
1619
  msgid "Title, slug, version, and is active"
1620
  msgstr ""
1621
 
1622
- #: templates/connect.php:421, templates/forms/license-activation.php:41
1623
- msgid "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."
1624
  msgstr ""
1625
 
1626
  #: templates/connect.php:426
 
 
 
 
 
 
 
 
1627
  msgid "What permissions are being granted?"
1628
  msgstr ""
1629
 
1630
- #: templates/connect.php:452
1631
  msgid "Don't have a license key?"
1632
  msgstr ""
1633
 
1634
- #: templates/connect.php:455
1635
  msgid "Have a license key?"
1636
  msgstr ""
1637
 
1638
- #: templates/connect.php:463
1639
  msgid "Privacy Policy"
1640
  msgstr ""
1641
 
1642
- #: templates/connect.php:465
1643
  msgid "License Agreement"
1644
  msgstr ""
1645
 
1646
- #: templates/connect.php:465
1647
  msgid "Terms of Service"
1648
  msgstr ""
1649
 
1650
- #: templates/connect.php:854
1651
  msgctxt "as in the process of sending an email"
1652
  msgid "Sending email"
1653
  msgstr ""
1654
 
1655
- #: templates/connect.php:855
1656
  msgctxt "as activating plugin"
1657
  msgid "Activating"
1658
  msgstr ""
@@ -2241,7 +2269,11 @@ msgstr ""
2241
  msgid "Update License"
2242
  msgstr ""
2243
 
2244
- #: templates/forms/license-activation.php:181
 
 
 
 
2245
  msgid "Associate with the license owner's account."
2246
  msgstr ""
2247
 
1
+ # Copyright (C) 2021 freemius
2
  # This file is distributed under the same license as the freemius package.
3
  msgid ""
4
  msgstr ""
16
  "X-Poedit-SourceCharset: UTF-8\n"
17
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18
 
19
+ #: includes/class-freemius.php:1919, templates/account.php:912
20
  msgid "An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned."
21
  msgstr ""
22
 
23
+ #: includes/class-freemius.php:1926
24
  msgid "Would you like to proceed with the update?"
25
  msgstr ""
26
 
27
+ #: includes/class-freemius.php:2138
28
  msgid "Freemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error."
29
  msgstr ""
30
 
31
+ #: includes/class-freemius.php:2140
32
  msgid "Error"
33
  msgstr ""
34
 
35
+ #: includes/class-freemius.php:2540
36
  msgid "I found a better %s"
37
  msgstr ""
38
 
39
+ #: includes/class-freemius.php:2542
40
  msgid "What's the %s's name?"
41
  msgstr ""
42
 
43
+ #: includes/class-freemius.php:2548
44
  msgid "It's a temporary %s. I'm just debugging an issue."
45
  msgstr ""
46
 
47
+ #: includes/class-freemius.php:2550
48
  msgid "Deactivation"
49
  msgstr ""
50
 
51
+ #: includes/class-freemius.php:2551
52
  msgid "Theme Switch"
53
  msgstr ""
54
 
55
+ #: includes/class-freemius.php:2560, templates/forms/resend-key.php:24, templates/forms/user-change.php:29
56
  msgid "Other"
57
  msgstr ""
58
 
59
+ #: includes/class-freemius.php:2568
60
  msgid "I no longer need the %s"
61
  msgstr ""
62
 
63
+ #: includes/class-freemius.php:2575
64
  msgid "I only needed the %s for a short period"
65
  msgstr ""
66
 
67
+ #: includes/class-freemius.php:2581
68
  msgid "The %s broke my site"
69
  msgstr ""
70
 
71
+ #: includes/class-freemius.php:2588
72
  msgid "The %s suddenly stopped working"
73
  msgstr ""
74
 
75
+ #: includes/class-freemius.php:2598
76
  msgid "I can't pay for it anymore"
77
  msgstr ""
78
 
79
+ #: includes/class-freemius.php:2600
80
  msgid "What price would you feel comfortable paying?"
81
  msgstr ""
82
 
83
+ #: includes/class-freemius.php:2606
84
  msgid "I don't like to share my information with you"
85
  msgstr ""
86
 
87
+ #: includes/class-freemius.php:2627
88
  msgid "The %s didn't work"
89
  msgstr ""
90
 
91
+ #: includes/class-freemius.php:2637
92
  msgid "I couldn't understand how to make it work"
93
  msgstr ""
94
 
95
+ #: includes/class-freemius.php:2645
96
  msgid "The %s is great, but I need specific feature that you don't support"
97
  msgstr ""
98
 
99
+ #: includes/class-freemius.php:2647
100
  msgid "What feature?"
101
  msgstr ""
102
 
103
+ #: includes/class-freemius.php:2651
104
  msgid "The %s is not working"
105
  msgstr ""
106
 
107
+ #: includes/class-freemius.php:2653
108
  msgid "Kindly share what didn't work so we can fix it for future users..."
109
  msgstr ""
110
 
111
+ #: includes/class-freemius.php:2657
112
  msgid "It's not what I was looking for"
113
  msgstr ""
114
 
115
+ #: includes/class-freemius.php:2659
116
  msgid "What you've been looking for?"
117
  msgstr ""
118
 
119
+ #: includes/class-freemius.php:2663
120
  msgid "The %s didn't work as expected"
121
  msgstr ""
122
 
123
+ #: includes/class-freemius.php:2665
124
  msgid "What did you expect?"
125
  msgstr ""
126
 
127
+ #: includes/class-freemius.php:3520, templates/debug.php:20
128
  msgid "Freemius Debug"
129
  msgstr ""
130
 
131
+ #: includes/class-freemius.php:4272
132
  msgid "I don't know what is cURL or how to install it, help me!"
133
  msgstr ""
134
 
135
+ #: includes/class-freemius.php:4274
136
  msgid "We'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update."
137
  msgstr ""
138
 
139
+ #: includes/class-freemius.php:4281
140
  msgid "Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again."
141
  msgstr ""
142
 
143
+ #: includes/class-freemius.php:4386
144
  msgid "Yes - do your thing"
145
  msgstr ""
146
 
147
+ #: includes/class-freemius.php:4391
148
  msgid "No - just deactivate"
149
  msgstr ""
150
 
151
+ #: includes/class-freemius.php:4436, includes/class-freemius.php:4930, includes/class-freemius.php:6191, includes/class-freemius.php:13368, includes/class-freemius.php:14110, includes/class-freemius.php:17542, includes/class-freemius.php:17647, includes/class-freemius.php:17822, includes/class-freemius.php:20056, includes/class-freemius.php:20414, includes/class-freemius.php:20424, includes/class-freemius.php:21109, includes/class-freemius.php:22015, includes/class-freemius.php:22148, includes/class-freemius.php:22304, templates/add-ons.php:57
152
  msgctxt "exclamation"
153
  msgid "Oops"
154
  msgstr ""
155
 
156
+ #: includes/class-freemius.php:4505
157
  msgid "Thank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience."
158
  msgstr ""
159
 
160
+ #: includes/class-freemius.php:4927
161
  msgctxt "addonX cannot run without pluginY"
162
  msgid "%s cannot run without %s."
163
  msgstr ""
164
 
165
+ #: includes/class-freemius.php:4928
166
  msgctxt "addonX cannot run..."
167
  msgid "%s cannot run without the plugin."
168
  msgstr ""
169
 
170
+ #: includes/class-freemius.php:5127, includes/class-freemius.php:5152, includes/class-freemius.php:21180
171
  msgid "Unexpected API error. Please contact the %s's author with the following error."
172
  msgstr ""
173
 
174
+ #: includes/class-freemius.php:5857
175
  msgid "Premium %s version was successfully activated."
176
  msgstr ""
177
 
178
+ #: includes/class-freemius.php:5869, includes/class-freemius.php:7774
179
  msgctxt "Used to express elation, enthusiasm, or triumph (especially in electronic communication)."
180
  msgid "W00t"
181
  msgstr ""
182
 
183
+ #: includes/class-freemius.php:5884
184
  msgid "You have a %s license."
185
  msgstr ""
186
 
187
+ #: includes/class-freemius.php:5888, includes/class-freemius.php:16947, includes/class-freemius.php:16958, includes/class-freemius.php:20325, includes/class-freemius.php:20689, includes/class-freemius.php:20758, includes/class-freemius.php:20930
188
  msgctxt "interjection expressing joy or exuberance"
189
  msgid "Yee-haw"
190
  msgstr ""
191
 
192
+ #: includes/class-freemius.php:6174
193
  msgid "%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license."
194
  msgstr ""
195
 
196
+ #: includes/class-freemius.php:6178
197
  msgid "%s is a premium only add-on. You have to purchase a license first before activating the plugin."
198
  msgstr ""
199
 
200
+ #: includes/class-freemius.php:6187, templates/add-ons.php:186, templates/account/partials/addon.php:381
201
  msgid "More information about %s"
202
  msgstr ""
203
 
204
+ #: includes/class-freemius.php:6188
205
  msgid "Purchase License"
206
  msgstr ""
207
 
208
+ #: includes/class-freemius.php:7125, templates/connect.php:171
209
  msgid "You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to %s."
210
  msgstr ""
211
 
212
+ #: includes/class-freemius.php:7129
213
  msgid "start the trial"
214
  msgstr ""
215
 
216
+ #: includes/class-freemius.php:7130, templates/connect.php:175
217
  msgid "complete the install"
218
  msgstr ""
219
 
220
+ #: includes/class-freemius.php:7249
221
  msgid "You are just one step away - %s"
222
  msgstr ""
223
 
224
+ #: includes/class-freemius.php:7252
225
  msgctxt "%s - plugin name. As complete \"PluginX\" activation now"
226
  msgid "Complete \"%s\" Activation Now"
227
  msgstr ""
228
 
229
+ #: includes/class-freemius.php:7334
230
  msgid "We made a few tweaks to the %s, %s"
231
  msgstr ""
232
 
233
+ #: includes/class-freemius.php:7338
234
  msgid "Opt in to make \"%s\" better!"
235
  msgstr ""
236
 
237
+ #: includes/class-freemius.php:7773
238
  msgid "The upgrade of %s was successfully completed."
239
  msgstr ""
240
 
241
+ #: includes/class-freemius.php:10255, includes/class-fs-plugin-updater.php:1087, includes/class-fs-plugin-updater.php:1282, includes/class-fs-plugin-updater.php:1289, templates/auto-installation.php:32
242
  msgid "Add-On"
243
  msgstr ""
244
 
245
+ #: includes/class-freemius.php:10257, templates/account.php:394, templates/account.php:402, templates/debug.php:358, templates/debug.php:549
246
  msgid "Plugin"
247
  msgstr ""
248
 
249
+ #: includes/class-freemius.php:10258, templates/account.php:395, templates/account.php:403, templates/debug.php:358, templates/debug.php:549, templates/forms/deactivation/form.php:71
250
  msgid "Theme"
251
  msgstr ""
252
 
253
+ #: includes/class-freemius.php:13188
254
  msgid "An unknown error has occurred while trying to toggle the license's white-label mode."
255
  msgstr ""
256
 
257
+ #: includes/class-freemius.php:13202
258
  msgid "Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s."
259
  msgstr ""
260
 
261
+ #: includes/class-freemius.php:13207
262
  msgid "User Dashboard"
263
  msgstr ""
264
 
265
+ #: includes/class-freemius.php:13208
266
  msgid "revert it now"
267
  msgstr ""
268
 
269
+ #: includes/class-freemius.php:13266
270
  msgid "An unknown error has occurred while trying to set the user's beta mode."
271
  msgstr ""
272
 
273
+ #: includes/class-freemius.php:13339
274
  msgid "Invalid new user ID or email address."
275
  msgstr ""
276
 
277
+ #: includes/class-freemius.php:13369, includes/class-freemius.php:22259
278
  msgid "Sorry, we could not complete the email update. Another user with the same email is already registered."
279
  msgstr ""
280
 
281
+ #: includes/class-freemius.php:13370, includes/class-freemius.php:22260
282
  msgid "If you would like to give up the ownership of the %s's account to %s click the Change Ownership button."
283
  msgstr ""
284
 
285
+ #: includes/class-freemius.php:13377, includes/class-freemius.php:22267
286
  msgid "Change Ownership"
287
  msgstr ""
288
 
289
+ #: includes/class-freemius.php:13977
290
  msgid "Invalid site details collection."
291
  msgstr ""
292
 
293
+ #: includes/class-freemius.php:14097
294
  msgid "We couldn't find your email address in the system, are you sure it's the right address?"
295
  msgstr ""
296
 
297
+ #: includes/class-freemius.php:14099
298
  msgid "We can't see any active licenses associated with that email address, are you sure it's the right address?"
299
  msgstr ""
300
 
301
+ #: includes/class-freemius.php:14373
302
  msgid "Account is pending activation."
303
  msgstr ""
304
 
305
+ #: includes/class-freemius.php:14485, templates/forms/premium-versions-upgrade-handler.php:47
306
  msgid "Buy a license now"
307
  msgstr ""
308
 
309
+ #: includes/class-freemius.php:14497, templates/forms/premium-versions-upgrade-handler.php:46
310
  msgid "Renew your license now"
311
  msgstr ""
312
 
313
+ #: includes/class-freemius.php:14501
314
  msgid "%s to access version %s security & feature updates, and support."
315
  msgstr ""
316
 
317
+ #: includes/class-freemius.php:16929
318
  msgid "%s activation was successfully completed."
319
  msgstr ""
320
 
321
+ #: includes/class-freemius.php:16943
322
  msgid "Your account was successfully activated with the %s plan."
323
  msgstr ""
324
 
325
+ #: includes/class-freemius.php:16954, includes/class-freemius.php:20754
326
  msgid "Your trial has been successfully started."
327
  msgstr ""
328
 
329
+ #: includes/class-freemius.php:17540, includes/class-freemius.php:17645, includes/class-freemius.php:17820
330
  msgid "Couldn't activate %s."
331
  msgstr ""
332
 
333
+ #: includes/class-freemius.php:17541, includes/class-freemius.php:17646, includes/class-freemius.php:17821
334
  msgid "Please contact us with the following message:"
335
  msgstr ""
336
 
337
+ #: includes/class-freemius.php:17642, templates/forms/data-debug-mode.php:162
338
  msgid "An unknown error has occurred."
339
  msgstr ""
340
 
341
+ #: includes/class-freemius.php:18178, includes/class-freemius.php:23340
342
  msgid "Upgrade"
343
  msgstr ""
344
 
345
+ #: includes/class-freemius.php:18184
346
  msgid "Start Trial"
347
  msgstr ""
348
 
349
+ #: includes/class-freemius.php:18186
350
  msgid "Pricing"
351
  msgstr ""
352
 
353
+ #: includes/class-freemius.php:18266, includes/class-freemius.php:18268
354
  msgid "Affiliation"
355
  msgstr ""
356
 
357
+ #: includes/class-freemius.php:18296, includes/class-freemius.php:18298, templates/account.php:242, templates/debug.php:324
358
  msgid "Account"
359
  msgstr ""
360
 
361
+ #: includes/class-freemius.php:18312, includes/class-freemius.php:18314, includes/customizer/class-fs-customizer-support-section.php:60
362
  msgid "Contact Us"
363
  msgstr ""
364
 
365
+ #: includes/class-freemius.php:18325, includes/class-freemius.php:18327, includes/class-freemius.php:23354, templates/account.php:121, templates/account/partials/addon.php:44
366
  msgid "Add-Ons"
367
  msgstr ""
368
 
369
+ #: includes/class-freemius.php:18361
370
  msgctxt "ASCII arrow left icon"
371
  msgid "&#x2190;"
372
  msgstr ""
373
 
374
+ #: includes/class-freemius.php:18361
375
  msgctxt "ASCII arrow right icon"
376
  msgid "&#x27a4;"
377
  msgstr ""
378
 
379
+ #: includes/class-freemius.php:18363, templates/pricing.php:109
380
  msgctxt "noun"
381
  msgid "Pricing"
382
  msgstr ""
383
 
384
+ #: includes/class-freemius.php:18576, includes/customizer/class-fs-customizer-support-section.php:67
385
  msgid "Support Forum"
386
  msgstr ""
387
 
388
+ #: includes/class-freemius.php:19550
389
  msgid "Your email has been successfully verified - you are AWESOME!"
390
  msgstr ""
391
 
392
+ #: includes/class-freemius.php:19551
393
  msgctxt "a positive response"
394
  msgid "Right on"
395
  msgstr ""
396
 
397
+ #: includes/class-freemius.php:20057
398
  msgid "seems like the key you entered doesn't match our records."
399
  msgstr ""
400
 
401
+ #: includes/class-freemius.php:20081
402
  msgid "Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the \"Stop Debug\" link."
403
  msgstr ""
404
 
405
+ #: includes/class-freemius.php:20316
406
  msgid "Your %s Add-on plan was successfully upgraded."
407
  msgstr ""
408
 
409
+ #: includes/class-freemius.php:20318
410
  msgid "%s Add-on was successfully purchased."
411
  msgstr ""
412
 
413
+ #: includes/class-freemius.php:20321
414
  msgid "Download the latest version"
415
  msgstr ""
416
 
417
+ #: includes/class-freemius.php:20407
418
  msgid "Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$s"
419
  msgstr ""
420
 
421
+ #: includes/class-freemius.php:20413, includes/class-freemius.php:20423, includes/class-freemius.php:20889, includes/class-freemius.php:20978
422
  msgid "Error received from the server:"
423
  msgstr ""
424
 
425
+ #: includes/class-freemius.php:20423
426
  msgid "It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again."
427
  msgstr ""
428
 
429
+ #: includes/class-freemius.php:20651, includes/class-freemius.php:20894, includes/class-freemius.php:20949, includes/class-freemius.php:21056
430
  msgctxt "something somebody says when they are thinking about what you have just said."
431
  msgid "Hmm"
432
  msgstr ""
433
 
434
+ #: includes/class-freemius.php:20664
435
  msgid "It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry."
436
  msgstr ""
437
 
438
+ #: includes/class-freemius.php:20665, templates/account.php:123, templates/add-ons.php:250, templates/account/partials/addon.php:46
439
  msgctxt "trial period"
440
  msgid "Trial"
441
  msgstr ""
442
 
443
+ #: includes/class-freemius.php:20670
444
  msgid "I have upgraded my account but when I try to Sync the License, the plan remains %s."
445
  msgstr ""
446
 
447
+ #: includes/class-freemius.php:20674, includes/class-freemius.php:20733
448
  msgid "Please contact us here"
449
  msgstr ""
450
 
451
+ #: includes/class-freemius.php:20685
452
  msgid "Your plan was successfully activated."
453
  msgstr ""
454
 
455
+ #: includes/class-freemius.php:20686
456
  msgid "Your plan was successfully upgraded."
457
  msgstr ""
458
 
459
+ #: includes/class-freemius.php:20703
460
  msgid "Your plan was successfully changed to %s."
461
  msgstr ""
462
 
463
+ #: includes/class-freemius.php:20719
464
  msgid "Your license has expired. You can still continue using the free %s forever."
465
  msgstr ""
466
 
467
+ #: includes/class-freemius.php:20721
468
  msgid "Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
469
  msgstr ""
470
 
471
+ #: includes/class-freemius.php:20729
472
  msgid "Your license has been cancelled. If you think it's a mistake, please contact support."
473
  msgstr ""
474
 
475
+ #: includes/class-freemius.php:20742
476
  msgid "Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support."
477
  msgstr ""
478
 
479
+ #: includes/class-freemius.php:20768
480
  msgid "Your free trial has expired. You can still continue using all our free features."
481
  msgstr ""
482
 
483
+ #: includes/class-freemius.php:20770
484
  msgid "Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
485
  msgstr ""
486
 
487
+ #: includes/class-freemius.php:20885
488
  msgid "It looks like the license could not be activated."
489
  msgstr ""
490
 
491
+ #: includes/class-freemius.php:20927
492
  msgid "Your license was successfully activated."
493
  msgstr ""
494
 
495
+ #: includes/class-freemius.php:20953
496
  msgid "It looks like your site currently doesn't have an active license."
497
  msgstr ""
498
 
499
+ #: includes/class-freemius.php:20977
500
  msgid "It looks like the license deactivation failed."
501
  msgstr ""
502
 
503
+ #: includes/class-freemius.php:21006
504
  msgid "Your %s license was successfully deactivated."
505
  msgstr ""
506
 
507
+ #: includes/class-freemius.php:21007
508
  msgid "Your license was successfully deactivated, you are back to the %s plan."
509
  msgstr ""
510
 
511
+ #: includes/class-freemius.php:21010
512
  msgid "O.K"
513
  msgstr ""
514
 
515
+ #: includes/class-freemius.php:21063
516
  msgid "Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes."
517
  msgstr ""
518
 
519
+ #: includes/class-freemius.php:21072
520
  msgid "Your subscription was successfully cancelled. Your %s plan license will expire in %s."
521
  msgstr ""
522
 
523
+ #: includes/class-freemius.php:21114
524
  msgid "You are already running the %s in a trial mode."
525
  msgstr ""
526
 
527
+ #: includes/class-freemius.php:21125
528
  msgid "You already utilized a trial before."
529
  msgstr ""
530
 
531
+ #: includes/class-freemius.php:21139
532
  msgid "Plan %s do not exist, therefore, can't start a trial."
533
  msgstr ""
534
 
535
+ #: includes/class-freemius.php:21150
536
  msgid "Plan %s does not support a trial period."
537
  msgstr ""
538
 
539
+ #: includes/class-freemius.php:21161
540
  msgid "None of the %s's plans supports a trial period."
541
  msgstr ""
542
 
543
+ #: includes/class-freemius.php:21211
544
  msgid "It looks like you are not in trial mode anymore so there's nothing to cancel :)"
545
  msgstr ""
546
 
547
+ #: includes/class-freemius.php:21247
548
  msgid "Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes."
549
  msgstr ""
550
 
551
+ #: includes/class-freemius.php:21266
552
  msgid "Your %s free trial was successfully cancelled."
553
  msgstr ""
554
 
555
+ #: includes/class-freemius.php:21582
556
  msgid "Version %s was released."
557
  msgstr ""
558
 
559
+ #: includes/class-freemius.php:21582
560
  msgid "Please download %s."
561
  msgstr ""
562
 
563
+ #: includes/class-freemius.php:21589
564
  msgid "the latest %s version here"
565
  msgstr ""
566
 
567
+ #: includes/class-freemius.php:21594
568
  msgid "New"
569
  msgstr ""
570
 
571
+ #: includes/class-freemius.php:21599
572
  msgid "Seems like you got the latest release."
573
  msgstr ""
574
 
575
+ #: includes/class-freemius.php:21600
576
  msgid "You are all good!"
577
  msgstr ""
578
 
579
+ #: includes/class-freemius.php:21903
580
  msgid "Verification mail was just sent to %s. If you can't find it after 5 min, please check your spam box."
581
  msgstr ""
582
 
583
+ #: includes/class-freemius.php:22043
584
  msgid "Site successfully opted in."
585
  msgstr ""
586
 
587
+ #: includes/class-freemius.php:22044, includes/class-freemius.php:23050
588
  msgid "Awesome"
589
  msgstr ""
590
 
591
+ #: includes/class-freemius.php:22060, templates/forms/optout.php:41
592
  msgid "We appreciate your help in making the %s better by letting us track some usage data."
593
  msgstr ""
594
 
595
+ #: includes/class-freemius.php:22061
596
  msgid "Thank you!"
597
  msgstr ""
598
 
599
+ #: includes/class-freemius.php:22068
600
  msgid "We will no longer be sending any usage data of %s on %s to %s."
601
  msgstr ""
602
 
603
+ #: includes/class-freemius.php:22226
604
  msgid "Please check your mailbox, you should receive an email via %s to confirm the ownership change. From security reasons, you must confirm the change within the next 15 min. If you cannot find the email, please check your spam folder."
605
  msgstr ""
606
 
607
+ #: includes/class-freemius.php:22232
608
  msgid "Thanks for confirming the ownership change. An email was just sent to %s for final approval."
609
  msgstr ""
610
 
611
+ #: includes/class-freemius.php:22237
612
  msgid "%s is the new owner of the account."
613
  msgstr ""
614
 
615
+ #: includes/class-freemius.php:22239
616
  msgctxt "as congratulations"
617
  msgid "Congrats"
618
  msgstr ""
619
 
620
+ #: includes/class-freemius.php:22275
621
  msgid "Your email was successfully updated. You should receive an email with confirmation instructions in few moments."
622
  msgstr ""
623
 
624
+ #: includes/class-freemius.php:22287
625
  msgid "Please provide your full name."
626
  msgstr ""
627
 
628
+ #: includes/class-freemius.php:22292
629
  msgid "Your name was successfully updated."
630
  msgstr ""
631
 
632
+ #: includes/class-freemius.php:22353
633
  msgid "You have successfully updated your %s."
634
  msgstr ""
635
 
636
+ #: includes/class-freemius.php:22412
637
  msgid "Is this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin."
638
  msgstr ""
639
 
640
+ #: includes/class-freemius.php:22415
641
  msgid "Click here"
642
  msgstr ""
643
 
644
+ #: includes/class-freemius.php:22513
645
  msgid "Just letting you know that the add-ons information of %s is being pulled from an external server."
646
  msgstr ""
647
 
648
+ #: includes/class-freemius.php:22514
649
  msgctxt "advance notice of something that will need attention."
650
  msgid "Heads up"
651
  msgstr ""
652
 
653
+ #: includes/class-freemius.php:23090
654
  msgctxt "exclamation"
655
  msgid "Hey"
656
  msgstr ""
657
 
658
+ #: includes/class-freemius.php:23090
659
  msgid "How do you like %s so far? Test all our %s premium features with a %d-day free trial."
660
  msgstr ""
661
 
662
+ #: includes/class-freemius.php:23098
663
  msgid "No commitment for %s days - cancel anytime!"
664
  msgstr ""
665
 
666
+ #: includes/class-freemius.php:23099
667
  msgid "No credit card required"
668
  msgstr ""
669
 
670
+ #: includes/class-freemius.php:23106, templates/forms/trial-start.php:53
671
  msgctxt "call to action"
672
  msgid "Start free trial"
673
  msgstr ""
674
 
675
+ #: includes/class-freemius.php:23183
676
  msgid "Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!"
677
  msgstr ""
678
 
679
+ #: includes/class-freemius.php:23192
680
  msgid "Learn more"
681
  msgstr ""
682
 
683
+ #: includes/class-freemius.php:23378, templates/account.php:558, templates/account.php:708, templates/connect.php:179, templates/connect.php:461, templates/forms/license-activation.php:27, templates/account/partials/addon.php:321
684
  msgid "Activate License"
685
  msgstr ""
686
 
687
+ #: includes/class-freemius.php:23379, templates/account.php:652, templates/account.php:707, templates/account/partials/addon.php:322, templates/account/partials/site.php:271
688
  msgid "Change License"
689
  msgstr ""
690
 
691
+ #: includes/class-freemius.php:23500, templates/account/partials/site.php:169
692
  msgid "Opt Out"
693
  msgstr ""
694
 
695
+ #: includes/class-freemius.php:23502, includes/class-freemius.php:23508, templates/account/partials/site.php:49, templates/account/partials/site.php:169
696
  msgid "Opt In"
697
  msgstr ""
698
 
699
+ #: includes/class-freemius.php:23738
700
  msgid " The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"
701
  msgstr ""
702
 
703
+ #: includes/class-freemius.php:23746
704
  msgid "Activate %s features"
705
  msgstr ""
706
 
707
+ #: includes/class-freemius.php:23759
708
  msgid "Please follow these steps to complete the upgrade"
709
  msgstr ""
710
 
711
+ #: includes/class-freemius.php:23763
712
  msgid "Download the latest %s version"
713
  msgstr ""
714
 
715
+ #: includes/class-freemius.php:23767
716
  msgid "Upload and activate the downloaded version"
717
  msgstr ""
718
 
719
+ #: includes/class-freemius.php:23769
720
  msgid "How to upload and activate?"
721
  msgstr ""
722
 
723
+ #: includes/class-freemius.php:23903
724
  msgid "%sClick here%s to choose the sites where you'd like to activate the license on."
725
  msgstr ""
726
 
727
+ #: includes/class-freemius.php:24072
728
  msgid "Auto installation only works for opted-in users."
729
  msgstr ""
730
 
731
+ #: includes/class-freemius.php:24082, includes/class-freemius.php:24115, includes/class-fs-plugin-updater.php:1261, includes/class-fs-plugin-updater.php:1275
732
  msgid "Invalid module ID."
733
  msgstr ""
734
 
735
+ #: includes/class-freemius.php:24091, includes/class-fs-plugin-updater.php:1297
736
  msgid "Premium version already active."
737
  msgstr ""
738
 
739
+ #: includes/class-freemius.php:24098
740
  msgid "You do not have a valid license to access the premium version."
741
  msgstr ""
742
 
743
+ #: includes/class-freemius.php:24105
744
  msgid "Plugin is a \"Serviceware\" which means it does not have a premium code version."
745
  msgstr ""
746
 
747
+ #: includes/class-freemius.php:24123, includes/class-fs-plugin-updater.php:1296
748
  msgid "Premium add-on version already installed."
749
  msgstr ""
750
 
751
+ #: includes/class-freemius.php:24473
752
  msgid "View paid features"
753
  msgstr ""
754
 
755
+ #: includes/class-freemius.php:24795
756
  msgid "Thank you so much for using %s and its add-ons!"
757
  msgstr ""
758
 
759
+ #: includes/class-freemius.php:24796
760
  msgid "Thank you so much for using %s!"
761
  msgstr ""
762
 
763
+ #: includes/class-freemius.php:24802
764
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving the %s."
765
  msgstr ""
766
 
767
+ #: includes/class-freemius.php:24806
768
  msgid "Thank you so much for using our products!"
769
  msgstr ""
770
 
771
+ #: includes/class-freemius.php:24807
772
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving them."
773
  msgstr ""
774
 
775
+ #: includes/class-freemius.php:24826
776
  msgid "%s and its add-ons"
777
  msgstr ""
778
 
779
+ #: includes/class-freemius.php:24835
780
  msgid "Products"
781
  msgstr ""
782
 
783
+ #: includes/class-freemius.php:24842, templates/connect.php:275
784
  msgid "Yes"
785
  msgstr ""
786
 
787
+ #: includes/class-freemius.php:24843, templates/connect.php:276
788
  msgid "send me security & feature updates, educational content and offers."
789
  msgstr ""
790
 
791
+ #: includes/class-freemius.php:24844, templates/connect.php:281
792
  msgid "No"
793
  msgstr ""
794
 
795
+ #: includes/class-freemius.php:24846, templates/connect.php:283
796
  msgid "do %sNOT%s send me security & feature updates, educational content and offers."
797
  msgstr ""
798
 
799
+ #: includes/class-freemius.php:24856
800
  msgid "Due to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)"
801
  msgstr ""
802
 
803
+ #: includes/class-freemius.php:24858, templates/connect.php:290
804
  msgid "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:"
805
  msgstr ""
806
 
807
+ #: includes/class-freemius.php:25140
808
  msgid "License key is empty."
809
  msgstr ""
810
 
832
  msgid "Important Upgrade Notice:"
833
  msgstr ""
834
 
835
+ #: includes/class-fs-plugin-updater.php:1326
836
  msgid "Installing plugin: %s"
837
  msgstr ""
838
 
839
+ #: includes/class-fs-plugin-updater.php:1367
840
  msgid "Unable to connect to the filesystem. Please confirm your credentials."
841
  msgstr ""
842
 
843
+ #: includes/class-fs-plugin-updater.php:1549
844
  msgid "The remote plugin package does not contain a folder with the desired slug and renaming did not work."
845
  msgstr ""
846
 
861
  msgid "Install Free Version Update Now"
862
  msgstr ""
863
 
864
+ #: includes/fs-plugin-info-dialog.php:745, templates/account.php:641
865
  msgid "Install Update Now"
866
  msgstr ""
867
 
878
  msgid "Download Latest Free Version"
879
  msgstr ""
880
 
881
+ #: includes/fs-plugin-info-dialog.php:772, templates/account.php:101, templates/add-ons.php:37, templates/account/partials/addon.php:25
882
  msgctxt "as download latest version"
883
  msgid "Download Latest"
884
  msgstr ""
887
  msgid "Activate this add-on"
888
  msgstr ""
889
 
890
+ #: includes/fs-plugin-info-dialog.php:789, templates/connect.php:458
891
  msgid "Activate Free Version"
892
  msgstr ""
893
 
894
+ #: includes/fs-plugin-info-dialog.php:790, templates/account.php:125, templates/add-ons.php:330, templates/account/partials/addon.php:48
895
  msgid "Activate"
896
  msgstr ""
897
 
1020
  msgid "Details"
1021
  msgstr ""
1022
 
1023
+ #: includes/fs-plugin-info-dialog.php:1318, templates/account.php:112, templates/debug.php:201, templates/debug.php:238, templates/debug.php:455, templates/account/partials/addon.php:36
1024
  msgctxt "product version"
1025
  msgid "Version"
1026
  msgstr ""
1034
  msgid "Last Updated"
1035
  msgstr ""
1036
 
1037
+ #: includes/fs-plugin-info-dialog.php:1337, templates/account.php:527
1038
  msgctxt "x-ago"
1039
  msgid "%s ago"
1040
  msgstr ""
1143
  msgid "Latest Free Version Installed"
1144
  msgstr ""
1145
 
1146
+ #: templates/account.php:102, templates/forms/subscription-cancellation.php:96, templates/account/partials/addon.php:26, templates/account/partials/site.php:311
1147
  msgid "Downgrading your plan"
1148
  msgstr ""
1149
 
1150
+ #: templates/account.php:103, templates/forms/subscription-cancellation.php:97, templates/account/partials/addon.php:27, templates/account/partials/site.php:312
1151
  msgid "Cancelling the subscription"
1152
  msgstr ""
1153
 
1154
  #. translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription'
1155
+ #: templates/account.php:105, templates/forms/subscription-cancellation.php:99, templates/account/partials/site.php:314
1156
  msgid "%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s."
1157
  msgstr ""
1158
 
1159
+ #: templates/account.php:106, templates/forms/subscription-cancellation.php:100, templates/account/partials/addon.php:30, templates/account/partials/site.php:315
1160
  msgid "Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price."
1161
  msgstr ""
1162
 
1163
+ #: templates/account.php:107, templates/forms/subscription-cancellation.php:106, templates/account/partials/addon.php:31
1164
  msgid "Cancelling the trial will immediately block access to all premium features. Are you sure?"
1165
  msgstr ""
1166
 
1167
+ #: templates/account.php:108, templates/forms/subscription-cancellation.php:101, templates/account/partials/addon.php:32, templates/account/partials/site.php:316
1168
  msgid "You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support."
1169
  msgstr ""
1170
 
1171
+ #: templates/account.php:109, templates/forms/subscription-cancellation.php:102, templates/account/partials/addon.php:33, templates/account/partials/site.php:317
1172
  msgid "Once your license expires you can still use the Free version but you will NOT have access to the %s features."
1173
  msgstr ""
1174
 
1175
  #. translators: %s: Plan title (e.g. "Professional")
1176
+ #: templates/account.php:111, templates/account/partials/activate-license-button.php:31, templates/account/partials/addon.php:35
1177
  msgid "Activate %s Plan"
1178
  msgstr ""
1179
 
1180
  #. translators: %s: Time period (e.g. Auto renews in "2 months")
1181
+ #: templates/account.php:114, templates/account/partials/addon.php:38, templates/account/partials/site.php:291
1182
  msgid "Auto renews in %s"
1183
  msgstr ""
1184
 
1185
  #. translators: %s: Time period (e.g. Expires in "2 months")
1186
+ #: templates/account.php:116, templates/account/partials/addon.php:40, templates/account/partials/site.php:293
1187
  msgid "Expires in %s"
1188
  msgstr ""
1189
 
1190
+ #: templates/account.php:117
1191
  msgctxt "as synchronize license"
1192
  msgid "Sync License"
1193
  msgstr ""
1194
 
1195
+ #: templates/account.php:118, templates/account/partials/addon.php:41
1196
  msgid "Cancel Trial"
1197
  msgstr ""
1198
 
1199
+ #: templates/account.php:119, templates/account/partials/addon.php:42
1200
  msgid "Change Plan"
1201
  msgstr ""
1202
 
1203
+ #: templates/account.php:120, templates/account/partials/addon.php:43
1204
  msgctxt "verb"
1205
  msgid "Upgrade"
1206
  msgstr ""
1207
 
1208
+ #: templates/account.php:122, templates/account/partials/addon.php:45, templates/account/partials/site.php:318
1209
  msgctxt "verb"
1210
  msgid "Downgrade"
1211
  msgstr ""
1212
 
1213
+ #: templates/account.php:124, templates/add-ons.php:246, templates/plugin-info/features.php:72, templates/account/partials/addon.php:47, templates/account/partials/site.php:33
1214
  msgid "Free"
1215
  msgstr ""
1216
 
1217
+ #: templates/account.php:126, templates/debug.php:371, includes/customizer/class-fs-customizer-upsell-control.php:110, templates/account/partials/addon.php:49
1218
  msgctxt "as product pricing plan"
1219
  msgid "Plan"
1220
  msgstr ""
1221
 
1222
+ #: templates/account.php:127
1223
  msgid "Bundle Plan"
1224
  msgstr ""
1225
 
1226
+ #: templates/account.php:250
1227
  msgid "Free Trial"
1228
  msgstr ""
1229
 
1230
+ #: templates/account.php:261
1231
  msgid "Account Details"
1232
  msgstr ""
1233
 
1234
+ #: templates/account.php:268, templates/forms/data-debug-mode.php:33
1235
  msgid "Start Debug"
1236
  msgstr ""
1237
 
1238
+ #: templates/account.php:270
1239
  msgid "Stop Debug"
1240
  msgstr ""
1241
 
1242
+ #: templates/account.php:277
1243
  msgid "Billing & Invoices"
1244
  msgstr ""
1245
 
1246
+ #: templates/account.php:288
1247
  msgid "Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the \"Cancel\" button, and first \"Downgrade\" your account. Are you sure you would like to continue with the deletion?"
1248
  msgstr ""
1249
 
1250
+ #: templates/account.php:290
1251
  msgid "Deletion is not temporary. Only delete if you no longer want to use this %s anymore. Are you sure you would like to continue with the deletion?"
1252
  msgstr ""
1253
 
1254
+ #: templates/account.php:293
1255
  msgid "Delete Account"
1256
  msgstr ""
1257
 
1258
+ #: templates/account.php:305, templates/account/partials/addon.php:231, templates/account/partials/deactivate-license-button.php:35
1259
  msgid "Deactivate License"
1260
  msgstr ""
1261
 
1262
+ #: templates/account.php:328, templates/forms/subscription-cancellation.php:125
1263
  msgid "Are you sure you want to proceed?"
1264
  msgstr ""
1265
 
1266
+ #: templates/account.php:328, templates/account/partials/addon.php:255
1267
  msgid "Cancel Subscription"
1268
  msgstr ""
1269
 
1270
+ #: templates/account.php:357, templates/account/partials/addon.php:340
1271
  msgctxt "as synchronize"
1272
  msgid "Sync"
1273
  msgstr ""
1274
 
1275
+ #: templates/account.php:372, templates/debug.php:505
1276
  msgid "Name"
1277
  msgstr ""
1278
 
1279
+ #: templates/account.php:378, templates/debug.php:506
1280
  msgid "Email"
1281
  msgstr ""
1282
 
1283
+ #: templates/account.php:385, templates/debug.php:369, templates/debug.php:555
1284
  msgid "User ID"
1285
  msgstr ""
1286
 
1287
+ #: templates/account.php:403, templates/account.php:721, templates/account.php:754, templates/debug.php:236, templates/debug.php:363, templates/debug.php:452, templates/debug.php:504, templates/debug.php:553, templates/debug.php:632, templates/account/payments.php:35, templates/debug/logger.php:21
1288
  msgid "ID"
1289
  msgstr ""
1290
 
1291
+ #: templates/account.php:410
1292
  msgid "Site ID"
1293
  msgstr ""
1294
 
1295
+ #: templates/account.php:413
1296
  msgid "No ID"
1297
  msgstr ""
1298
 
1299
+ #: templates/account.php:418, templates/debug.php:243, templates/debug.php:372, templates/debug.php:456, templates/debug.php:508, templates/account/partials/site.php:227
1300
  msgid "Public Key"
1301
  msgstr ""
1302
 
1303
+ #: templates/account.php:424, templates/debug.php:373, templates/debug.php:457, templates/debug.php:509, templates/account/partials/site.php:239
1304
  msgid "Secret Key"
1305
  msgstr ""
1306
 
1307
+ #: templates/account.php:427
1308
  msgctxt "as secret encryption key missing"
1309
  msgid "No Secret"
1310
  msgstr ""
1311
 
1312
+ #: templates/account.php:454, templates/account/partials/site.php:120, templates/account/partials/site.php:122
1313
  msgid "Trial"
1314
  msgstr ""
1315
 
1316
+ #: templates/account.php:481, templates/debug.php:561, templates/account/partials/site.php:260
1317
  msgid "License Key"
1318
  msgstr ""
1319
 
1320
+ #: templates/account.php:512
1321
  msgid "Join the Beta program"
1322
  msgstr ""
1323
 
1324
+ #: templates/account.php:518
1325
  msgid "not verified"
1326
  msgstr ""
1327
 
1328
+ #: templates/account.php:527, templates/account/partials/addon.php:190
1329
  msgid "Expired"
1330
  msgstr ""
1331
 
1332
+ #: templates/account.php:587
1333
  msgid "Premium version"
1334
  msgstr ""
1335
 
1336
+ #: templates/account.php:589
1337
  msgid "Free version"
1338
  msgstr ""
1339
 
1340
+ #: templates/account.php:601
1341
  msgid "Verify Email"
1342
  msgstr ""
1343
 
1344
+ #: templates/account.php:615
1345
  msgid "Download %s Version"
1346
  msgstr ""
1347
 
1348
+ #: templates/account.php:631
1349
  msgid "Download Paid Version"
1350
  msgstr ""
1351
 
1352
+ #: templates/account.php:649, templates/account.php:892, templates/account/partials/site.php:248, templates/account/partials/site.php:270
1353
  msgctxt "verb"
1354
  msgid "Show"
1355
  msgstr ""
1356
 
1357
+ #: templates/account.php:664
1358
  msgid "What is your %s?"
1359
  msgstr ""
1360
 
1361
+ #: templates/account.php:672, templates/account/billing.php:21
1362
  msgctxt "verb"
1363
  msgid "Edit"
1364
  msgstr ""
1365
 
1366
+ #: templates/account.php:676, templates/forms/user-change.php:27
1367
  msgid "Change User"
1368
  msgstr ""
1369
 
1370
+ #: templates/account.php:700
1371
  msgid "Sites"
1372
  msgstr ""
1373
 
1374
+ #: templates/account.php:713
1375
  msgid "Search by address"
1376
  msgstr ""
1377
 
1378
+ #: templates/account.php:722, templates/debug.php:366
1379
  msgid "Address"
1380
  msgstr ""
1381
 
1382
+ #: templates/account.php:723
1383
  msgid "License"
1384
  msgstr ""
1385
 
1386
+ #: templates/account.php:724
1387
  msgid "Plan"
1388
  msgstr ""
1389
 
1390
+ #: templates/account.php:757
1391
  msgctxt "as software license"
1392
  msgid "License"
1393
  msgstr ""
1394
 
1395
+ #: templates/account.php:886
1396
  msgctxt "verb"
1397
  msgid "Hide"
1398
  msgstr ""
1399
 
1400
+ #: templates/account.php:908, templates/forms/data-debug-mode.php:31
1401
  msgid "Processing"
1402
  msgstr ""
1403
 
1404
+ #: templates/account.php:911
1405
  msgid "Get updates for bleeding edge Beta versions of %s."
1406
  msgstr ""
1407
 
1408
+ #: templates/account.php:969
1409
  msgid "Cancelling %s"
1410
  msgstr ""
1411
 
1412
+ #: templates/account.php:969, templates/account.php:986, templates/forms/subscription-cancellation.php:27, templates/forms/deactivation/form.php:133
1413
  msgid "trial"
1414
  msgstr ""
1415
 
1416
+ #: templates/account.php:984, templates/forms/deactivation/form.php:150
1417
  msgid "Cancelling %s..."
1418
  msgstr ""
1419
 
1420
+ #: templates/account.php:987, templates/forms/subscription-cancellation.php:28, templates/forms/deactivation/form.php:134
1421
  msgid "subscription"
1422
  msgstr ""
1423
 
1424
+ #: templates/account.php:1001
1425
  msgid "Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?"
1426
  msgstr ""
1427
 
1428
+ #: templates/account.php:1075
1429
  msgid "Disabling white-label mode"
1430
  msgstr ""
1431
 
1432
+ #: templates/account.php:1076
1433
  msgid "Enabling white-label mode"
1434
  msgstr ""
1435
 
1455
  msgid "Installed"
1456
  msgstr ""
1457
 
1458
+ #: templates/admin-notice.php:13, templates/forms/license-activation.php:222, templates/forms/resend-key.php:77
1459
  msgctxt "as close a window"
1460
  msgid "Dismiss"
1461
  msgstr ""
1510
  msgid "Agree & Activate License"
1511
  msgstr ""
1512
 
1513
+ #: templates/connect.php:184
1514
+ msgid "Welcome to %s! To get started, please enter your license key:"
1515
  msgstr ""
1516
 
1517
+ #: templates/connect.php:191
1518
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s."
1519
  msgstr ""
1520
 
1521
+ #: templates/connect.php:192
1522
  msgid "Never miss an important update - opt in to our security and feature updates notifications, and non-sensitive diagnostic tracking with %4$s."
1523
  msgstr ""
1524
 
1525
+ #: templates/connect.php:198
1526
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1527
  msgstr ""
1528
 
1529
+ #: templates/connect.php:199
1530
  msgid "Never miss an important update - opt in to our security & feature updates notifications, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1531
  msgstr ""
1532
 
1533
+ #: templates/connect.php:233
1534
  msgid "We're excited to introduce the Freemius network-level integration."
1535
  msgstr ""
1536
 
1537
+ #: templates/connect.php:236
1538
  msgid "During the update process we detected %d site(s) that are still pending license activation."
1539
  msgstr ""
1540
 
1541
+ #: templates/connect.php:238
1542
  msgid "If you'd like to use the %s on those sites, please enter your license key below and click the activation button."
1543
  msgstr ""
1544
 
1545
+ #: templates/connect.php:240
1546
  msgid "%s's paid features"
1547
  msgstr ""
1548
 
1549
+ #: templates/connect.php:245
1550
  msgid "Alternatively, you can skip it for now and activate the license later, in your %s's network-level Account page."
1551
  msgstr ""
1552
 
1553
+ #: templates/connect.php:247
1554
  msgid "During the update process we detected %s site(s) in the network that are still pending your attention."
1555
  msgstr ""
1556
 
1557
+ #: templates/connect.php:256, templates/forms/data-debug-mode.php:35, templates/forms/license-activation.php:49
1558
  msgid "License key"
1559
  msgstr ""
1560
 
1561
+ #: templates/connect.php:259, templates/forms/license-activation.php:22
1562
  msgid "Can't find your license key?"
1563
  msgstr ""
1564
 
1565
+ #: templates/connect.php:318, templates/connect.php:700, templates/forms/deactivation/retry-skip.php:20
1566
  msgctxt "verb"
1567
  msgid "Skip"
1568
  msgstr ""
1569
 
1570
+ #: templates/connect.php:321
1571
  msgid "Delegate to Site Admins"
1572
  msgstr ""
1573
 
1574
+ #: templates/connect.php:321
1575
  msgid "If you click it, this decision will be delegated to the sites administrators."
1576
  msgstr ""
1577
 
1578
+ #: templates/connect.php:346
1579
+ msgid "License issues?"
1580
+ msgstr ""
1581
+
1582
+ #: templates/connect.php:362
1583
  msgid "Your Profile Overview"
1584
  msgstr ""
1585
 
1586
+ #: templates/connect.php:363
1587
  msgid "Name and email address"
1588
  msgstr ""
1589
 
1590
+ #: templates/connect.php:370
1591
+ msgid "So you can manage and control your license remotely from the User Dashboard."
1592
+ msgstr ""
1593
+
1594
+ #: templates/connect.php:371
1595
  msgid "Your Site Overview"
1596
  msgstr ""
1597
 
1598
+ #: templates/connect.php:372
1599
  msgid "Site URL, WP version, PHP info"
1600
  msgstr ""
1601
 
1603
  msgid "Admin Notices"
1604
  msgstr ""
1605
 
1606
+ #: templates/connect.php:380, templates/connect.php:398
1607
  msgid "Updates, announcements, marketing, no spam"
1608
  msgstr ""
1609
 
1610
+ #: templates/connect.php:387
1611
+ msgid "So you can reuse the license when the %s is no longer active."
1612
+ msgstr ""
1613
+
1614
+ #: templates/connect.php:388
1615
+ msgid "Current %s Status"
1616
  msgstr ""
1617
 
1618
+ #: templates/connect.php:389
1619
+ msgid "Active, deactivated, or uninstalled"
1620
  msgstr ""
1621
 
1622
+ #: templates/connect.php:397
1623
  msgid "Newsletter"
1624
  msgstr ""
1625
 
1626
+ #: templates/connect.php:405
1627
  msgid "Plugins & Themes"
1628
  msgstr ""
1629
 
1630
+ #: templates/connect.php:405
1631
+ msgid "optional"
1632
+ msgstr ""
1633
+
1634
+ #: templates/connect.php:406
1635
+ msgid "To help us troubleshoot any potential issues that may arise from other plugin or theme conflicts."
1636
+ msgstr ""
1637
+
1638
+ #: templates/connect.php:407
1639
  msgid "Title, slug, version, and is active"
1640
  msgstr ""
1641
 
1642
+ #: templates/connect.php:424
1643
+ msgid "The %1$s will periodically send %2$s to %3$s for security & feature updates delivery, and license management."
1644
  msgstr ""
1645
 
1646
  #: templates/connect.php:426
1647
+ msgid "diagnostic data"
1648
+ msgstr ""
1649
+
1650
+ #: templates/connect.php:427
1651
+ msgid "Freemius is our licensing and software updates engine"
1652
+ msgstr ""
1653
+
1654
+ #: templates/connect.php:430
1655
  msgid "What permissions are being granted?"
1656
  msgstr ""
1657
 
1658
+ #: templates/connect.php:457
1659
  msgid "Don't have a license key?"
1660
  msgstr ""
1661
 
1662
+ #: templates/connect.php:460
1663
  msgid "Have a license key?"
1664
  msgstr ""
1665
 
1666
+ #: templates/connect.php:468
1667
  msgid "Privacy Policy"
1668
  msgstr ""
1669
 
1670
+ #: templates/connect.php:470
1671
  msgid "License Agreement"
1672
  msgstr ""
1673
 
1674
+ #: templates/connect.php:470
1675
  msgid "Terms of Service"
1676
  msgstr ""
1677
 
1678
+ #: templates/connect.php:866
1679
  msgctxt "as in the process of sending an email"
1680
  msgid "Sending email"
1681
  msgstr ""
1682
 
1683
+ #: templates/connect.php:867
1684
  msgctxt "as activating plugin"
1685
  msgid "Activating"
1686
  msgstr ""
2269
  msgid "Update License"
2270
  msgstr ""
2271
 
2272
+ #: templates/forms/license-activation.php:41
2273
+ msgid "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."
2274
+ msgstr ""
2275
+
2276
+ #: templates/forms/license-activation.php:183
2277
  msgid "Associate with the license owner's account."
2278
  msgstr ""
2279
 
freemius/require.php CHANGED
@@ -6,6 +6,10 @@
6
  * @since 1.1.9
7
  */
8
 
 
 
 
 
9
  // Configuration should be loaded first.
10
  require_once dirname( __FILE__ ) . '/config.php';
11
  require_once WP_FS__DIR_INCLUDES . '/fs-core-functions.php';
@@ -46,4 +50,4 @@
46
  require_once WP_FS__DIR_INCLUDES . '/class-fs-admin-notices.php';
47
  require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php';
48
  require_once WP_FS__DIR_INCLUDES . '/sdk/Exceptions/Exception.php';
49
- require_once WP_FS__DIR_INCLUDES . '/class-freemius.php';
6
  * @since 1.1.9
7
  */
8
 
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
  // Configuration should be loaded first.
14
  require_once dirname( __FILE__ ) . '/config.php';
15
  require_once WP_FS__DIR_INCLUDES . '/fs-core-functions.php';
50
  require_once WP_FS__DIR_INCLUDES . '/class-fs-admin-notices.php';
51
  require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php';
52
  require_once WP_FS__DIR_INCLUDES . '/sdk/Exceptions/Exception.php';
53
+ require_once WP_FS__DIR_INCLUDES . '/class-freemius.php';
freemius/start.php CHANGED
@@ -15,7 +15,7 @@
15
  *
16
  * @var string
17
  */
18
- $this_sdk_version = '2.4.1';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
@@ -512,7 +512,7 @@
512
  }
513
 
514
  /**
515
- * @param array <string,string> $module Plugin or Theme details.
516
  *
517
  * @return Freemius
518
  * @throws Freemius_Exception
@@ -527,4 +527,4 @@
527
  function fs_dump_log() {
528
  FS_Logger::dump();
529
  }
530
- }
15
  *
16
  * @var string
17
  */
18
+ $this_sdk_version = '2.4.3';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
512
  }
513
 
514
  /**
515
+ * @param array <string,string|bool|array> $module Plugin or Theme details.
516
  *
517
  * @return Freemius
518
  * @throws Freemius_Exception
527
  function fs_dump_log() {
528
  FS_Logger::dump();
529
  }
530
+ }
freemius/templates/account.php CHANGED
@@ -21,7 +21,9 @@
21
  /**
22
  * @var FS_Plugin_Tag $update
23
  */
24
- $update = $fs->get_update( false, false, WP_FS__TIME_24_HOURS_IN_SEC / 24 );
 
 
25
 
26
  if ( is_object($update) ) {
27
  /**
@@ -433,11 +435,11 @@
433
  'value' => $fs->get_plugin_version()
434
  );
435
 
436
- if ( $is_premium && ! $is_whitelabeled ) {
437
  $profile[] = array(
438
  'id' => 'beta_program',
439
  'title' => '',
440
- 'value' => $user->is_beta
441
  );
442
  }
443
 
21
  /**
22
  * @var FS_Plugin_Tag $update
23
  */
24
+ $update = $fs->has_release_on_freemius() ?
25
+ $fs->get_update( false, false, WP_FS__TIME_24_HOURS_IN_SEC / 24 ) :
26
+ null;
27
 
28
  if ( is_object($update) ) {
29
  /**
435
  'value' => $fs->get_plugin_version()
436
  );
437
 
438
+ if ( ! fs_is_network_admin() && $is_premium && ! $is_whitelabeled ) {
439
  $profile[] = array(
440
  'id' => 'beta_program',
441
  'title' => '',
442
+ 'value' => $site->is_beta
443
  );
444
  }
445
 
freemius/templates/account/partials/addon.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
  /**
3
  * @var array $VARS
4
  * @var Freemius $fs
@@ -443,4 +448,4 @@
443
  </td>
444
  <!--/ Optional Delete Action -->
445
  <?php endif ?>
446
- </tr>
1
  <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
  /**
8
  * @var array $VARS
9
  * @var Freemius $fs
448
  </td>
449
  <!--/ Optional Delete Action -->
450
  <?php endif ?>
451
+ </tr>
freemius/templates/ajax-loader.php CHANGED
@@ -1 +1,6 @@
1
- <div class="fs-ajax-loader" style="display: none"><?php for ( $i = 1; $i <= 8; $i ++ ) : ?><div class="fs-ajax-loader-bar fs-ajax-loader-bar-<?php echo $i ?>"></div><?php endfor ?></div>
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+ ?>
6
+ <div class="fs-ajax-loader" style="display: none"><?php for ( $i = 1; $i <= 8; $i ++ ) : ?><div class="fs-ajax-loader-bar fs-ajax-loader-bar-<?php echo $i ?>"></div><?php endfor ?></div>
freemius/templates/connect.php CHANGED
@@ -1,1026 +1,1038 @@
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.0.7
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- * @var Freemius $fs
16
- */
17
- $fs = freemius( $VARS['id'] );
18
- $slug = $fs->get_slug();
19
-
20
- $is_pending_activation = $fs->is_pending_activation();
21
- $is_premium_only = $fs->is_only_premium();
22
- $has_paid_plans = $fs->has_paid_plan();
23
- $is_premium_code = $fs->is_premium();
24
- $is_freemium = $fs->is_freemium();
25
-
26
- $fs->_enqueue_connect_essentials();
27
-
28
- $current_user = Freemius::_get_current_wp_user();
29
-
30
- $first_name = $current_user->user_firstname;
31
- if ( empty( $first_name ) ) {
32
- $first_name = $current_user->nickname;
33
- }
34
-
35
- $site_url = get_site_url();
36
- $protocol_pos = strpos( $site_url, '://' );
37
- if ( false !== $protocol_pos ) {
38
- $site_url = substr( $site_url, $protocol_pos + 3 );
39
- }
40
-
41
- $freemius_site_www = 'https://freemius.com';
42
-
43
- $freemius_usage_tracking_url = $fs->get_usage_tracking_terms_url();
44
- $freemius_plugin_terms_url = $fs->get_eula_url();
45
-
46
- $freemius_site_url = $fs->is_premium() ?
47
- $freemius_site_www :
48
- $freemius_usage_tracking_url;
49
-
50
- if ( $fs->is_premium() ) {
51
- $freemius_site_url .= '?' . http_build_query( array(
52
- 'id' => $fs->get_id(),
53
- 'slug' => $slug,
54
- ) );
55
- }
56
-
57
- $freemius_link = '<a href="' . $freemius_site_url . '" target="_blank" rel="noopener" tabindex="1">freemius.com</a>';
58
-
59
- $error = fs_request_get( 'error' );
60
-
61
- $require_license_key = $is_premium_only ||
62
- ( $is_freemium && $is_premium_code && fs_request_get_bool( 'require_license', true ) );
63
-
64
- if ( $is_pending_activation ) {
65
- $require_license_key = false;
66
- }
67
-
68
- if ( $require_license_key ) {
69
- $fs->_add_license_activation_dialog_box();
70
- }
71
-
72
- $is_optin_dialog = (
73
- $fs->is_theme() &&
74
- $fs->is_themes_page() &&
75
- $fs->show_opt_in_on_themes_page()
76
- );
77
-
78
- if ( $is_optin_dialog ) {
79
- $show_close_button = false;
80
- $previous_theme_activation_url = '';
81
-
82
- if ( ! $is_premium_code ) {
83
- $show_close_button = true;
84
- } else if ( $is_premium_only ) {
85
- $previous_theme_activation_url = $fs->get_previous_theme_activation_url();
86
- $show_close_button = ( ! empty( $previous_theme_activation_url ) );
87
- }
88
- }
89
-
90
- $is_network_level_activation = (
91
- fs_is_network_admin() &&
92
- $fs->is_network_active() &&
93
- ! $fs->is_network_delegated_connection()
94
- );
95
-
96
- $fs_user = Freemius::_get_user_by_email( $current_user->user_email );
97
-
98
- $activate_with_current_user = (
99
- is_object( $fs_user ) &&
100
- ! $is_pending_activation &&
101
- // If requires a license for activation, use the user associated with the license for the opt-in.
102
- ! $require_license_key &&
103
- ! $is_network_level_activation
104
- );
105
-
106
- $optin_params = $fs->get_opt_in_params( array(), $is_network_level_activation );
107
- $sites = isset( $optin_params['sites'] ) ? $optin_params['sites'] : array();
108
-
109
- $is_network_upgrade_mode = ( fs_is_network_admin() && $fs->is_network_upgrade_mode() );
110
-
111
- /* translators: %s: name (e.g. Hey John,) */
112
- $hey_x_text = esc_html( sprintf( fs_text_x_inline( 'Hey %s,', 'greeting', 'hey-x', $slug ), $first_name ) );
113
-
114
- $is_gdpr_required = ( ! $is_pending_activation && ! $require_license_key ) ?
115
- FS_GDPR_Manager::instance()->is_required() :
116
- false;
117
-
118
- if ( is_null( $is_gdpr_required ) ) {
119
- $is_gdpr_required = $fs->fetch_and_store_current_user_gdpr_anonymously();
120
- }
121
- ?>
122
- <?php
123
- if ( $is_optin_dialog ) { ?>
124
- <div id="fs_theme_connect_wrapper">
125
- <?php
126
- if ( $show_close_button ) { ?>
127
- <button class="close dashicons dashicons-no"><span class="screen-reader-text">Close connect dialog</span>
128
- </button>
129
- <?php
130
- }
131
- ?>
132
- <?php
133
- }
134
-
135
- /**
136
- * Allows developers to include custom HTML before the opt-in content.
137
- *
138
- * @author Vova Feldman
139
- * @since 2.3.2
140
- */
141
- $fs->do_action( 'connect/before' );
142
- ?>
143
- <div id="fs_connect"
144
- class="wrap<?php if ( ! fs_is_network_admin() && ( ! $fs->is_enable_anonymous() || $is_pending_activation || $require_license_key ) ) {
145
- echo ' fs-anonymous-disabled';
146
- } ?><?php echo $require_license_key ? ' require-license-key' : '' ?>">
147
- <div class="fs-visual">
148
- <b class="fs-site-icon"><i class="dashicons dashicons-wordpress"></i></b>
149
- <i class="dashicons dashicons-plus fs-first"></i>
150
- <?php
151
- $vars = array( 'id' => $fs->get_id() );
152
- fs_require_once_template( 'plugin-icon.php', $vars );
153
- ?>
154
- <i class="dashicons dashicons-plus fs-second"></i>
155
- <img class="fs-connect-logo" width="80" height="80" src="//img.freemius.com/connect-logo.png"/>
156
- </div>
157
- <div class="fs-content">
158
- <?php if ( ! empty( $error ) ) : ?>
159
- <p class="fs-error"><?php echo esc_html( $error ) ?></p>
160
- <?php endif ?>
161
- <p><?php
162
- $button_label = fs_text_inline( 'Allow & Continue', 'opt-in-connect', $slug );
163
- $message = '';
164
-
165
- if ( $is_pending_activation ) {
166
- $button_label = fs_text_inline( 'Re-send activation email', 'resend-activation-email', $slug );
167
-
168
- $message = $fs->apply_filters( 'pending_activation_message', sprintf(
169
- /* translators: %s: name (e.g. Thanks John!) */
170
- fs_text_inline( 'Thanks %s!', 'thanks-x', $slug ) . '<br>' .
171
- fs_text_inline( 'You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to %s.', 'pending-activation-message', $slug ),
172
- $first_name,
173
- '<b>' . $fs->get_plugin_name() . '</b>',
174
- '<b>' . $current_user->user_email . '</b>',
175
- fs_text_inline( 'complete the install', 'complete-the-install', $slug )
176
- ) );
177
- } else if ( $require_license_key ) {
178
- $button_label = $is_network_upgrade_mode ?
179
- fs_text_inline( 'Activate License', 'agree-activate-license', $slug ) :
180
- fs_text_inline( 'Agree & Activate License', 'agree-activate-license', $slug );
181
-
182
- $message = $fs->apply_filters(
183
- 'connect-message_on-premium',
184
- ($is_network_upgrade_mode ?
185
- '' :
186
- /* translators: %s: name (e.g. Hey John,) */
187
- $hey_x_text . '<br>'
188
- ) .
189
- sprintf( fs_text_inline( 'Thanks for purchasing %s! To get started, please enter your license key:', 'thanks-for-purchasing', $slug ), '<b>' . $fs->get_plugin_name() . '</b>' ),
190
- $first_name,
191
- $fs->get_plugin_name()
192
- );
193
- } else {
194
- $filter = 'connect_message';
195
- $default_optin_message = $is_gdpr_required ?
196
- fs_text_inline( 'Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s.', 'connect-message', $slug) :
197
- fs_text_inline( 'Never miss an important update - opt in to our security and feature updates notifications, and non-sensitive diagnostic tracking with %4$s.', 'connect-message', $slug);
198
-
199
- if ( $fs->is_plugin_update() ) {
200
- // If Freemius was added on a plugin update, set different
201
- // opt-in message.
202
- $default_optin_message = $is_gdpr_required ?
203
- fs_text_inline( 'Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s. If you skip this, that\'s okay! %1$s will still work just fine.', 'connect-message_on-update', $slug ) :
204
- fs_text_inline( 'Never miss an important update - opt in to our security & feature updates notifications, and non-sensitive diagnostic tracking with %4$s. If you skip this, that\'s okay! %1$s will still work just fine.', 'connect-message_on-update', $slug );
205
-
206
- // If user customized the opt-in message on update, use
207
- // that message. Otherwise, fallback to regular opt-in
208
- // custom message if exist.
209
- if ( $fs->has_filter( 'connect_message_on_update' ) ) {
210
- $filter = 'connect_message_on_update';
211
- }
212
- }
213
-
214
- $message = $fs->apply_filters(
215
- $filter,
216
- ($is_network_upgrade_mode ?
217
- '' :
218
- /* translators: %s: name (e.g. Hey John,) */
219
- $hey_x_text . '<br>'
220
- ) .
221
- sprintf(
222
- esc_html( $default_optin_message ),
223
- '<b>' . esc_html( $fs->get_plugin_name() ) . '</b>',
224
- '<b>' . $current_user->user_login . '</b>',
225
- '<a href="' . $site_url . '" target="_blank" rel="noopener noreferrer">' . $site_url . '</a>',
226
- $freemius_link
227
- ),
228
- $first_name,
229
- $fs->get_plugin_name(),
230
- $current_user->user_login,
231
- '<a href="' . $site_url . '" target="_blank" rel="noopener noreferrer">' . $site_url . '</a>',
232
- $freemius_link,
233
- $is_gdpr_required
234
- );
235
- }
236
-
237
- if ( $is_network_upgrade_mode ) {
238
- $network_integration_text = esc_html( fs_text_inline( 'We\'re excited to introduce the Freemius network-level integration.', 'connect_message_network_upgrade', $slug ) );
239
-
240
- if ($is_premium_code){
241
- $message = $network_integration_text . ' ' . sprintf( fs_text_inline( 'During the update process we detected %d site(s) that are still pending license activation.', 'connect_message_network_upgrade-premium', $slug ), count( $sites ) );
242
-
243
- $message .= '<br><br>' . sprintf( fs_text_inline( 'If you\'d like to use the %s on those sites, please enter your license key below and click the activation button.', 'connect_message_network_upgrade-premium-activate-license', $slug ), $is_premium_only ? $fs->get_module_label( true ) : sprintf(
244
- /* translators: %s: module type (plugin, theme, or add-on) */
245
- fs_text_inline( "%s's paid features", 'x-paid-features', $slug ),
246
- $fs->get_module_label( true )
247
- ) );
248
-
249
- /* translators: %s: module type (plugin, theme, or add-on) */
250
- $message .= ' ' . sprintf( fs_text_inline( 'Alternatively, you can skip it for now and activate the license later, in your %s\'s network-level Account page.', 'connect_message_network_upgrade-premium-skip-license', $slug ), $fs->get_module_label( true ) );
251
- }else {
252
- $message = $network_integration_text . ' ' . sprintf( fs_text_inline( 'During the update process we detected %s site(s) in the network that are still pending your attention.', 'connect_message_network_upgrade-free', $slug ), count( $sites ) ) . '<br><br>' . ( fs_starts_with( $message, $hey_x_text . '<br>' ) ? substr( $message, strlen( $hey_x_text . '<br>' ) ) : $message );
253
- }
254
- }
255
-
256
- echo $message;
257
- ?></p>
258
- <?php if ( $require_license_key ) : ?>
259
- <div class="fs-license-key-container">
260
- <input id="fs_license_key" name="fs_key" type="text" required maxlength="<?php echo $fs->apply_filters('license_key_maxlength', 32) ?>"
261
- placeholder="<?php fs_esc_attr_echo_inline( 'License key', 'license-key', $slug ) ?>" tabindex="1"/>
262
- <i class="dashicons dashicons-admin-network"></i>
263
- <a class="show-license-resend-modal show-license-resend-modal-<?php echo $fs->get_unique_affix() ?>"
264
- href="#"><?php fs_esc_html_echo_inline( "Can't find your license key?", 'cant-find-license-key', $slug ); ?></a>
265
- </div>
266
-
267
- <?php
268
- /**
269
- * Allows developers to include custom HTML after the license input container.
270
- *
271
- * @author Vova Feldman
272
- * @since 2.1.2
273
- */
274
- $fs->do_action( 'connect/after_license_input' );
275
- ?>
276
-
277
- <?php
278
- $send_updates_text = sprintf(
279
- '%s<span class="action-description"> - %s</span>',
280
- $fs->get_text_inline( 'Yes', 'yes' ),
281
- $fs->get_text_inline( 'send me security & feature updates, educational content and offers.', 'send-updates' )
282
- );
283
-
284
- $do_not_send_updates_text = sprintf(
285
- '%s<span class="action-description"> - %s</span>',
286
- $fs->get_text_inline( 'No', 'no' ),
287
- sprintf(
288
- $fs->get_text_inline( 'do %sNOT%s send me security & feature updates, educational content and offers.', 'do-not-send-updates' ),
289
- '<span class="underlined">',
290
- '</span>'
291
- )
292
- );
293
- ?>
294
- <div id="fs_marketing_optin">
295
- <span class="fs-message"><?php fs_echo_inline( "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:", 'contact-for-updates' ) ?></span>
296
- <div class="fs-input-container">
297
- <label>
298
- <input type="radio" name="allow-marketing" value="true" tabindex="1" />
299
- <span class="fs-input-label"><?php echo $send_updates_text ?></span>
300
- </label>
301
- <label>
302
- <input type="radio" name="allow-marketing" value="false" tabindex="1" />
303
- <span class="fs-input-label"><?php echo $do_not_send_updates_text ?></span>
304
- </label>
305
- </div>
306
- </div>
307
- <?php endif ?>
308
- <?php if ( $is_network_level_activation ) : ?>
309
- <?php
310
- $vars = array(
311
- 'id' => $fs->get_id(),
312
- 'sites' => $sites,
313
- 'require_license_key' => $require_license_key
314
- );
315
-
316
- echo fs_get_template( 'partials/network-activation.php', $vars );
317
- ?>
318
- <?php endif ?>
319
- </div>
320
- <div class="fs-actions">
321
- <?php if ( $fs->is_enable_anonymous() && ! $is_pending_activation && ( ! $require_license_key || $is_network_upgrade_mode ) ) : ?>
322
- <a id="skip_activation" href="<?php echo fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_skip_activation' ), $is_network_level_activation ), $fs->get_unique_affix() . '_skip_activation' ) ?>"
323
- class="button button-secondary" tabindex="2"><?php fs_esc_html_echo_x_inline( 'Skip', 'verb', 'skip', $slug ) ?></a>
324
- <?php endif ?>
325
- <?php if ( $is_network_level_activation && $fs->apply_filters( 'show_delegation_option', true ) ) : ?>
326
- <a id="delegate_to_site_admins" class="fs-tooltip-trigger <?php echo is_rtl() ? ' rtl' : '' ?>" href="<?php echo fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_delegate_activation' ) ), $fs->get_unique_affix() . '_delegate_activation' ) ?>"><?php fs_esc_html_echo_inline( 'Delegate to Site Admins', 'delegate-to-site-admins', $slug ) ?><span class="fs-tooltip"><?php fs_esc_html_echo_inline( 'If you click it, this decision will be delegated to the sites administrators.', 'delegate-sites-tooltip', $slug ) ?></span></a>
327
- <?php endif ?>
328
- <?php if ( $activate_with_current_user ) : ?>
329
- <form action="" method="POST">
330
- <input type="hidden" name="fs_action"
331
- value="<?php echo $fs->get_unique_affix() ?>_activate_existing">
332
- <?php wp_nonce_field( 'activate_existing_' . $fs->get_public_key() ) ?>
333
- <input type="hidden" name="is_extensions_tracking_allowed" value="1">
334
- <button class="button button-primary" tabindex="1"
335
- type="submit"><?php echo esc_html( $button_label ) ?></button>
336
- </form>
337
- <?php else : ?>
338
- <form method="post" action="<?php echo WP_FS__ADDRESS ?>/action/service/user/install/">
339
- <?php unset( $optin_params['sites']); ?>
340
- <?php foreach ( $optin_params as $name => $value ) : ?>
341
- <input type="hidden" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ) ?>">
342
- <?php endforeach ?>
343
- <input type="hidden" name="is_extensions_tracking_allowed" value="1">
344
- <button class="button button-primary" tabindex="1"
345
- type="submit"<?php if ( $require_license_key ) {
346
- echo ' disabled="disabled"';
347
- } ?>><?php echo esc_html( $button_label ) ?></button>
348
- </form>
349
- <?php endif ?>
350
- </div><?php
351
-
352
- // Set core permission list items.
353
- $permissions = array();
354
-
355
- /**
356
- * When activating a license key the information of the admin is not collected, we gather the user info from the license.
357
- *
358
- * @since 2.3.2
359
- * @author Vova Feldman
360
- */
361
- if ( ! $require_license_key ) {
362
- $permissions['profile'] = array(
363
- 'icon-class' => 'dashicons dashicons-admin-users',
364
- 'label' => $fs->get_text_inline( 'Your Profile Overview', 'permissions-profile' ),
365
- 'desc' => $fs->get_text_inline( 'Name and email address', 'permissions-profile_desc' ),
366
- 'priority' => 5,
367
- );
368
- }
369
-
370
- $permissions['site'] = array(
371
- 'icon-class' => 'dashicons dashicons-admin-settings',
372
- 'label' => $fs->get_text_inline( 'Your Site Overview', 'permissions-site' ),
373
- 'desc' => $fs->get_text_inline( 'Site URL, WP version, PHP info', 'permissions-site_desc' ),
374
- 'priority' => 10,
375
- );
376
-
377
- $permissions['notices'] = array(
378
- 'icon-class' => 'dashicons dashicons-testimonial',
379
- 'label' => $fs->get_text_inline( 'Admin Notices', 'permissions-admin-notices' ),
380
- 'desc' => $fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
381
- 'priority' => 13,
382
- );
383
-
384
- $permissions['events'] = array(
385
- 'icon-class' => 'dashicons dashicons-admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
386
- 'label' => sprintf( $fs->get_text_inline( 'Current %s Events', 'permissions-events' ), ucfirst( $fs->get_module_type() ) ),
387
- 'desc' => $fs->get_text_inline( 'Activation, deactivation and uninstall', 'permissions-events_desc' ),
388
- 'priority' => 20,
389
- );
390
-
391
- // Add newsletter permissions if enabled.
392
- if ( $is_gdpr_required || $fs->is_permission_requested( 'newsletter' ) ) {
393
- $permissions['newsletter'] = array(
394
- 'icon-class' => 'dashicons dashicons-email-alt',
395
- 'label' => $fs->get_text_inline( 'Newsletter', 'permissions-newsletter' ),
396
- 'desc' => $fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
397
- 'priority' => 15,
398
- );
399
- }
400
-
401
- $permissions['extensions'] = array(
402
- 'icon-class' => 'dashicons dashicons-menu',
403
- 'label' => $fs->get_text_inline( 'Plugins & Themes', 'permissions-extensions' ),
404
- 'desc' => $fs->get_text_inline( 'Title, slug, version, and is active', 'permissions-extensions_desc' ),
405
- 'priority' => 25,
406
- 'optional' => true,
407
- 'default' => $fs->apply_filters( 'permission_extensions_default', true )
408
- );
409
-
410
- // Allow filtering of the permissions list.
411
- $permissions = $fs->apply_filters( 'permission_list', $permissions );
412
-
413
- // Sort by priority.
414
- uasort( $permissions, 'fs_sort_by_priority' );
415
-
416
- if ( ! empty( $permissions ) ) : ?>
417
- <div class="fs-permissions">
418
- <?php if ( $require_license_key ) : ?>
419
- <p class="fs-license-sync-disclaimer"><?php
420
- echo sprintf(
421
- fs_esc_html_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 ),
422
- $fs->get_module_label( true ),
423
- $freemius_link
424
- ) ?></p>
425
- <?php endif ?>
426
- <a class="fs-trigger" href="#" tabindex="1"><?php fs_esc_html_echo_inline( 'What permissions are being granted?', 'what-permissions', $slug ) ?></a>
427
- <ul><?php
428
- foreach ( $permissions as $id => $permission ) : ?>
429
- <li id="fs-permission-<?php echo esc_attr( $id ); ?>"
430
- class="fs-permission fs-<?php echo esc_attr( $id ); ?>">
431
- <i class="<?php echo esc_attr( $permission['icon-class'] ); ?>"></i>
432
- <?php if ( isset( $permission['optional'] ) && true === $permission['optional'] ) : ?>
433
- <div class="fs-switch fs-small fs-round fs-<?php echo (! isset( $permission['default'] ) || true === $permission['default'] ) ? 'on' : 'off' ?>">
434
- <div class="fs-toggle"></div>
435
- </div>
436
- <?php endif ?>
437
-
438
- <div class="fs-permission-description">
439
- <span><?php echo esc_html( $permission['label'] ); ?></span>
440
-
441
- <p><?php echo esc_html( $permission['desc'] ); ?></p>
442
- </div>
443
- </li>
444
- <?php endforeach; ?>
445
- </ul>
446
- </div>
447
- <?php endif ?>
448
- <?php if ( $is_premium_code && $is_freemium ) : ?>
449
- <div class="fs-freemium-licensing">
450
- <p>
451
- <?php if ( $require_license_key ) : ?>
452
- <?php fs_esc_html_echo_inline( 'Don\'t have a license key?', 'dont-have-license-key', $slug ) ?>
453
- <a data-require-license="false" tabindex="1"><?php fs_esc_html_echo_inline( 'Activate Free Version', 'activate-free-version', $slug ) ?></a>
454
- <?php else : ?>
455
- <?php fs_echo_inline( 'Have a license key?', 'have-license-key', $slug ) ?>
456
- <a data-require-license="true" tabindex="1"><?php fs_esc_html_echo_inline( 'Activate License', 'activate-license', $slug ) ?></a>
457
- <?php endif ?>
458
- </p>
459
- </div>
460
- <?php endif ?>
461
- <div class="fs-terms">
462
- <a href="https://freemius.com/privacy/" target="_blank" rel="noopener"
463
- tabindex="1"><?php fs_esc_html_echo_inline( 'Privacy Policy', 'privacy-policy', $slug ) ?></a>
464
- &nbsp;&nbsp;-&nbsp;&nbsp;
465
- <a href="<?php echo $require_license_key ? $freemius_plugin_terms_url : $freemius_usage_tracking_url ?>" target="_blank" rel="noopener" tabindex="1"><?php $require_license_key ? fs_echo_inline( 'License Agreement', 'license-agreement', $slug ) : fs_echo_inline( 'Terms of Service', 'tos', $slug ) ?></a>
466
- </div>
467
- </div>
468
- <?php
469
- /**
470
- * Allows developers to include custom HTML after the opt-in content.
471
- *
472
- * @author Vova Feldman
473
- * @since 2.3.2
474
- */
475
- $fs->do_action( 'connect/after' );
476
-
477
- if ( $is_optin_dialog ) { ?>
478
- </div>
479
- <?php
480
- }
481
- ?>
482
- <script type="text/javascript">
483
- (function ($) {
484
- var $html = $('html');
485
-
486
- <?php
487
- if ( $is_optin_dialog ) {
488
- if ( $show_close_button ) { ?>
489
- var $themeConnectWrapper = $('#fs_theme_connect_wrapper');
490
-
491
- $themeConnectWrapper.find('button.close').on('click', function () {
492
- <?php if ( ! empty( $previous_theme_activation_url ) ) { ?>
493
- location.href = '<?php echo html_entity_decode( $previous_theme_activation_url ); ?>';
494
- <?php } else { ?>
495
- $themeConnectWrapper.remove();
496
- $html.css({overflow: $html.attr('fs-optin-overflow')});
497
- <?php } ?>
498
- });
499
- <?php
500
- }
501
- ?>
502
-
503
- $html.attr('fs-optin-overflow', $html.css('overflow'));
504
- $html.css({overflow: 'hidden'});
505
-
506
- <?php
507
- }
508
- ?>
509
-
510
- var $primaryCta = $('.fs-actions .button.button-primary'),
511
- primaryCtaLabel = $primaryCta.html(),
512
- $form = $('.fs-actions form'),
513
- isNetworkActive = <?php echo $is_network_level_activation ? 'true' : 'false' ?>,
514
- requireLicenseKey = <?php echo $require_license_key ? 'true' : 'false' ?>,
515
- hasContextUser = <?php echo $activate_with_current_user ? 'true' : 'false' ?>,
516
- isNetworkUpgradeMode = <?php echo $is_network_upgrade_mode ? 'true' : 'false' ?>,
517
- $licenseSecret,
518
- $licenseKeyInput = $('#fs_license_key'),
519
- pauseCtaLabelUpdate = false,
520
- isNetworkDelegating = false,
521
- /**
522
- * @author Leo Fajardo (@leorw)
523
- * @since 2.1.0
524
- */
525
- resetLoadingMode = function() {
526
- // Reset loading mode.
527
- $primaryCta.html(primaryCtaLabel);
528
- $primaryCta.prop('disabled', false);
529
- $(document.body).css({'cursor': 'auto'});
530
- $('.fs-loading').removeClass('fs-loading');
531
-
532
- console.log('resetLoadingMode - Primary button was enabled');
533
- },
534
- setLoadingMode = function () {
535
- $(document.body).css({'cursor': 'wait'});
536
- };
537
-
538
- $('.fs-actions .button').on('click', function () {
539
- setLoadingMode();
540
-
541
- var $this = $(this);
542
-
543
- setTimeout(function () {
544
- if ( ! requireLicenseKey || ! $marketingOptin.hasClass( 'error' ) ) {
545
- $this.attr('disabled', 'disabled');
546
- }
547
- }, 200);
548
- });
549
-
550
- if ( isNetworkActive ) {
551
- var
552
- $multisiteOptionsContainer = $( '.fs-multisite-options-container' ),
553
- $allSitesOptions = $( '.fs-all-sites-options' ),
554
- $applyOnAllSites = $( '.fs-apply-on-all-sites-checkbox' ),
555
- $sitesListContainer = $( '.fs-sites-list-container' ),
556
- totalSites = <?php echo count( $sites ) ?>,
557
- maxSitesListHeight = null,
558
- $skipActivationButton = $( '#skip_activation' ),
559
- $delegateToSiteAdminsButton = $( '#delegate_to_site_admins' ),
560
- hasAnyInstall = <?php echo ! is_null( $fs->find_first_install() ) ? 'true' : 'false' ?>;
561
-
562
- $applyOnAllSites.click(function() {
563
- var isChecked = $( this ).is( ':checked' );
564
-
565
- if ( isChecked ) {
566
- $multisiteOptionsContainer.find( '.action' ).removeClass( 'selected' );
567
- updatePrimaryCtaText( 'allow' );
568
- }
569
-
570
- $multisiteOptionsContainer.find( '.action-allow' ).addClass( 'selected' );
571
-
572
- $skipActivationButton.toggle();
573
-
574
- $delegateToSiteAdminsButton.toggle();
575
-
576
- $multisiteOptionsContainer.toggleClass( 'fs-apply-on-all-sites', isChecked );
577
-
578
- $sitesListContainer.toggle( ! isChecked );
579
- if ( ! isChecked && null === maxSitesListHeight ) {
580
- /**
581
- * Set the visible number of rows to 5 (5 * height of the first row).
582
- *
583
- * @author Leo Fajardo (@leorw)
584
- */
585
- maxSitesListHeight = ( 5 * $sitesListContainer.find( 'tr:first' ).height() );
586
- $sitesListContainer.css( 'max-height', maxSitesListHeight );
587
- }
588
- });
589
-
590
- $allSitesOptions.find( '.action' ).click(function( evt ) {
591
- var actionType = $( evt.target ).data( 'action-type' );
592
-
593
- $multisiteOptionsContainer.find( '.action' ).removeClass( 'selected' );
594
- $multisiteOptionsContainer.find( '.action-' + actionType ).toggleClass( 'selected' );
595
-
596
- updatePrimaryCtaText( actionType );
597
- });
598
-
599
- $sitesListContainer.delegate( '.action', 'click', function( evt ) {
600
- var $this = $( evt.target );
601
- if ( $this.hasClass( 'selected' ) ) {
602
- return false;
603
- }
604
-
605
- $this.parents( 'tr:first' ).find( '.action' ).removeClass( 'selected' );
606
- $this.toggleClass( 'selected' );
607
-
608
- var
609
- singleSiteActionType = $this.data( 'action-type' ),
610
- totalSelected = $sitesListContainer.find( '.action-' + singleSiteActionType + '.selected' ).length;
611
-
612
- $allSitesOptions.find( '.action.selected' ).removeClass( 'selected' );
613
-
614
- if ( totalSelected === totalSites ) {
615
- $allSitesOptions.find( '.action-' + singleSiteActionType ).addClass( 'selected' );
616
-
617
- updatePrimaryCtaText( singleSiteActionType );
618
- } else {
619
- updatePrimaryCtaText( 'mixed' );
620
- }
621
- });
622
-
623
- if ( isNetworkUpgradeMode || hasAnyInstall ) {
624
- $skipActivationButton.click(function(){
625
- $delegateToSiteAdminsButton.hide();
626
-
627
- $skipActivationButton.html('<?php fs_esc_js_echo_inline( 'Skipping, please wait', 'skipping-wait', $slug ) ?>...');
628
-
629
- pauseCtaLabelUpdate = true;
630
-
631
- // Check all sites to be skipped.
632
- $allSitesOptions.find('.action.action-skip').click();
633
-
634
- $form.submit();
635
-
636
- pauseCtaLabelUpdate = false;
637
-
638
- return false;
639
- });
640
-
641
- $delegateToSiteAdminsButton.click(function(){
642
- $delegateToSiteAdminsButton.html('<?php fs_esc_js_echo_inline( 'Delegating, please wait', 'delegating-wait', $slug ) ?>...');
643
-
644
- pauseCtaLabelUpdate = true;
645
-
646
- /**
647
- * Set to true so that the form submission handler can differentiate delegation from license
648
- * activation and the proper AJAX action will be used (when delegating, the action should be
649
- * `network_activate` and not `activate_license`).
650
- *
651
- * @author Leo Fajardo (@leorw)
652
- * @since 2.3.0
653
- */
654
- isNetworkDelegating = true;
655
-
656
- // Check all sites to be skipped.
657
- $allSitesOptions.find('.action.action-delegate').click();
658
-
659
- $form.submit();
660
-
661
- pauseCtaLabelUpdate = false;
662
-
663
- /**
664
- * Set to false so that in case the previous AJAX request has failed, the form submission handler
665
- * can differentiate license activation from delegation and the proper AJAX action will be used
666
- * (when activating a license, the action should be `activate_license` and not `network_activate`).
667
- *
668
- * @author Leo Fajardo (@leorw)
669
- * @since 2.3.0
670
- */
671
- isNetworkDelegating = false;
672
-
673
- return false;
674
- });
675
- }
676
- }
677
-
678
- /**
679
- * @author Leo Fajardo (@leorw)
680
- */
681
- function updatePrimaryCtaText( actionType ) {
682
- if (pauseCtaLabelUpdate)
683
- return;
684
-
685
- var text = '<?php fs_esc_js_echo_inline( 'Continue', 'continue', $slug ) ?>';
686
-
687
- switch ( actionType ) {
688
- case 'allow':
689
- text = '<?php fs_esc_js_echo_inline( 'Allow & Continue', 'opt-in-connect', $slug ) ?>';
690
- break;
691
- case 'delegate':
692
- text = '<?php fs_esc_js_echo_inline( 'Delegate to Site Admins & Continue', 'delegate-to-site-admins-and-continue', $slug ) ?>';
693
- break;
694
- case 'skip':
695
- text = '<?php fs_esc_js_echo_x_inline( 'Skip', 'verb', 'skip', $slug ) ?>';
696
- break;
697
- }
698
-
699
- $primaryCta.html( text );
700
- }
701
-
702
- var ajaxOptin = ( requireLicenseKey || isNetworkActive );
703
-
704
- $form.on('submit', function () {
705
- var isExtensionsTrackingAllowed = $( '#fs-permission-extensions .fs-switch' ).hasClass( 'fs-on' );
706
-
707
- $( 'input[name=is_extensions_tracking_allowed]' ).val( isExtensionsTrackingAllowed ? 1 : 0 );
708
-
709
- /**
710
- * @author Vova Feldman (@svovaf)
711
- * @since 1.1.9
712
- */
713
- if ( ajaxOptin ) {
714
- if (!hasContextUser || isNetworkUpgradeMode) {
715
- var action = null,
716
- security = null;
717
-
718
- if ( requireLicenseKey && ! isNetworkDelegating ) {
719
- action = '<?php echo $fs->get_ajax_action( 'activate_license' ) ?>';
720
- security = '<?php echo $fs->get_ajax_security( 'activate_license' ) ?>';
721
- } else {
722
- action = '<?php echo $fs->get_ajax_action( 'network_activate' ) ?>';
723
- security = '<?php echo $fs->get_ajax_security( 'network_activate' ) ?>';
724
- }
725
-
726
- $('.fs-error').remove();
727
-
728
- var
729
- licenseKey = $licenseKeyInput.val(),
730
- data = {
731
- action : action,
732
- security : security,
733
- license_key: licenseKey,
734
- module_id : '<?php echo $fs->get_id() ?>'
735
- };
736
-
737
- if (
738
- requireLicenseKey &&
739
- ! isNetworkDelegating &&
740
- isMarketingAllowedByLicense.hasOwnProperty(licenseKey)
741
- ) {
742
- var
743
- isMarketingAllowed = null,
744
- $isMarketingAllowed = $marketingOptin.find( 'input[type="radio"][name="allow-marketing"]:checked');
745
-
746
-
747
- if ($isMarketingAllowed.length > 0)
748
- isMarketingAllowed = ('true' == $isMarketingAllowed.val());
749
-
750
- if ( null == isMarketingAllowedByLicense[ licenseKey ] &&
751
- null == isMarketingAllowed
752
- ) {
753
- $marketingOptin.addClass( 'error' ).show();
754
- resetLoadingMode();
755
- return false;
756
- } else if ( null == isMarketingAllowed ) {
757
- isMarketingAllowed = isMarketingAllowedByLicense[ licenseKey ];
758
- }
759
-
760
- data.is_marketing_allowed = isMarketingAllowed;
761
-
762
- data.is_extensions_tracking_allowed = isExtensionsTrackingAllowed;
763
- }
764
-
765
- $marketingOptin.removeClass( 'error' );
766
-
767
- if ( isNetworkActive ) {
768
- var
769
- sites = [],
770
- applyOnAllSites = $applyOnAllSites.is( ':checked' );
771
-
772
- $sitesListContainer.find( 'tr' ).each(function() {
773
- var
774
- $this = $( this ),
775
- includeSite = ( ! requireLicenseKey || applyOnAllSites || $this.find( 'input' ).is( ':checked' ) );
776
-
777
- if ( ! includeSite )
778
- return;
779
-
780
- var site = {
781
- uid : $this.find( '.uid' ).val(),
782
- url : $this.find( '.url' ).val(),
783
- title : $this.find( '.title' ).val(),
784
- language: $this.find( '.language' ).val(),
785
- charset : $this.find( '.charset' ).val(),
786
- blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
787
- };
788
-
789
- if ( ! requireLicenseKey) {
790
- site.action = $this.find('.action.selected').data('action-type');
791
- } else if ( isNetworkDelegating ) {
792
- site.action = 'delegate';
793
- }
794
-
795
- sites.push( site );
796
- });
797
-
798
- data.sites = sites;
799
-
800
- if ( hasAnyInstall ) {
801
- data.has_any_install = hasAnyInstall;
802
- }
803
- }
804
-
805
- /**
806
- * Use the AJAX opt-in when license key is required to potentially
807
- * process the after install failure hook.
808
- *
809
- * @author Vova Feldman (@svovaf)
810
- * @since 1.2.1.5
811
- */
812
- $.ajax({
813
- url : ajaxurl,
814
- method : 'POST',
815
- data : data,
816
- success: function (result) {
817
- var resultObj = $.parseJSON(result);
818
- if (resultObj.success) {
819
- // Redirect to the "Account" page and sync the license.
820
- window.location.href = resultObj.next_page;
821
- } else {
822
- resetLoadingMode();
823
-
824
- // Show error.
825
- $('.fs-content').prepend('<p class="fs-error">' + (resultObj.error.message ? resultObj.error.message : resultObj.error) + '</p>');
826
- }
827
- },
828
- error: function () {
829
- resetLoadingMode();
830
- }
831
- });
832
-
833
- return false;
834
- }
835
- else {
836
- if (null == $licenseSecret) {
837
- $licenseSecret = $('<input type="hidden" name="license_secret_key" value="" />');
838
- $form.append($licenseSecret);
839
- }
840
-
841
- // Update secret key if premium only plugin.
842
- $licenseSecret.val($licenseKeyInput.val());
843
- }
844
- }
845
-
846
- return true;
847
- });
848
-
849
- $primaryCta.on('click', function () {
850
- console.log('Primary button was clicked');
851
-
852
- $(this).addClass('fs-loading');
853
- $(this).html('<?php echo esc_js( $is_pending_activation ?
854
- fs_text_x_inline( 'Sending email', 'as in the process of sending an email', 'sending-email', $slug ) :
855
- fs_text_x_inline( 'Activating', 'as activating plugin', 'activating', $slug )
856
- ) ?>...');
857
- });
858
-
859
- $('.fs-permissions .fs-trigger').on('click', function () {
860
- $('.fs-permissions').toggleClass('fs-open');
861
-
862
- return false;
863
- });
864
-
865
- $( '.fs-switch' ).click( function () {
866
- $(this)
867
- .toggleClass( 'fs-on' )
868
- .toggleClass( 'fs-off' );
869
- });
870
-
871
- if (requireLicenseKey) {
872
- /**
873
- * Submit license key on enter.
874
- *
875
- * @author Vova Feldman (@svovaf)
876
- * @since 1.1.9
877
- */
878
- $licenseKeyInput.keypress(function (e) {
879
- if (e.which == 13) {
880
- if ('' !== $(this).val()) {
881
- $primaryCta.click();
882
- return false;
883
- }
884
- }
885
- });
886
-
887
- /**
888
- * Disable activation button when empty license key.
889
- *
890
- * @author Vova Feldman (@svovaf)
891
- * @since 1.1.9
892
- */
893
- $licenseKeyInput.on('keyup paste delete cut', function () {
894
- setTimeout(function () {
895
- var key = $licenseKeyInput.val();
896
-
897
- if (key == previousLicenseKey){
898
- return;
899
- }
900
-
901
- if ('' === key) {
902
- $primaryCta.attr('disabled', 'disabled');
903
- $marketingOptin.hide();
904
- } else {
905
- $primaryCta.prop('disabled', false);
906
-
907
- if (32 <= key.length){
908
- fetchIsMarketingAllowedFlagAndToggleOptin();
909
- } else {
910
- $marketingOptin.hide();
911
- }
912
- }
913
-
914
- previousLicenseKey = key;
915
- }, 100);
916
- }).focus();
917
- }
918
-
919
- /**
920
- * Set license mode trigger URL.
921
- *
922
- * @author Vova Feldman (@svovaf)
923
- * @since 1.1.9
924
- */
925
- var
926
- $connectLicenseModeTrigger = $('#fs_connect .fs-freemium-licensing a'),
927
- href = window.location.href;
928
-
929
- if (href.indexOf('?') > 0) {
930
- href += '&';
931
- } else {
932
- href += '?';
933
- }
934
-
935
- if ($connectLicenseModeTrigger.length > 0) {
936
- $connectLicenseModeTrigger.attr(
937
- 'href',
938
- href + 'require_license=' + $connectLicenseModeTrigger.attr('data-require-license')
939
- );
940
- }
941
-
942
- //--------------------------------------------------------------------------------
943
- //region GDPR
944
- //--------------------------------------------------------------------------------
945
- var isMarketingAllowedByLicense = {},
946
- $marketingOptin = $('#fs_marketing_optin'),
947
- previousLicenseKey = null;
948
-
949
- if (requireLicenseKey) {
950
-
951
- var
952
- afterMarketingFlagLoaded = function () {
953
- var licenseKey = $licenseKeyInput.val();
954
-
955
- if (null == isMarketingAllowedByLicense[licenseKey]) {
956
- $marketingOptin.show();
957
-
958
- if ($marketingOptin.find('input[type=radio]:checked').length > 0){
959
- // Focus on button if GDPR opt-in already selected is already selected.
960
- $primaryCta.focus();
961
- } else {
962
- // Focus on the GDPR opt-in radio button.
963
- $($marketingOptin.find('input[type=radio]')[0]).focus();
964
- }
965
- } else {
966
- $marketingOptin.hide();
967
- $primaryCta.focus();
968
- }
969
- },
970
- /**
971
- * @author Leo Fajardo (@leorw)
972
- * @since 2.1.0
973
- */
974
- fetchIsMarketingAllowedFlagAndToggleOptin = function () {
975
- var licenseKey = $licenseKeyInput.val();
976
-
977
- if (licenseKey.length < 32) {
978
- $marketingOptin.hide();
979
- return;
980
- }
981
-
982
- if (isMarketingAllowedByLicense.hasOwnProperty(licenseKey)) {
983
- afterMarketingFlagLoaded();
984
- return;
985
- }
986
-
987
- $marketingOptin.hide();
988
-
989
- setLoadingMode();
990
-
991
- $primaryCta.addClass('fs-loading');
992
- $primaryCta.attr('disabled', 'disabled');
993
- $primaryCta.html('<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...');
994
-
995
- $.ajax({
996
- url : ajaxurl,
997
- method : 'POST',
998
- data : {
999
- action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
1000
- security : '<?php echo $fs->get_ajax_security( 'fetch_is_marketing_required_flag_value' ) ?>',
1001
- license_key: licenseKey,
1002
- module_id : '<?php echo $fs->get_id() ?>'
1003
- },
1004
- success: function (result) {
1005
- resetLoadingMode();
1006
-
1007
- if (result.success) {
1008
- result = result.data;
1009
-
1010
- // Cache result.
1011
- isMarketingAllowedByLicense[licenseKey] = result.is_marketing_allowed;
1012
- }
1013
-
1014
- afterMarketingFlagLoaded();
1015
- }
1016
- });
1017
- };
1018
-
1019
- $marketingOptin.find( 'input' ).click(function() {
1020
- $marketingOptin.removeClass( 'error' );
1021
- });
1022
- }
1023
-
1024
- //endregion
1025
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
1026
  </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.0.7
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ * @var Freemius $fs
16
+ */
17
+ $fs = freemius( $VARS['id'] );
18
+ $slug = $fs->get_slug();
19
+
20
+ $is_pending_activation = $fs->is_pending_activation();
21
+ $is_premium_only = $fs->is_only_premium();
22
+ $has_paid_plans = $fs->has_paid_plan();
23
+ $is_premium_code = $fs->is_premium();
24
+ $is_freemium = $fs->is_freemium();
25
+
26
+ $fs->_enqueue_connect_essentials();
27
+
28
+ $current_user = Freemius::_get_current_wp_user();
29
+
30
+ $first_name = $current_user->user_firstname;
31
+ if ( empty( $first_name ) ) {
32
+ $first_name = $current_user->nickname;
33
+ }
34
+
35
+ $site_url = get_site_url();
36
+ $protocol_pos = strpos( $site_url, '://' );
37
+ if ( false !== $protocol_pos ) {
38
+ $site_url = substr( $site_url, $protocol_pos + 3 );
39
+ }
40
+
41
+ $freemius_site_www = 'https://freemius.com';
42
+
43
+ $freemius_usage_tracking_url = $fs->get_usage_tracking_terms_url();
44
+ $freemius_plugin_terms_url = $fs->get_eula_url();
45
+
46
+ $freemius_site_url = $fs->is_premium() ?
47
+ $freemius_site_www :
48
+ $freemius_usage_tracking_url;
49
+
50
+ if ( $fs->is_premium() ) {
51
+ $freemius_site_url .= '?' . http_build_query( array(
52
+ 'id' => $fs->get_id(),
53
+ 'slug' => $slug,
54
+ ) );
55
+ }
56
+
57
+ $freemius_link = '<a href="' . $freemius_site_url . '" target="_blank" rel="noopener" tabindex="1">freemius.com</a>';
58
+
59
+ $error = fs_request_get( 'error' );
60
+
61
+ $require_license_key = $is_premium_only ||
62
+ ( $is_freemium && $is_premium_code && fs_request_get_bool( 'require_license', true ) );
63
+
64
+ if ( $is_pending_activation ) {
65
+ $require_license_key = false;
66
+ }
67
+
68
+ if ( $require_license_key ) {
69
+ $fs->_add_license_activation_dialog_box();
70
+ }
71
+
72
+ $is_optin_dialog = (
73
+ $fs->is_theme() &&
74
+ $fs->is_themes_page() &&
75
+ $fs->show_opt_in_on_themes_page()
76
+ );
77
+
78
+ if ( $is_optin_dialog ) {
79
+ $show_close_button = false;
80
+ $previous_theme_activation_url = '';
81
+
82
+ if ( ! $is_premium_code ) {
83
+ $show_close_button = true;
84
+ } else if ( $is_premium_only ) {
85
+ $previous_theme_activation_url = $fs->get_previous_theme_activation_url();
86
+ $show_close_button = ( ! empty( $previous_theme_activation_url ) );
87
+ }
88
+ }
89
+
90
+ $is_network_level_activation = (
91
+ fs_is_network_admin() &&
92
+ $fs->is_network_active() &&
93
+ ! $fs->is_network_delegated_connection()
94
+ );
95
+
96
+ $fs_user = Freemius::_get_user_by_email( $current_user->user_email );
97
+
98
+ $activate_with_current_user = (
99
+ is_object( $fs_user ) &&
100
+ ! $is_pending_activation &&
101
+ // If requires a license for activation, use the user associated with the license for the opt-in.
102
+ ! $require_license_key &&
103
+ ! $is_network_level_activation
104
+ );
105
+
106
+ $optin_params = $fs->get_opt_in_params( array(), $is_network_level_activation );
107
+ $sites = isset( $optin_params['sites'] ) ? $optin_params['sites'] : array();
108
+
109
+ $is_network_upgrade_mode = ( fs_is_network_admin() && $fs->is_network_upgrade_mode() );
110
+
111
+ /* translators: %s: name (e.g. Hey John,) */
112
+ $hey_x_text = esc_html( sprintf( fs_text_x_inline( 'Hey %s,', 'greeting', 'hey-x', $slug ), $first_name ) );
113
+
114
+ $is_gdpr_required = ( ! $is_pending_activation && ! $require_license_key ) ?
115
+ FS_GDPR_Manager::instance()->is_required() :
116
+ false;
117
+
118
+ if ( is_null( $is_gdpr_required ) ) {
119
+ $is_gdpr_required = $fs->fetch_and_store_current_user_gdpr_anonymously();
120
+ }
121
+ ?>
122
+ <?php
123
+ if ( $is_optin_dialog ) { ?>
124
+ <div id="fs_theme_connect_wrapper">
125
+ <?php
126
+ if ( $show_close_button ) { ?>
127
+ <button class="close dashicons dashicons-no"><span class="screen-reader-text">Close connect dialog</span>
128
+ </button>
129
+ <?php
130
+ }
131
+ ?>
132
+ <?php
133
+ }
134
+
135
+ /**
136
+ * Allows developers to include custom HTML before the opt-in content.
137
+ *
138
+ * @author Vova Feldman
139
+ * @since 2.3.2
140
+ */
141
+ $fs->do_action( 'connect/before' );
142
+ ?>
143
+ <div id="fs_connect"
144
+ class="wrap<?php if ( ! fs_is_network_admin() && ( ! $fs->is_enable_anonymous() || $is_pending_activation || $require_license_key ) ) {
145
+ echo ' fs-anonymous-disabled';
146
+ } ?><?php echo $require_license_key ? ' require-license-key' : '' ?>">
147
+ <div class="fs-visual">
148
+ <b class="fs-site-icon"><i class="dashicons dashicons-wordpress"></i></b>
149
+ <i class="dashicons dashicons-plus fs-first"></i>
150
+ <?php
151
+ $vars = array( 'id' => $fs->get_id() );
152
+ fs_require_once_template( 'plugin-icon.php', $vars );
153
+ ?>
154
+ <i class="dashicons dashicons-plus fs-second"></i>
155
+ <img class="fs-connect-logo" width="80" height="80" src="//img.freemius.com/connect-logo.png"/>
156
+ </div>
157
+ <div class="fs-content">
158
+ <?php if ( ! empty( $error ) ) : ?>
159
+ <p class="fs-error"><?php echo esc_html( $error ) ?></p>
160
+ <?php endif ?>
161
+ <p><?php
162
+ $button_label = fs_text_inline( 'Allow & Continue', 'opt-in-connect', $slug );
163
+ $message = '';
164
+
165
+ if ( $is_pending_activation ) {
166
+ $button_label = fs_text_inline( 'Re-send activation email', 'resend-activation-email', $slug );
167
+
168
+ $message = $fs->apply_filters( 'pending_activation_message', sprintf(
169
+ /* translators: %s: name (e.g. Thanks John!) */
170
+ fs_text_inline( 'Thanks %s!', 'thanks-x', $slug ) . '<br>' .
171
+ fs_text_inline( 'You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to %s.', 'pending-activation-message', $slug ),
172
+ $first_name,
173
+ '<b>' . $fs->get_plugin_name() . '</b>',
174
+ '<b>' . $current_user->user_email . '</b>',
175
+ fs_text_inline( 'complete the install', 'complete-the-install', $slug )
176
+ ) );
177
+ } else if ( $require_license_key ) {
178
+ $button_label = $is_network_upgrade_mode ?
179
+ fs_text_inline( 'Activate License', 'agree-activate-license', $slug ) :
180
+ fs_text_inline( 'Agree & Activate License', 'agree-activate-license', $slug );
181
+
182
+ $message = $fs->apply_filters(
183
+ 'connect-message_on-premium',
184
+ sprintf( fs_text_inline( 'Welcome to %s! To get started, please enter your license key:', 'thanks-for-purchasing', $slug ), '<b>' . $fs->get_plugin_name() . '</b>' ),
185
+ $first_name,
186
+ $fs->get_plugin_name()
187
+ );
188
+ } else {
189
+ $filter = 'connect_message';
190
+ $default_optin_message = $is_gdpr_required ?
191
+ fs_text_inline( 'Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s.', 'connect-message', $slug) :
192
+ fs_text_inline( 'Never miss an important update - opt in to our security and feature updates notifications, and non-sensitive diagnostic tracking with %4$s.', 'connect-message', $slug);
193
+
194
+ if ( $fs->is_plugin_update() ) {
195
+ // If Freemius was added on a plugin update, set different
196
+ // opt-in message.
197
+ $default_optin_message = $is_gdpr_required ?
198
+ fs_text_inline( 'Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s. If you skip this, that\'s okay! %1$s will still work just fine.', 'connect-message_on-update', $slug ) :
199
+ fs_text_inline( 'Never miss an important update - opt in to our security & feature updates notifications, and non-sensitive diagnostic tracking with %4$s. If you skip this, that\'s okay! %1$s will still work just fine.', 'connect-message_on-update', $slug );
200
+
201
+ // If user customized the opt-in message on update, use
202
+ // that message. Otherwise, fallback to regular opt-in
203
+ // custom message if exist.
204
+ if ( $fs->has_filter( 'connect_message_on_update' ) ) {
205
+ $filter = 'connect_message_on_update';
206
+ }
207
+ }
208
+
209
+ $message = $fs->apply_filters(
210
+ $filter,
211
+ ($is_network_upgrade_mode ?
212
+ '' :
213
+ /* translators: %s: name (e.g. Hey John,) */
214
+ $hey_x_text . '<br>'
215
+ ) .
216
+ sprintf(
217
+ esc_html( $default_optin_message ),
218
+ '<b>' . esc_html( $fs->get_plugin_name() ) . '</b>',
219
+ '<b>' . $current_user->user_login . '</b>',
220
+ '<a href="' . $site_url . '" target="_blank" rel="noopener noreferrer">' . $site_url . '</a>',
221
+ $freemius_link
222
+ ),
223
+ $first_name,
224
+ $fs->get_plugin_name(),
225
+ $current_user->user_login,
226
+ '<a href="' . $site_url . '" target="_blank" rel="noopener noreferrer">' . $site_url . '</a>',
227
+ $freemius_link,
228
+ $is_gdpr_required
229
+ );
230
+ }
231
+
232
+ if ( $is_network_upgrade_mode ) {
233
+ $network_integration_text = esc_html( fs_text_inline( 'We\'re excited to introduce the Freemius network-level integration.', 'connect_message_network_upgrade', $slug ) );
234
+
235
+ if ($is_premium_code){
236
+ $message = $network_integration_text . ' ' . sprintf( fs_text_inline( 'During the update process we detected %d site(s) that are still pending license activation.', 'connect_message_network_upgrade-premium', $slug ), count( $sites ) );
237
+
238
+ $message .= '<br><br>' . sprintf( fs_text_inline( 'If you\'d like to use the %s on those sites, please enter your license key below and click the activation button.', 'connect_message_network_upgrade-premium-activate-license', $slug ), $is_premium_only ? $fs->get_module_label( true ) : sprintf(
239
+ /* translators: %s: module type (plugin, theme, or add-on) */
240
+ fs_text_inline( "%s's paid features", 'x-paid-features', $slug ),
241
+ $fs->get_module_label( true )
242
+ ) );
243
+
244
+ /* translators: %s: module type (plugin, theme, or add-on) */
245
+ $message .= ' ' . sprintf( fs_text_inline( 'Alternatively, you can skip it for now and activate the license later, in your %s\'s network-level Account page.', 'connect_message_network_upgrade-premium-skip-license', $slug ), $fs->get_module_label( true ) );
246
+ }else {
247
+ $message = $network_integration_text . ' ' . sprintf( fs_text_inline( 'During the update process we detected %s site(s) in the network that are still pending your attention.', 'connect_message_network_upgrade-free', $slug ), count( $sites ) ) . '<br><br>' . ( fs_starts_with( $message, $hey_x_text . '<br>' ) ? substr( $message, strlen( $hey_x_text . '<br>' ) ) : $message );
248
+ }
249
+ }
250
+
251
+ echo $message;
252
+ ?></p>
253
+ <?php if ( $require_license_key ) : ?>
254
+ <div class="fs-license-key-container">
255
+ <input id="fs_license_key" name="fs_key" type="text" required maxlength="<?php echo $fs->apply_filters('license_key_maxlength', 32) ?>"
256
+ placeholder="<?php fs_esc_attr_echo_inline( 'License key', 'license-key', $slug ) ?>" tabindex="1"/>
257
+ <i class="dashicons dashicons-admin-network"></i>
258
+ <a class="show-license-resend-modal show-license-resend-modal-<?php echo $fs->get_unique_affix() ?>"
259
+ href="#"><?php fs_esc_html_echo_inline( "Can't find your license key?", 'cant-find-license-key', $slug ); ?></a>
260
+ </div>
261
+
262
+ <?php
263
+ /**
264
+ * Allows developers to include custom HTML after the license input container.
265
+ *
266
+ * @author Vova Feldman
267
+ * @since 2.1.2
268
+ */
269
+ $fs->do_action( 'connect/after_license_input' );
270
+ ?>
271
+
272
+ <?php
273
+ $send_updates_text = sprintf(
274
+ '%s<span class="action-description"> - %s</span>',
275
+ $fs->get_text_inline( 'Yes', 'yes' ),
276
+ $fs->get_text_inline( 'send me security & feature updates, educational content and offers.', 'send-updates' )
277
+ );
278
+
279
+ $do_not_send_updates_text = sprintf(
280
+ '%s<span class="action-description"> - %s</span>',
281
+ $fs->get_text_inline( 'No', 'no' ),
282
+ sprintf(
283
+ $fs->get_text_inline( 'do %sNOT%s send me security & feature updates, educational content and offers.', 'do-not-send-updates' ),
284
+ '<span class="underlined">',
285
+ '</span>'
286
+ )
287
+ );
288
+ ?>
289
+ <div id="fs_marketing_optin">
290
+ <span class="fs-message"><?php fs_echo_inline( "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:", 'contact-for-updates' ) ?></span>
291
+ <div class="fs-input-container">
292
+ <label>
293
+ <input type="radio" name="allow-marketing" value="true" tabindex="1" />
294
+ <span class="fs-input-label"><?php echo $send_updates_text ?></span>
295
+ </label>
296
+ <label>
297
+ <input type="radio" name="allow-marketing" value="false" tabindex="1" />
298
+ <span class="fs-input-label"><?php echo $do_not_send_updates_text ?></span>
299
+ </label>
300
+ </div>
301
+ </div>
302
+ <?php endif ?>
303
+ <?php if ( $is_network_level_activation ) : ?>
304
+ <?php
305
+ $vars = array(
306
+ 'id' => $fs->get_id(),
307
+ 'sites' => $sites,
308
+ 'require_license_key' => $require_license_key
309
+ );
310
+
311
+ echo fs_get_template( 'partials/network-activation.php', $vars );
312
+ ?>
313
+ <?php endif ?>
314
+ </div>
315
+ <div class="fs-actions">
316
+ <?php if ( $fs->is_enable_anonymous() && ! $is_pending_activation && ( ! $require_license_key || $is_network_upgrade_mode ) ) : ?>
317
+ <a id="skip_activation" href="<?php echo fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_skip_activation' ), $is_network_level_activation ), $fs->get_unique_affix() . '_skip_activation' ) ?>"
318
+ class="button button-secondary" tabindex="2"><?php fs_esc_html_echo_x_inline( 'Skip', 'verb', 'skip', $slug ) ?></a>
319
+ <?php endif ?>
320
+ <?php if ( $is_network_level_activation && $fs->apply_filters( 'show_delegation_option', true ) ) : ?>
321
+ <a id="delegate_to_site_admins" class="fs-tooltip-trigger <?php echo is_rtl() ? ' rtl' : '' ?>" href="<?php echo fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_delegate_activation' ) ), $fs->get_unique_affix() . '_delegate_activation' ) ?>"><?php fs_esc_html_echo_inline( 'Delegate to Site Admins', 'delegate-to-site-admins', $slug ) ?><span class="fs-tooltip"><?php fs_esc_html_echo_inline( 'If you click it, this decision will be delegated to the sites administrators.', 'delegate-sites-tooltip', $slug ) ?></span></a>
322
+ <?php endif ?>
323
+ <?php if ( $activate_with_current_user ) : ?>
324
+ <form action="" method="POST">
325
+ <input type="hidden" name="fs_action"
326
+ value="<?php echo $fs->get_unique_affix() ?>_activate_existing">
327
+ <?php wp_nonce_field( 'activate_existing_' . $fs->get_public_key() ) ?>
328
+ <input type="hidden" name="is_extensions_tracking_allowed" value="1">
329
+ <button class="button button-primary" tabindex="1"
330
+ type="submit"><?php echo esc_html( $button_label ) ?></button>
331
+ </form>
332
+ <?php else : ?>
333
+ <form method="post" action="<?php echo WP_FS__ADDRESS ?>/action/service/user/install/">
334
+ <?php unset( $optin_params['sites']); ?>
335
+ <?php foreach ( $optin_params as $name => $value ) : ?>
336
+ <input type="hidden" name="<?php echo $name ?>" value="<?php echo esc_attr( $value ) ?>">
337
+ <?php endforeach ?>
338
+ <input type="hidden" name="is_extensions_tracking_allowed" value="1">
339
+ <button class="button button-primary" tabindex="1"
340
+ type="submit"<?php if ( $require_license_key ) {
341
+ echo ' disabled="disabled"';
342
+ } ?>><?php echo esc_html( $button_label ) ?></button>
343
+ </form>
344
+ <?php endif ?>
345
+ <?php if ( $require_license_key ) : ?>
346
+ <a id="license_issues_link" href="<?php echo $fs->apply_filters( 'known_license_issues_url', 'https://freemius.com/help/documentation/wordpress-sdk/license-activation-issues/' ) ?>" target="_blank"><?php fs_esc_html_echo_inline( 'License issues?', 'license-issues', $slug ) ?></a>
347
+ <?php endif ?>
348
+ </div><?php
349
+
350
+ // Set core permission list items.
351
+ $permissions = array();
352
+
353
+ /**
354
+ * When activating a license key the information of the admin is not collected, we gather the user info from the license.
355
+ *
356
+ * @since 2.3.2
357
+ * @author Vova Feldman
358
+ */
359
+ if ( ! $require_license_key ) {
360
+ $permissions['profile'] = array(
361
+ 'icon-class' => 'dashicons dashicons-admin-users',
362
+ 'label' => $fs->get_text_inline( 'Your Profile Overview', 'permissions-profile' ),
363
+ 'desc' => $fs->get_text_inline( 'Name and email address', 'permissions-profile_desc' ),
364
+ 'priority' => 5,
365
+ );
366
+ }
367
+
368
+ $permissions['site'] = array(
369
+ 'icon-class' => 'dashicons dashicons-admin-settings',
370
+ 'tooltip' => ( $require_license_key ? sprintf( $fs->get_text_inline( 'So you can manage and control your license remotely from the User Dashboard.', 'permissions-site_tooltip' ), $fs->get_module_type() ) : '' ),
371
+ 'label' => $fs->get_text_inline( 'Your Site Overview', 'permissions-site' ),
372
+ 'desc' => $fs->get_text_inline( 'Site URL, WP version, PHP info', 'permissions-site_desc' ),
373
+ 'priority' => 10,
374
+ );
375
+
376
+ if ( ! $require_license_key ) {
377
+ $permissions['notices'] = array(
378
+ 'icon-class' => 'dashicons dashicons-testimonial',
379
+ 'label' => $fs->get_text_inline( 'Admin Notices', 'permissions-admin-notices' ),
380
+ 'desc' => $fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
381
+ 'priority' => 13,
382
+ );
383
+ }
384
+
385
+ $permissions['events'] = array(
386
+ 'icon-class' => 'dashicons dashicons-admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
387
+ 'tooltip' => ( $require_license_key ? sprintf( $fs->get_text_inline( 'So you can reuse the license when the %s is no longer active.', 'permissions-events_tooltip' ), $fs->get_module_type() ) : '' ),
388
+ 'label' => sprintf( $fs->get_text_inline( 'Current %s Status', 'permissions-events' ), ucfirst( $fs->get_module_type() ) ),
389
+ 'desc' => $fs->get_text_inline( 'Active, deactivated, or uninstalled', 'permissions-events_desc' ),
390
+ 'priority' => 20,
391
+ );
392
+
393
+ // Add newsletter permissions if enabled.
394
+ if ( $is_gdpr_required || $fs->is_permission_requested( 'newsletter' ) ) {
395
+ $permissions['newsletter'] = array(
396
+ 'icon-class' => 'dashicons dashicons-email-alt',
397
+ 'label' => $fs->get_text_inline( 'Newsletter', 'permissions-newsletter' ),
398
+ 'desc' => $fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
399
+ 'priority' => 15,
400
+ );
401
+ }
402
+
403
+ $permissions['extensions'] = array(
404
+ 'icon-class' => 'dashicons dashicons-menu',
405
+ 'label' => $fs->get_text_inline( 'Plugins & Themes', 'permissions-extensions' ) . ( $require_license_key ? ' (' . $fs->get_text_inline( 'optional' ) . ')' : '' ),
406
+ 'tooltip' => $fs->get_text_inline( 'To help us troubleshoot any potential issues that may arise from other plugin or theme conflicts.', 'permissions-events_tooltip' ),
407
+ 'desc' => $fs->get_text_inline( 'Title, slug, version, and is active', 'permissions-extensions_desc' ),
408
+ 'priority' => 25,
409
+ 'optional' => true,
410
+ 'default' => $fs->apply_filters( 'permission_extensions_default', ! $require_license_key )
411
+ );
412
+
413
+ // Allow filtering of the permissions list.
414
+ $permissions = $fs->apply_filters( 'permission_list', $permissions );
415
+
416
+ // Sort by priority.
417
+ uasort( $permissions, 'fs_sort_by_priority' );
418
+
419
+ if ( ! empty( $permissions ) ) : ?>
420
+ <div class="fs-permissions">
421
+ <?php if ( $require_license_key ) : ?>
422
+ <p class="fs-license-sync-disclaimer"><?php
423
+ echo sprintf(
424
+ fs_esc_html_inline( 'The %1$s will periodically send %2$s to %3$s for security & feature updates delivery, and license management.', 'license-sync-disclaimer', $slug ),
425
+ $fs->get_module_label( true ),
426
+ sprintf('<a class="fs-trigger" href="#" tabindex="1">%s</a>', fs_esc_html_inline('diagnostic data', 'send-data')),
427
+ '<a class="fs-tooltip-trigger' . (is_rtl() ? ' rtl' : '') . '" href="' . $freemius_site_url . '" target="_blank" rel="noopener" tabindex="1">freemius.com <i class="dashicons dashicons-editor-help" style="text-decoration: none;"><span class="fs-tooltip" style="width: 170px">' . $fs->get_text_inline( 'Freemius is our licensing and software updates engine', 'permissions-extensions_desc' ) . '</span></i></a>'
428
+ ) ?></p>
429
+ <?php else : ?>
430
+ <a class="fs-trigger" href="#" tabindex="1"><?php fs_esc_html_echo_inline( 'What permissions are being granted?', 'what-permissions', $slug ) ?></a>
431
+ <?php endif ?>
432
+ <ul><?php
433
+ foreach ( $permissions as $id => $permission ) : ?>
434
+ <li id="fs-permission-<?php echo esc_attr( $id ); ?>"
435
+ class="fs-permission fs-<?php echo esc_attr( $id ); ?>">
436
+ <i class="<?php echo esc_attr( $permission['icon-class'] ); ?>"></i>
437
+ <?php if ( isset( $permission['optional'] ) && true === $permission['optional'] ) : ?>
438
+ <div class="fs-switch fs-small fs-round fs-<?php echo (! isset( $permission['default'] ) || true === $permission['default'] ) ? 'on' : 'off' ?>">
439
+ <div class="fs-toggle"></div>
440
+ </div>
441
+ <?php endif ?>
442
+
443
+ <div class="fs-permission-description">
444
+ <span<?php if ( ! empty($permission['tooltip']) ) : ?> class="fs-tooltip-trigger"<?php endif ?>><?php echo esc_html( $permission['label'] ); ?><?php if ( ! empty($permission['tooltip']) ) : ?><i class="dashicons dashicons-editor-help"><span class="fs-tooltip" style="width: 200px"><?php echo $permission['tooltip'] ?></span></i><?php endif ?></span>
445
+
446
+ <p><?php echo esc_html( $permission['desc'] ); ?></p>
447
+ </div>
448
+ </li>
449
+ <?php endforeach; ?>
450
+ </ul>
451
+ </div>
452
+ <?php endif ?>
453
+ <?php if ( $is_premium_code && $is_freemium ) : ?>
454
+ <div class="fs-freemium-licensing">
455
+ <p>
456
+ <?php if ( $require_license_key ) : ?>
457
+ <?php fs_esc_html_echo_inline( 'Don\'t have a license key?', 'dont-have-license-key', $slug ) ?>
458
+ <a data-require-license="false" tabindex="1"><?php fs_esc_html_echo_inline( 'Activate Free Version', 'activate-free-version', $slug ) ?></a>
459
+ <?php else : ?>
460
+ <?php fs_echo_inline( 'Have a license key?', 'have-license-key', $slug ) ?>
461
+ <a data-require-license="true" tabindex="1"><?php fs_esc_html_echo_inline( 'Activate License', 'activate-license', $slug ) ?></a>
462
+ <?php endif ?>
463
+ </p>
464
+ </div>
465
+ <?php endif ?>
466
+ <div class="fs-terms">
467
+ <a href="https://freemius.com/privacy/" target="_blank" rel="noopener"
468
+ tabindex="1"><?php fs_esc_html_echo_inline( 'Privacy Policy', 'privacy-policy', $slug ) ?></a>
469
+ &nbsp;&nbsp;-&nbsp;&nbsp;
470
+ <a href="<?php echo $require_license_key ? $freemius_plugin_terms_url : $freemius_usage_tracking_url ?>" target="_blank" rel="noopener" tabindex="1"><?php $require_license_key ? fs_echo_inline( 'License Agreement', 'license-agreement', $slug ) : fs_echo_inline( 'Terms of Service', 'tos', $slug ) ?></a>
471
+ </div>
472
+ </div>
473
+ <?php
474
+ /**
475
+ * Allows developers to include custom HTML after the opt-in content.
476
+ *
477
+ * @author Vova Feldman
478
+ * @since 2.3.2
479
+ */
480
+ $fs->do_action( 'connect/after' );
481
+
482
+ if ( $is_optin_dialog ) { ?>
483
+ </div>
484
+ <?php
485
+ }
486
+ ?>
487
+ <script type="text/javascript">
488
+ (function ($) {
489
+ var $html = $('html');
490
+
491
+ <?php
492
+ if ( $is_optin_dialog ) {
493
+ if ( $show_close_button ) { ?>
494
+ var $themeConnectWrapper = $('#fs_theme_connect_wrapper');
495
+
496
+ $themeConnectWrapper.find('button.close').on('click', function () {
497
+ <?php if ( ! empty( $previous_theme_activation_url ) ) { ?>
498
+ location.href = '<?php echo html_entity_decode( $previous_theme_activation_url ); ?>';
499
+ <?php } else { ?>
500
+ $themeConnectWrapper.remove();
501
+ $html.css({overflow: $html.attr('fs-optin-overflow')});
502
+ <?php } ?>
503
+ });
504
+ <?php
505
+ }
506
+ ?>
507
+
508
+ $html.attr('fs-optin-overflow', $html.css('overflow'));
509
+ $html.css({overflow: 'hidden'});
510
+
511
+ <?php
512
+ }
513
+ ?>
514
+
515
+ var $primaryCta = $('.fs-actions .button.button-primary'),
516
+ primaryCtaLabel = $primaryCta.html(),
517
+ $form = $('.fs-actions form'),
518
+ isNetworkActive = <?php echo $is_network_level_activation ? 'true' : 'false' ?>,
519
+ requireLicenseKey = <?php echo $require_license_key ? 'true' : 'false' ?>,
520
+ hasContextUser = <?php echo $activate_with_current_user ? 'true' : 'false' ?>,
521
+ isNetworkUpgradeMode = <?php echo $is_network_upgrade_mode ? 'true' : 'false' ?>,
522
+ $licenseSecret,
523
+ $licenseKeyInput = $('#fs_license_key'),
524
+ pauseCtaLabelUpdate = false,
525
+ isNetworkDelegating = false,
526
+ /**
527
+ * @author Leo Fajardo (@leorw)
528
+ * @since 2.1.0
529
+ */
530
+ resetLoadingMode = function() {
531
+ // Reset loading mode.
532
+ $primaryCta.html(primaryCtaLabel);
533
+ $primaryCta.prop('disabled', false);
534
+ $(document.body).css({'cursor': 'auto'});
535
+ $('.fs-loading').removeClass('fs-loading');
536
+
537
+ console.log('resetLoadingMode - Primary button was enabled');
538
+ },
539
+ setLoadingMode = function () {
540
+ $(document.body).css({'cursor': 'wait'});
541
+ };
542
+
543
+ $('.fs-actions .button').on('click', function () {
544
+ setLoadingMode();
545
+
546
+ var $this = $(this);
547
+
548
+ setTimeout(function () {
549
+ if ( ! requireLicenseKey || ! $marketingOptin.hasClass( 'error' ) ) {
550
+ $this.attr('disabled', 'disabled');
551
+ }
552
+ }, 200);
553
+ });
554
+
555
+ if ( isNetworkActive ) {
556
+ var
557
+ $multisiteOptionsContainer = $( '.fs-multisite-options-container' ),
558
+ $allSitesOptions = $( '.fs-all-sites-options' ),
559
+ $applyOnAllSites = $( '.fs-apply-on-all-sites-checkbox' ),
560
+ $sitesListContainer = $( '.fs-sites-list-container' ),
561
+ totalSites = <?php echo count( $sites ) ?>,
562
+ maxSitesListHeight = null,
563
+ $skipActivationButton = $( '#skip_activation' ),
564
+ $delegateToSiteAdminsButton = $( '#delegate_to_site_admins' ),
565
+ hasAnyInstall = <?php echo ! is_null( $fs->find_first_install() ) ? 'true' : 'false' ?>;
566
+
567
+ $applyOnAllSites.click(function() {
568
+ var isChecked = $( this ).is( ':checked' );
569
+
570
+ if ( isChecked ) {
571
+ $multisiteOptionsContainer.find( '.action' ).removeClass( 'selected' );
572
+ updatePrimaryCtaText( 'allow' );
573
+ }
574
+
575
+ $multisiteOptionsContainer.find( '.action-allow' ).addClass( 'selected' );
576
+
577
+ $skipActivationButton.toggle();
578
+
579
+ $delegateToSiteAdminsButton.toggle();
580
+
581
+ $multisiteOptionsContainer.toggleClass( 'fs-apply-on-all-sites', isChecked );
582
+
583
+ $sitesListContainer.toggle( ! isChecked );
584
+ if ( ! isChecked && null === maxSitesListHeight ) {
585
+ /**
586
+ * Set the visible number of rows to 5 (5 * height of the first row).
587
+ *
588
+ * @author Leo Fajardo (@leorw)
589
+ */
590
+ maxSitesListHeight = ( 5 * $sitesListContainer.find( 'tr:first' ).height() );
591
+ $sitesListContainer.css( 'max-height', maxSitesListHeight );
592
+ }
593
+ });
594
+
595
+ $allSitesOptions.find( '.action' ).click(function( evt ) {
596
+ var actionType = $( evt.target ).data( 'action-type' );
597
+
598
+ $multisiteOptionsContainer.find( '.action' ).removeClass( 'selected' );
599
+ $multisiteOptionsContainer.find( '.action-' + actionType ).toggleClass( 'selected' );
600
+
601
+ updatePrimaryCtaText( actionType );
602
+ });
603
+
604
+ $sitesListContainer.delegate( '.action', 'click', function( evt ) {
605
+ var $this = $( evt.target );
606
+ if ( $this.hasClass( 'selected' ) ) {
607
+ return false;
608
+ }
609
+
610
+ $this.parents( 'tr:first' ).find( '.action' ).removeClass( 'selected' );
611
+ $this.toggleClass( 'selected' );
612
+
613
+ var
614
+ singleSiteActionType = $this.data( 'action-type' ),
615
+ totalSelected = $sitesListContainer.find( '.action-' + singleSiteActionType + '.selected' ).length;
616
+
617
+ $allSitesOptions.find( '.action.selected' ).removeClass( 'selected' );
618
+
619
+ if ( totalSelected === totalSites ) {
620
+ $allSitesOptions.find( '.action-' + singleSiteActionType ).addClass( 'selected' );
621
+
622
+ updatePrimaryCtaText( singleSiteActionType );
623
+ } else {
624
+ updatePrimaryCtaText( 'mixed' );
625
+ }
626
+ });
627
+
628
+ if ( isNetworkUpgradeMode || hasAnyInstall ) {
629
+ $skipActivationButton.click(function(){
630
+ $delegateToSiteAdminsButton.hide();
631
+
632
+ $skipActivationButton.html('<?php fs_esc_js_echo_inline( 'Skipping, please wait', 'skipping-wait', $slug ) ?>...');
633
+
634
+ pauseCtaLabelUpdate = true;
635
+
636
+ // Check all sites to be skipped.
637
+ $allSitesOptions.find('.action.action-skip').click();
638
+
639
+ $form.submit();
640
+
641
+ pauseCtaLabelUpdate = false;
642
+
643
+ return false;
644
+ });
645
+
646
+ $delegateToSiteAdminsButton.click(function(){
647
+ $delegateToSiteAdminsButton.html('<?php fs_esc_js_echo_inline( 'Delegating, please wait', 'delegating-wait', $slug ) ?>...');
648
+
649
+ pauseCtaLabelUpdate = true;
650
+
651
+ /**
652
+ * Set to true so that the form submission handler can differentiate delegation from license
653
+ * activation and the proper AJAX action will be used (when delegating, the action should be
654
+ * `network_activate` and not `activate_license`).
655
+ *
656
+ * @author Leo Fajardo (@leorw)
657
+ * @since 2.3.0
658
+ */
659
+ isNetworkDelegating = true;
660
+
661
+ // Check all sites to be skipped.
662
+ $allSitesOptions.find('.action.action-delegate').click();
663
+
664
+ $form.submit();
665
+
666
+ pauseCtaLabelUpdate = false;
667
+
668
+ /**
669
+ * Set to false so that in case the previous AJAX request has failed, the form submission handler
670
+ * can differentiate license activation from delegation and the proper AJAX action will be used
671
+ * (when activating a license, the action should be `activate_license` and not `network_activate`).
672
+ *
673
+ * @author Leo Fajardo (@leorw)
674
+ * @since 2.3.0
675
+ */
676
+ isNetworkDelegating = false;
677
+
678
+ return false;
679
+ });
680
+ }
681
+ }
682
+
683
+ /**
684
+ * @author Leo Fajardo (@leorw)
685
+ */
686
+ function updatePrimaryCtaText( actionType ) {
687
+ if (pauseCtaLabelUpdate)
688
+ return;
689
+
690
+ var text = '<?php fs_esc_js_echo_inline( 'Continue', 'continue', $slug ) ?>';
691
+
692
+ switch ( actionType ) {
693
+ case 'allow':
694
+ text = '<?php fs_esc_js_echo_inline( 'Allow & Continue', 'opt-in-connect', $slug ) ?>';
695
+ break;
696
+ case 'delegate':
697
+ text = '<?php fs_esc_js_echo_inline( 'Delegate to Site Admins & Continue', 'delegate-to-site-admins-and-continue', $slug ) ?>';
698
+ break;
699
+ case 'skip':
700
+ text = '<?php fs_esc_js_echo_x_inline( 'Skip', 'verb', 'skip', $slug ) ?>';
701
+ break;
702
+ }
703
+
704
+ $primaryCta.html( text );
705
+ }
706
+
707
+ var ajaxOptin = ( requireLicenseKey || isNetworkActive );
708
+
709
+ $form.on('submit', function () {
710
+ var $extensionsPermission = $('#fs-permission-extensions .fs-switch'),
711
+ isExtensionsTrackingAllowed = ($extensionsPermission.length > 0) ?
712
+ $extensionsPermission.hasClass('fs-on') :
713
+ null;
714
+
715
+ if (null === isExtensionsTrackingAllowed) {
716
+ $('input[name=is_extensions_tracking_allowed]').remove();
717
+ } else {
718
+ $('input[name=is_extensions_tracking_allowed]').val(isExtensionsTrackingAllowed ? 1 : 0);
719
+ }
720
+
721
+ /**
722
+ * @author Vova Feldman (@svovaf)
723
+ * @since 1.1.9
724
+ */
725
+ if ( ajaxOptin ) {
726
+ if (!hasContextUser || isNetworkUpgradeMode) {
727
+ var action = null,
728
+ security = null;
729
+
730
+ if ( requireLicenseKey && ! isNetworkDelegating ) {
731
+ action = '<?php echo $fs->get_ajax_action( 'activate_license' ) ?>';
732
+ security = '<?php echo $fs->get_ajax_security( 'activate_license' ) ?>';
733
+ } else {
734
+ action = '<?php echo $fs->get_ajax_action( 'network_activate' ) ?>';
735
+ security = '<?php echo $fs->get_ajax_security( 'network_activate' ) ?>';
736
+ }
737
+
738
+ $('.fs-error').remove();
739
+
740
+ var
741
+ licenseKey = $licenseKeyInput.val(),
742
+ data = {
743
+ action : action,
744
+ security : security,
745
+ license_key: licenseKey,
746
+ module_id : '<?php echo $fs->get_id() ?>'
747
+ };
748
+
749
+ if (
750
+ requireLicenseKey &&
751
+ ! isNetworkDelegating &&
752
+ isMarketingAllowedByLicense.hasOwnProperty(licenseKey)
753
+ ) {
754
+ var
755
+ isMarketingAllowed = null,
756
+ $isMarketingAllowed = $marketingOptin.find( 'input[type="radio"][name="allow-marketing"]:checked');
757
+
758
+
759
+ if ($isMarketingAllowed.length > 0)
760
+ isMarketingAllowed = ('true' == $isMarketingAllowed.val());
761
+
762
+ if ( null == isMarketingAllowedByLicense[ licenseKey ] &&
763
+ null == isMarketingAllowed
764
+ ) {
765
+ $marketingOptin.addClass( 'error' ).show();
766
+ resetLoadingMode();
767
+ return false;
768
+ } else if ( null == isMarketingAllowed ) {
769
+ isMarketingAllowed = isMarketingAllowedByLicense[ licenseKey ];
770
+ }
771
+
772
+ data.is_marketing_allowed = isMarketingAllowed;
773
+
774
+ data.is_extensions_tracking_allowed = isExtensionsTrackingAllowed;
775
+ }
776
+
777
+ $marketingOptin.removeClass( 'error' );
778
+
779
+ if ( isNetworkActive ) {
780
+ var
781
+ sites = [],
782
+ applyOnAllSites = $applyOnAllSites.is( ':checked' );
783
+
784
+ $sitesListContainer.find( 'tr' ).each(function() {
785
+ var
786
+ $this = $( this ),
787
+ includeSite = ( ! requireLicenseKey || applyOnAllSites || $this.find( 'input' ).is( ':checked' ) );
788
+
789
+ if ( ! includeSite )
790
+ return;
791
+
792
+ var site = {
793
+ uid : $this.find( '.uid' ).val(),
794
+ url : $this.find( '.url' ).val(),
795
+ title : $this.find( '.title' ).val(),
796
+ language: $this.find( '.language' ).val(),
797
+ charset : $this.find( '.charset' ).val(),
798
+ blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
799
+ };
800
+
801
+ if ( ! requireLicenseKey) {
802
+ site.action = $this.find('.action.selected').data('action-type');
803
+ } else if ( isNetworkDelegating ) {
804
+ site.action = 'delegate';
805
+ }
806
+
807
+ sites.push( site );
808
+ });
809
+
810
+ data.sites = sites;
811
+
812
+ if ( hasAnyInstall ) {
813
+ data.has_any_install = hasAnyInstall;
814
+ }
815
+ }
816
+
817
+ /**
818
+ * Use the AJAX opt-in when license key is required to potentially
819
+ * process the after install failure hook.
820
+ *
821
+ * @author Vova Feldman (@svovaf)
822
+ * @since 1.2.1.5
823
+ */
824
+ $.ajax({
825
+ url : ajaxurl,
826
+ method : 'POST',
827
+ data : data,
828
+ success: function (result) {
829
+ var resultObj = $.parseJSON(result);
830
+ if (resultObj.success) {
831
+ // Redirect to the "Account" page and sync the license.
832
+ window.location.href = resultObj.next_page;
833
+ } else {
834
+ resetLoadingMode();
835
+
836
+ // Show error.
837
+ $('.fs-content').prepend('<p class="fs-error">' + (resultObj.error.message ? resultObj.error.message : resultObj.error) + '</p>');
838
+ }
839
+ },
840
+ error: function () {
841
+ resetLoadingMode();
842
+ }
843
+ });
844
+
845
+ return false;
846
+ }
847
+ else {
848
+ if (null == $licenseSecret) {
849
+ $licenseSecret = $('<input type="hidden" name="license_secret_key" value="" />');
850
+ $form.append($licenseSecret);
851
+ }
852
+
853
+ // Update secret key if premium only plugin.
854
+ $licenseSecret.val($licenseKeyInput.val());
855
+ }
856
+ }
857
+
858
+ return true;
859
+ });
860
+
861
+ $primaryCta.on('click', function () {
862
+ console.log('Primary button was clicked');
863
+
864
+ $(this).addClass('fs-loading');
865
+ $(this).html('<?php echo esc_js( $is_pending_activation ?
866
+ fs_text_x_inline( 'Sending email', 'as in the process of sending an email', 'sending-email', $slug ) :
867
+ fs_text_x_inline( 'Activating', 'as activating plugin', 'activating', $slug )
868
+ ) ?>...');
869
+ });
870
+
871
+ $('.fs-permissions .fs-trigger').on('click', function () {
872
+ $('.fs-permissions').toggleClass('fs-open');
873
+
874
+ return false;
875
+ });
876
+
877
+ $( '.fs-switch' ).click( function () {
878
+ $(this)
879
+ .toggleClass( 'fs-on' )
880
+ .toggleClass( 'fs-off' );
881
+ });
882
+
883
+ if (requireLicenseKey) {
884
+ /**
885
+ * Submit license key on enter.
886
+ *
887
+ * @author Vova Feldman (@svovaf)
888
+ * @since 1.1.9
889
+ */
890
+ $licenseKeyInput.keypress(function (e) {
891
+ if (e.which == 13) {
892
+ if ('' !== $(this).val()) {
893
+ $primaryCta.click();
894
+ return false;
895
+ }
896
+ }
897
+ });
898
+
899
+ /**
900
+ * Disable activation button when empty license key.
901
+ *
902
+ * @author Vova Feldman (@svovaf)
903
+ * @since 1.1.9
904
+ */
905
+ $licenseKeyInput.on('keyup paste delete cut', function () {
906
+ setTimeout(function () {
907
+ var key = $licenseKeyInput.val();
908
+
909
+ if (key == previousLicenseKey){
910
+ return;
911
+ }
912
+
913
+ if ('' === key) {
914
+ $primaryCta.attr('disabled', 'disabled');
915
+ $marketingOptin.hide();
916
+ } else {
917
+ $primaryCta.prop('disabled', false);
918
+
919
+ if (32 <= key.length){
920
+ fetchIsMarketingAllowedFlagAndToggleOptin();
921
+ } else {
922
+ $marketingOptin.hide();
923
+ }
924
+ }
925
+
926
+ previousLicenseKey = key;
927
+ }, 100);
928
+ }).focus();
929
+ }
930
+
931
+ /**
932
+ * Set license mode trigger URL.
933
+ *
934
+ * @author Vova Feldman (@svovaf)
935
+ * @since 1.1.9
936
+ */
937
+ var
938
+ $connectLicenseModeTrigger = $('#fs_connect .fs-freemium-licensing a'),
939
+ href = window.location.href;
940
+
941
+ if (href.indexOf('?') > 0) {
942
+ href += '&';
943
+ } else {
944
+ href += '?';
945
+ }
946
+
947
+ if ($connectLicenseModeTrigger.length > 0) {
948
+ $connectLicenseModeTrigger.attr(
949
+ 'href',
950
+ href + 'require_license=' + $connectLicenseModeTrigger.attr('data-require-license')
951
+ );
952
+ }
953
+
954
+ //--------------------------------------------------------------------------------
955
+ //region GDPR
956
+ //--------------------------------------------------------------------------------
957
+ var isMarketingAllowedByLicense = {},
958
+ $marketingOptin = $('#fs_marketing_optin'),
959
+ previousLicenseKey = null;
960
+
961
+ if (requireLicenseKey) {
962
+
963
+ var
964
+ afterMarketingFlagLoaded = function () {
965
+ var licenseKey = $licenseKeyInput.val();
966
+
967
+ if (null == isMarketingAllowedByLicense[licenseKey]) {
968
+ $marketingOptin.show();
969
+
970
+ if ($marketingOptin.find('input[type=radio]:checked').length > 0){
971
+ // Focus on button if GDPR opt-in already selected is already selected.
972
+ $primaryCta.focus();
973
+ } else {
974
+ // Focus on the GDPR opt-in radio button.
975
+ $($marketingOptin.find('input[type=radio]')[0]).focus();
976
+ }
977
+ } else {
978
+ $marketingOptin.hide();
979
+ $primaryCta.focus();
980
+ }
981
+ },
982
+ /**
983
+ * @author Leo Fajardo (@leorw)
984
+ * @since 2.1.0
985
+ */
986
+ fetchIsMarketingAllowedFlagAndToggleOptin = function () {
987
+ var licenseKey = $licenseKeyInput.val();
988
+
989
+ if (licenseKey.length < 32) {
990
+ $marketingOptin.hide();
991
+ return;
992
+ }
993
+
994
+ if (isMarketingAllowedByLicense.hasOwnProperty(licenseKey)) {
995
+ afterMarketingFlagLoaded();
996
+ return;
997
+ }
998
+
999
+ $marketingOptin.hide();
1000
+
1001
+ setLoadingMode();
1002
+
1003
+ $primaryCta.addClass('fs-loading');
1004
+ $primaryCta.attr('disabled', 'disabled');
1005
+ $primaryCta.html('<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...');
1006
+
1007
+ $.ajax({
1008
+ url : ajaxurl,
1009
+ method : 'POST',
1010
+ data : {
1011
+ action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
1012
+ security : '<?php echo $fs->get_ajax_security( 'fetch_is_marketing_required_flag_value' ) ?>',
1013
+ license_key: licenseKey,
1014
+ module_id : '<?php echo $fs->get_id() ?>'
1015
+ },
1016
+ success: function (result) {
1017
+ resetLoadingMode();
1018
+
1019
+ if (result.success) {
1020
+ result = result.data;
1021
+
1022
+ // Cache result.
1023
+ isMarketingAllowedByLicense[licenseKey] = result.is_marketing_allowed;
1024
+ }
1025
+
1026
+ afterMarketingFlagLoaded();
1027
+ }
1028
+ });
1029
+ };
1030
+
1031
+ $marketingOptin.find( 'input' ).click(function() {
1032
+ $marketingOptin.removeClass( 'error' );
1033
+ });
1034
+ }
1035
+
1036
+ //endregion
1037
+ })(jQuery);
1038
  </script>
freemius/templates/debug.php CHANGED
@@ -37,6 +37,8 @@
37
 
38
  $.post( ajaxurl, {
39
  action: 'fs_toggle_debug_mode',
 
 
40
  is_on : ($(this).hasClass( 'fs-on' ) ? 1 : 0)
41
  }, function ( response ) {
42
  if ( 1 == response ) {
@@ -111,7 +113,8 @@
111
  if (optionName) {
112
  $.post(ajaxurl, {
113
  action : 'fs_get_db_option',
114
- _wpnonce : '<?php echo wp_create_nonce( 'fs_get_db_option' ) ?>',
 
115
  option_name: optionName
116
  }, function (response) {
117
  if (response.data.value)
@@ -131,7 +134,8 @@
131
  if (optionValue) {
132
  $.post(ajaxurl, {
133
  action : 'fs_set_db_option',
134
- _wpnonce : '<?php echo wp_create_nonce( 'fs_set_db_option' ) ?>',
 
135
  option_name : optionName,
136
  option_value: optionValue
137
  }, function () {
@@ -724,6 +728,8 @@
724
 
725
  $.post(ajaxurl, {
726
  action : 'fs_get_debug_log',
 
 
727
  filters: filters,
728
  offset : offset,
729
  limit : limit
37
 
38
  $.post( ajaxurl, {
39
  action: 'fs_toggle_debug_mode',
40
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
41
+ _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_toggle_debug_mode' ) ); ?>,
42
  is_on : ($(this).hasClass( 'fs-on' ) ? 1 : 0)
43
  }, function ( response ) {
44
  if ( 1 == response ) {
113
  if (optionName) {
114
  $.post(ajaxurl, {
115
  action : 'fs_get_db_option',
116
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
117
+ _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_get_db_option' ) ); ?>,
118
  option_name: optionName
119
  }, function (response) {
120
  if (response.data.value)
134
  if (optionValue) {
135
  $.post(ajaxurl, {
136
  action : 'fs_set_db_option',
137
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
138
+ _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_set_db_option' ) ); ?>,
139
  option_name : optionName,
140
  option_value: optionValue
141
  }, function () {
728
 
729
  $.post(ajaxurl, {
730
  action : 'fs_get_debug_log',
731
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
732
+ _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_get_debug_log' ) ); ?>,
733
  filters: filters,
734
  offset : offset,
735
  limit : limit
freemius/templates/firewall-issues-js.php CHANGED
@@ -22,10 +22,12 @@
22
  notice = $( this ).parents( '.fs-notice' ),
23
  ajaxActionSuffix = notice.attr( 'data-manager-id' ).replace( ':', '-' );
24
 
25
- var data = {
26
- action : 'fs_resolve_firewall_issues_' + ajaxActionSuffix,
27
- error_type: error_type
28
- };
 
 
29
 
30
  if ( 'squid' === error_type ) {
31
  data.hosting_company = prompt( 'What is the name or URL of your hosting company?' );
@@ -39,7 +41,9 @@
39
  }
40
 
41
  if ( 'retry_ping' === error_type ) {
42
- data.action = 'fs_retry_connectivity_test_' + ajaxActionSuffix;
 
 
43
  }
44
 
45
  $( this ).css({'cursor': 'wait'});
@@ -56,4 +60,4 @@
56
  });
57
  });
58
  });
59
- </script>
22
  notice = $( this ).parents( '.fs-notice' ),
23
  ajaxActionSuffix = notice.attr( 'data-manager-id' ).replace( ':', '-' );
24
 
25
+ var data = {
26
+ action : 'fs_resolve_firewall_issues_' + ajaxActionSuffix,
27
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
28
+ _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_resolve_firewall_issues' ) ); ?>,
29
+ error_type: error_type
30
+ };
31
 
32
  if ( 'squid' === error_type ) {
33
  data.hosting_company = prompt( 'What is the name or URL of your hosting company?' );
41
  }
42
 
43
  if ( 'retry_ping' === error_type ) {
44
+ data.action = 'fs_retry_connectivity_test_' + ajaxActionSuffix;
45
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
46
+ data._wpnonce = <?php echo wp_json_encode( wp_create_nonce( 'fs_retry_connectivity_test' ) ); ?>;
47
  }
48
 
49
  $( this ).css({'cursor': 'wait'});
60
  });
61
  });
62
  });
63
+ </script>
freemius/templates/forms/license-activation.php CHANGED
@@ -115,13 +115,15 @@ HTML;
115
  * @var FS_Plugin_License $license
116
  */
117
  foreach ( $available_licenses as $license ) {
 
 
118
  $label = sprintf(
119
  "%s-Site %s License - %s",
120
  ( 1 == $license->quota ?
121
  'Single' :
122
  ( $license->is_unlimited() ? 'Unlimited' : $license->quota )
123
  ),
124
- $fs->_get_plan_by_id( $license->plan_id )->title,
125
  $license->get_html_escaped_masked_secret_key()
126
  );
127
 
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
 
freemius/templates/forms/optout.php CHANGED
@@ -1,336 +1,336 @@
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.2.1.5
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- * @var Freemius $fs
16
- */
17
- $fs = freemius( $VARS['id'] );
18
- $slug = $fs->get_slug();
19
-
20
- $action = $fs->is_tracking_allowed() ?
21
- 'stop_tracking' :
22
- 'allow_tracking';
23
-
24
- $reconnect_url = $fs->get_activation_url( array(
25
- 'nonce' => wp_create_nonce( $fs->get_unique_affix() . '_reconnect' ),
26
- 'fs_action' => ( $fs->get_unique_affix() . '_reconnect' ),
27
- ) );
28
-
29
- $plugin_title = "<strong>{$fs->get_plugin()->title}</strong>";
30
- $opt_out_text = fs_text_x_inline( 'Opt Out', 'verb', 'opt-out', $slug );
31
- $opt_in_text = fs_text_x_inline( 'Opt In', 'verb', 'opt-in', $slug );
32
-
33
- if ( $fs->is_premium() ) {
34
- $opt_in_message_appreciation = fs_text_inline( 'Connectivity to the licensing engine was successfully re-established. Automatic security & feature updates are now available through the WP Admin Dashboard.', 'premium-opt-in-message-appreciation', $slug );
35
-
36
- $opt_out_message_subtitle = sprintf( fs_text_inline( 'Warning: Opting out will block automatic updates', 'premium-opt-out-message-appreciation', $slug ), $fs->get_module_type() );
37
- $opt_out_message_usage_tracking = sprintf( fs_text_inline( 'Ongoing connectivity with the licensing engine is essential for receiving automatic security & feature updates of the paid product. To receive these updates, data like your license key, %1$s version, and WordPress version, is periodically sent to the server to check for updates. By opting out, you understand that your site won\'t receive automatic updates for %2$s from within the WP Admin Dashboard. This can put your site at risk, and we highly recommend to keep this connection active. If you do choose to opt-out, you\'ll need to check for %1$s updates and install them manually.', 'premium-opt-out-message-usage-tracking', $slug ), $fs->get_module_type(), $plugin_title );
38
-
39
- $primary_cta_label = fs_text_inline( 'I\'d like to keep automatic updates', 'premium-opt-out-cancel', $slug );
40
- } else {
41
- $opt_in_message_appreciation = sprintf( fs_text_inline( 'We appreciate your help in making the %s better by letting us track some usage data.', 'opt-in-message-appreciation', $slug ), $fs->get_module_type() );
42
-
43
- $opt_out_message_subtitle = $opt_in_message_appreciation;
44
- $opt_out_message_usage_tracking = sprintf( fs_text_inline( "Usage tracking is done in the name of making %s better. Making a better user experience, prioritizing new features, and more good things. We'd really appreciate if you'll reconsider letting us continue with the tracking.", 'opt-out-message-usage-tracking', $slug ), $plugin_title );
45
- $primary_cta_label = fs_text_inline( 'On second thought - I want to continue helping', 'opt-out-cancel', $slug );
46
- }
47
-
48
- $opt_out_message_clicking_opt_out = sprintf(
49
- fs_text_inline( 'By clicking "Opt Out", we will no longer be sending any data from %s to %s.', 'opt-out-message-clicking-opt-out', $slug ),
50
- $plugin_title,
51
- sprintf(
52
- '<a href="%s" target="_blank" rel="noopener">%s</a>',
53
- 'https://freemius.com',
54
- 'freemius.com'
55
- )
56
- );
57
-
58
- $admin_notice_params = array(
59
- 'id' => '',
60
- 'slug' => $fs->get_id(),
61
- 'type' => 'success',
62
- 'sticky' => false,
63
- 'plugin' => $fs->get_plugin()->title,
64
- 'message' => $opt_in_message_appreciation
65
- );
66
-
67
- $admin_notice_html = fs_get_template( 'admin-notice.php', $admin_notice_params );
68
-
69
- $modal_content_html = "
70
- <h2" . ( $fs->is_premium() ? ' style="color: red"' : '' ) . ">{$opt_out_message_subtitle}</h2>
71
- <div class=\"notice notice-error inline opt-out-error-message\"><p></p></div>
72
- <p>{$opt_out_message_usage_tracking}</p>
73
- <p>{$opt_out_message_clicking_opt_out}</p>
74
- <label class=\"fs-permission-extensions\"><div class=\"fs-switch fs-small fs-round fs-" . ( $fs->is_extensions_tracking_allowed() ? 'on' : 'off' ) . "\"><div class=\"fs-toggle\"></div></div> " . fs_text_inline( 'Plugins & themes tracking' ) . " <span class=\"fs-switch-feedback success\"></span></label>";
75
-
76
- fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
77
- fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
78
- ?>
79
- <script type="text/javascript">
80
- (function( $ ) {
81
- $( document ).ready(function() {
82
- var modalContentHtml = <?php echo json_encode( $modal_content_html ) ?>,
83
- modalHtml =
84
- '<div class="fs-modal fs-modal-opt-out">'
85
- + ' <div class="fs-modal-dialog">'
86
- + ' <div class="fs-modal-header">'
87
- + ' <h4><?php echo esc_js( $opt_out_text ) ?></h4>'
88
- + ' </div>'
89
- + ' <div class="fs-modal-body">'
90
- + ' <div class="fs-modal-panel active">' + modalContentHtml + '</div>'
91
- + ' </div>'
92
- + ' <div class="fs-modal-footer">'
93
- + ' <button class="button <?php echo $fs->is_premium() ? 'button-primary warn' : 'button-secondary' ?> button-opt-out" tabindex="1"><?php echo esc_js( $opt_out_text ) ?></button>'
94
- + ' <button class="button <?php echo $fs->is_premium() ? 'button-secondary' : 'button-primary' ?> button-close" tabindex="2"><?php echo esc_js( $primary_cta_label ) ?></button>'
95
- + ' </div>'
96
- + ' </div>'
97
- + '</div>',
98
- $modal = $(modalHtml),
99
- $adminNotice = $( <?php echo json_encode( $admin_notice_html ) ?> ),
100
- action = '<?php echo $action ?>',
101
- actionLinkSelector = 'span.opt-in-or-opt-out.<?php echo $slug ?> a',
102
- $optOutButton = $modal.find( '.button-opt-out' ),
103
- $optOutErrorMessage = $modal.find( '.opt-out-error-message' ),
104
- $extensionsTracking = $modal.find( '.fs-permission-extensions' ),
105
- $body = $( 'body' ),
106
- moduleID = '<?php echo $fs->get_id() ?>';
107
-
108
- $modal.data( 'action', action );
109
- $modal.appendTo( $body );
110
-
111
- function registerActionLinkClick() {
112
- $body.on( 'click', actionLinkSelector, function( evt ) {
113
- evt.preventDefault();
114
-
115
- if ( 'stop_tracking' == $modal.data( 'action' ) ) {
116
- showModal();
117
- } else {
118
- optIn();
119
- }
120
-
121
- return false;
122
- });
123
- }
124
-
125
- function registerEventHandlers() {
126
- registerActionLinkClick();
127
-
128
- $modal.on( 'click', '.button-opt-out', function( evt ) {
129
- evt.preventDefault();
130
-
131
- if ( $( this ).hasClass( 'disabled' ) ) {
132
- return;
133
- }
134
-
135
- disableOptOutButton();
136
- optOut();
137
- });
138
-
139
- // If the user has clicked outside the window, close the modal.
140
- $modal.on( 'click', '.fs-close, .button-close', function() {
141
- closeModal();
142
- return false;
143
- });
144
- }
145
-
146
- <?php if ( $fs->is_registered() ) : ?>
147
- registerEventHandlers();
148
- <?php endif ?>
149
-
150
- function showModal() {
151
- resetModal();
152
-
153
- // Display the dialog box.
154
- $modal.addClass( 'active' );
155
- $body.addClass( 'has-fs-modal' );
156
- }
157
-
158
- function closeModal() {
159
- $modal.removeClass( 'active' );
160
- $body.removeClass( 'has-fs-modal' );
161
- }
162
-
163
- function resetOptOutButton() {
164
- enableOptOutButton();
165
- $optOutButton.text( <?php echo json_encode( $opt_out_text ) ?> );
166
- }
167
-
168
- function resetModal() {
169
- hideError();
170
- resetOptOutButton();
171
- }
172
-
173
- function optIn() {
174
- sendRequest();
175
- }
176
-
177
- function optOut() {
178
- sendRequest();
179
- }
180
-
181
- function sendRequest() {
182
- var $actionLink = $( actionLinkSelector );
183
-
184
- $.ajax({
185
- url: ajaxurl,
186
- method: 'POST',
187
- data: {
188
- action : ( 'stop_tracking' == action ?
189
- '<?php echo $fs->get_ajax_action( 'stop_tracking' ) ?>' :
190
- '<?php echo $fs->get_ajax_action( 'allow_tracking' ) ?>'
191
- ),
192
- security : ( 'stop_tracking' == action ?
193
- '<?php echo $fs->get_ajax_security( 'stop_tracking' ) ?>' :
194
- '<?php echo $fs->get_ajax_security( 'allow_tracking' ) ?>'
195
- ),
196
- module_id: moduleID,
197
- _wp_http_referer: '<?php echo $fs->current_page_url() ?>'
198
- },
199
- beforeSend: function() {
200
- if ( 'allow_tracking' == action ) {
201
- $actionLink.text( '<?php fs_esc_js_echo_inline( 'Opting in', 'opting-in', $slug ) ?>...' );
202
- } else {
203
- $optOutButton.text( '<?php fs_esc_js_echo_inline( 'Opting out', 'opting-out', $slug ) ?>...' );
204
- }
205
- },
206
- success: function( resultObj ) {
207
- if ( resultObj.success ) {
208
- if ( 'allow_tracking' == action ) {
209
- action = 'stop_tracking';
210
- $actionLink.text( '<?php echo esc_js( $opt_out_text ) ?>' );
211
- showOptInAppreciationMessageAndScrollToTop();
212
- } else {
213
- action = 'allow_tracking';
214
- $actionLink.text( '<?php echo esc_js( $opt_in_text ) ?>' );
215
- closeModal();
216
-
217
- if ( $adminNotice.length > 0 ) {
218
- $adminNotice.remove();
219
- }
220
- }
221
-
222
- $modal.data( 'action', action );
223
- } else {
224
- showError( resultObj.error );
225
- resetOptOutButton();
226
- }
227
- }
228
- });
229
- }
230
-
231
- var isUpdatingPermission = false;
232
- $extensionsTracking.on('click', function() {
233
- if (isUpdatingPermission) {
234
- return false;
235
- }
236
-
237
- isUpdatingPermission = true;
238
-
239
- var $switch = $extensionsTracking.find( '.fs-switch' ),
240
- $switchFeedback = $extensionsTracking.find( '.fs-switch-feedback' );
241
-
242
- $switch
243
- .toggleClass( 'fs-on' )
244
- .toggleClass( 'fs-off' );
245
-
246
- $switchFeedback.html( '<i class="fs-ajax-spinner"></i>' );
247
-
248
- $.ajax({
249
- url: ajaxurl,
250
- method: 'POST',
251
- data: {
252
- action : '<?php echo $fs->get_ajax_action( 'update_tracking_permission' ) ?>',
253
- security : '<?php echo $fs->get_ajax_security( 'update_tracking_permission' ) ?>',
254
- module_id : moduleID,
255
- _wp_http_referer: '<?php echo $fs->current_page_url() ?>',
256
- permission: 'extensions',
257
- is_enabled: $switch.hasClass('fs-on')
258
- },
259
- success: function( resultObj ) {
260
- if ( resultObj.success ) {
261
- $switchFeedback.html( '<i class="dashicons dashicons-yes"></i> <?php echo esc_js( fs_text_inline( 'Saved', 'saved', $slug ) ) ?>' )
262
- } else {
263
- $switch
264
- .toggleClass( 'fs-on' )
265
- .toggleClass( 'fs-off' );
266
- }
267
-
268
- isUpdatingPermission = false;
269
- }
270
- });
271
- });
272
-
273
- function enableOptOutButton() {
274
- $optOutButton.removeClass( 'disabled' );
275
- }
276
-
277
- function disableOptOutButton() {
278
- $optOutButton.addClass( 'disabled' );
279
- }
280
-
281
- function hideError() {
282
- $optOutErrorMessage.hide();
283
- }
284
-
285
- function showOptInAppreciationMessageAndScrollToTop() {
286
- $adminNotice.insertAfter( $( '#wpbody-content' ).find( ' > .wrap > h1' ) );
287
- window.scrollTo(0, 0);
288
- }
289
-
290
- function showError( msg ) {
291
- $optOutErrorMessage.find( ' > p' ).html( msg );
292
- $optOutErrorMessage.show();
293
- }
294
-
295
- <?php if ( $fs->is_theme() ) : ?>
296
- /**
297
- * Add opt-in/out button to the active theme's buttons collection
298
- * in the theme's extended details overlay.
299
- *
300
- * @author Vova Feldman (@svovaf)
301
- * @since 1.2.2.7
302
- */
303
- $('.theme-overlay').contentChange(function () {
304
- if (0 === $('.theme-overlay.active').length) {
305
- // Add opt-in/out button only to the currently active theme.
306
- return;
307
- }
308
-
309
- if ($('#fs_theme_opt_in_out').length > 0){
310
- // Button already there.
311
- return;
312
- }
313
-
314
- var label = (('stop_tracking' == action) ?
315
- '<?php echo esc_js( $opt_out_text ) ?>' :
316
- '<?php echo esc_js( $opt_in_text ) ?>'),
317
- href = (('stop_tracking' != action) ?
318
- '<?php echo ( $fs->is_registered() ? '' : esc_js( $reconnect_url ) ) ?>' :
319
- '');
320
-
321
- var $actionLink = $('<a id="fs_theme_opt_in_out" href="' + encodeURI(href) + '" class="button">' + label + '</a>');
322
-
323
- actionLinkSelector = '#fs_theme_opt_in_out';
324
-
325
- $modal.data( 'action', action );
326
-
327
- $('.theme-wrap .theme-actions .active-theme').append($actionLink);
328
-
329
- if ('' === href) {
330
- registerActionLinkClick();
331
- }
332
- });
333
- <?php endif ?>
334
- });
335
- })( jQuery );
336
- </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.2.1.5
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ * @var Freemius $fs
16
+ */
17
+ $fs = freemius( $VARS['id'] );
18
+ $slug = $fs->get_slug();
19
+
20
+ $action = $fs->is_tracking_allowed() ?
21
+ 'stop_tracking' :
22
+ 'allow_tracking';
23
+
24
+ $reconnect_url = $fs->get_activation_url( array(
25
+ 'nonce' => wp_create_nonce( $fs->get_unique_affix() . '_reconnect' ),
26
+ 'fs_action' => ( $fs->get_unique_affix() . '_reconnect' ),
27
+ ) );
28
+
29
+ $plugin_title = "<strong>{$fs->get_plugin()->title}</strong>";
30
+ $opt_out_text = fs_text_x_inline( 'Opt Out', 'verb', 'opt-out', $slug );
31
+ $opt_in_text = fs_text_x_inline( 'Opt In', 'verb', 'opt-in', $slug );
32
+
33
+ if ( $fs->is_premium() ) {
34
+ $opt_in_message_appreciation = fs_text_inline( 'Connectivity to the licensing engine was successfully re-established. Automatic security & feature updates are now available through the WP Admin Dashboard.', 'premium-opt-in-message-appreciation', $slug );
35
+
36
+ $opt_out_message_subtitle = sprintf( fs_text_inline( 'Warning: Opting out will block automatic updates', 'premium-opt-out-message-appreciation', $slug ), $fs->get_module_type() );
37
+ $opt_out_message_usage_tracking = sprintf( fs_text_inline( 'Ongoing connectivity with the licensing engine is essential for receiving automatic security & feature updates of the paid product. To receive these updates, data like your license key, %1$s version, and WordPress version, is periodically sent to the server to check for updates. By opting out, you understand that your site won\'t receive automatic updates for %2$s from within the WP Admin Dashboard. This can put your site at risk, and we highly recommend to keep this connection active. If you do choose to opt-out, you\'ll need to check for %1$s updates and install them manually.', 'premium-opt-out-message-usage-tracking', $slug ), $fs->get_module_type(), $plugin_title );
38
+
39
+ $primary_cta_label = fs_text_inline( 'I\'d like to keep automatic updates', 'premium-opt-out-cancel', $slug );
40
+ } else {
41
+ $opt_in_message_appreciation = sprintf( fs_text_inline( 'We appreciate your help in making the %s better by letting us track some usage data.', 'opt-in-message-appreciation', $slug ), $fs->get_module_type() );
42
+
43
+ $opt_out_message_subtitle = $opt_in_message_appreciation;
44
+ $opt_out_message_usage_tracking = sprintf( fs_text_inline( "Usage tracking is done in the name of making %s better. Making a better user experience, prioritizing new features, and more good things. We'd really appreciate if you'll reconsider letting us continue with the tracking.", 'opt-out-message-usage-tracking', $slug ), $plugin_title );
45
+ $primary_cta_label = fs_text_inline( 'On second thought - I want to continue helping', 'opt-out-cancel', $slug );
46
+ }
47
+
48
+ $opt_out_message_clicking_opt_out = sprintf(
49
+ fs_text_inline( 'By clicking "Opt Out", we will no longer be sending any data from %s to %s.', 'opt-out-message-clicking-opt-out', $slug ),
50
+ $plugin_title,
51
+ sprintf(
52
+ '<a href="%s" target="_blank" rel="noopener">%s</a>',
53
+ 'https://freemius.com',
54
+ 'freemius.com'
55
+ )
56
+ );
57
+
58
+ $admin_notice_params = array(
59
+ 'id' => '',
60
+ 'slug' => $fs->get_id(),
61
+ 'type' => 'success',
62
+ 'sticky' => false,
63
+ 'plugin' => $fs->get_plugin()->title,
64
+ 'message' => $opt_in_message_appreciation
65
+ );
66
+
67
+ $admin_notice_html = fs_get_template( 'admin-notice.php', $admin_notice_params );
68
+
69
+ $modal_content_html = "
70
+ <h2" . ( $fs->is_premium() ? ' style="color: red"' : '' ) . ">{$opt_out_message_subtitle}</h2>
71
+ <div class=\"notice notice-error inline opt-out-error-message\"><p></p></div>
72
+ <p>{$opt_out_message_usage_tracking}</p>
73
+ <p>{$opt_out_message_clicking_opt_out}</p>
74
+ <label class=\"fs-permission-extensions\"><div class=\"fs-switch fs-small fs-round fs-" . ( $fs->is_extensions_tracking_allowed() ? 'on' : 'off' ) . "\"><div class=\"fs-toggle\"></div></div> " . fs_text_inline( 'Plugins & themes tracking' ) . " <span class=\"fs-switch-feedback success\"></span></label>";
75
+
76
+ fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
77
+ fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
78
+ ?>
79
+ <script type="text/javascript">
80
+ (function( $ ) {
81
+ $( document ).ready(function() {
82
+ var modalContentHtml = <?php echo json_encode( $modal_content_html ) ?>,
83
+ modalHtml =
84
+ '<div class="fs-modal fs-modal-opt-out">'
85
+ + ' <div class="fs-modal-dialog">'
86
+ + ' <div class="fs-modal-header">'
87
+ + ' <h4><?php echo esc_js( $opt_out_text ) ?></h4>'
88
+ + ' </div>'
89
+ + ' <div class="fs-modal-body">'
90
+ + ' <div class="fs-modal-panel active">' + modalContentHtml + '</div>'
91
+ + ' </div>'
92
+ + ' <div class="fs-modal-footer">'
93
+ + ' <button class="button <?php echo $fs->is_premium() ? 'button-primary warn' : 'button-secondary' ?> button-opt-out" tabindex="1"><?php echo esc_js( $opt_out_text ) ?></button>'
94
+ + ' <button class="button <?php echo $fs->is_premium() ? 'button-secondary' : 'button-primary' ?> button-close" tabindex="2"><?php echo esc_js( $primary_cta_label ) ?></button>'
95
+ + ' </div>'
96
+ + ' </div>'
97
+ + '</div>',
98
+ $modal = $(modalHtml),
99
+ $adminNotice = $( <?php echo json_encode( $admin_notice_html ) ?> ),
100
+ action = '<?php echo $action ?>',
101
+ actionLinkSelector = 'span.opt-in-or-opt-out.<?php echo $slug ?> a',
102
+ $optOutButton = $modal.find( '.button-opt-out' ),
103
+ $optOutErrorMessage = $modal.find( '.opt-out-error-message' ),
104
+ $extensionsTracking = $modal.find( '.fs-permission-extensions' ),
105
+ $body = $( 'body' ),
106
+ moduleID = '<?php echo $fs->get_id() ?>';
107
+
108
+ $modal.data( 'action', action );
109
+ $modal.appendTo( $body );
110
+
111
+ function registerActionLinkClick() {
112
+ $body.on( 'click', actionLinkSelector, function( evt ) {
113
+ evt.preventDefault();
114
+
115
+ if ( 'stop_tracking' == $modal.data( 'action' ) ) {
116
+ showModal();
117
+ } else {
118
+ optIn();
119
+ }
120
+
121
+ return false;
122
+ });
123
+ }
124
+
125
+ function registerEventHandlers() {
126
+ registerActionLinkClick();
127
+
128
+ $modal.on( 'click', '.button-opt-out', function( evt ) {
129
+ evt.preventDefault();
130
+
131
+ if ( $( this ).hasClass( 'disabled' ) ) {
132
+ return;
133
+ }
134
+
135
+ disableOptOutButton();
136
+ optOut();
137
+ });
138
+
139
+ // If the user has clicked outside the window, close the modal.
140
+ $modal.on( 'click', '.fs-close, .button-close', function() {
141
+ closeModal();
142
+ return false;
143
+ });
144
+ }
145
+
146
+ <?php if ( $fs->is_registered() ) : ?>
147
+ registerEventHandlers();
148
+ <?php endif ?>
149
+
150
+ function showModal() {
151
+ resetModal();
152
+
153
+ // Display the dialog box.
154
+ $modal.addClass( 'active' );
155
+ $body.addClass( 'has-fs-modal' );
156
+ }
157
+
158
+ function closeModal() {
159
+ $modal.removeClass( 'active' );
160
+ $body.removeClass( 'has-fs-modal' );
161
+ }
162
+
163
+ function resetOptOutButton() {
164
+ enableOptOutButton();
165
+ $optOutButton.text( <?php echo json_encode( $opt_out_text ) ?> );
166
+ }
167
+
168
+ function resetModal() {
169
+ hideError();
170
+ resetOptOutButton();
171
+ }
172
+
173
+ function optIn() {
174
+ sendRequest();
175
+ }
176
+
177
+ function optOut() {
178
+ sendRequest();
179
+ }
180
+
181
+ function sendRequest() {
182
+ var $actionLink = $( actionLinkSelector );
183
+
184
+ $.ajax({
185
+ url: ajaxurl,
186
+ method: 'POST',
187
+ data: {
188
+ action : ( 'stop_tracking' == action ?
189
+ '<?php echo $fs->get_ajax_action( 'stop_tracking' ) ?>' :
190
+ '<?php echo $fs->get_ajax_action( 'allow_tracking' ) ?>'
191
+ ),
192
+ security : ( 'stop_tracking' == action ?
193
+ '<?php echo $fs->get_ajax_security( 'stop_tracking' ) ?>' :
194
+ '<?php echo $fs->get_ajax_security( 'allow_tracking' ) ?>'
195
+ ),
196
+ module_id: moduleID,
197
+ _wp_http_referer: '<?php echo $fs->current_page_url() ?>'
198
+ },
199
+ beforeSend: function() {
200
+ if ( 'allow_tracking' == action ) {
201
+ $actionLink.text( '<?php fs_esc_js_echo_inline( 'Opting in', 'opting-in', $slug ) ?>...' );
202
+ } else {
203
+ $optOutButton.text( '<?php fs_esc_js_echo_inline( 'Opting out', 'opting-out', $slug ) ?>...' );
204
+ }
205
+ },
206
+ success: function( resultObj ) {
207
+ if ( resultObj.success ) {
208
+ if ( 'allow_tracking' == action ) {
209
+ action = 'stop_tracking';
210
+ $actionLink.text( '<?php echo esc_js( $opt_out_text ) ?>' );
211
+ showOptInAppreciationMessageAndScrollToTop();
212
+ } else {
213
+ action = 'allow_tracking';
214
+ $actionLink.text( '<?php echo esc_js( $opt_in_text ) ?>' );
215
+ closeModal();
216
+
217
+ if ( $adminNotice.length > 0 ) {
218
+ $adminNotice.remove();
219
+ }
220
+ }
221
+
222
+ $modal.data( 'action', action );
223
+ } else {
224
+ showError( resultObj.error );
225
+ resetOptOutButton();
226
+ }
227
+ }
228
+ });
229
+ }
230
+
231
+ var isUpdatingPermission = false;
232
+ $extensionsTracking.on('click', function() {
233
+ if (isUpdatingPermission) {
234
+ return false;
235
+ }
236
+
237
+ isUpdatingPermission = true;
238
+
239
+ var $switch = $extensionsTracking.find( '.fs-switch' ),
240
+ $switchFeedback = $extensionsTracking.find( '.fs-switch-feedback' );
241
+
242
+ $switch
243
+ .toggleClass( 'fs-on' )
244
+ .toggleClass( 'fs-off' );
245
+
246
+ $switchFeedback.html( '<i class="fs-ajax-spinner"></i>' );
247
+
248
+ $.ajax({
249
+ url: ajaxurl,
250
+ method: 'POST',
251
+ data: {
252
+ action : '<?php echo $fs->get_ajax_action( 'update_tracking_permission' ) ?>',
253
+ security : '<?php echo $fs->get_ajax_security( 'update_tracking_permission' ) ?>',
254
+ module_id : moduleID,
255
+ _wp_http_referer: '<?php echo $fs->current_page_url() ?>',
256
+ permission: 'extensions',
257
+ is_enabled: $switch.hasClass('fs-on')
258
+ },
259
+ success: function( resultObj ) {
260
+ if ( resultObj.success ) {
261
+ $switchFeedback.html( '<i class="dashicons dashicons-yes"></i> <?php echo esc_js( fs_text_inline( 'Saved', 'saved', $slug ) ) ?>' )
262
+ } else {
263
+ $switch
264
+ .toggleClass( 'fs-on' )
265
+ .toggleClass( 'fs-off' );
266
+ }
267
+
268
+ isUpdatingPermission = false;
269
+ }
270
+ });
271
+ });
272
+
273
+ function enableOptOutButton() {
274
+ $optOutButton.removeClass( 'disabled' );
275
+ }
276
+
277
+ function disableOptOutButton() {
278
+ $optOutButton.addClass( 'disabled' );
279
+ }
280
+
281
+ function hideError() {
282
+ $optOutErrorMessage.hide();
283
+ }
284
+
285
+ function showOptInAppreciationMessageAndScrollToTop() {
286
+ $adminNotice.insertAfter( $( '#wpbody-content' ).find( ' > .wrap > h1' ) );
287
+ window.scrollTo(0, 0);
288
+ }
289
+
290
+ function showError( msg ) {
291
+ $optOutErrorMessage.find( ' > p' ).html( msg );
292
+ $optOutErrorMessage.show();
293
+ }
294
+
295
+ <?php if ( $fs->is_theme() ) : ?>
296
+ /**
297
+ * Add opt-in/out button to the active theme's buttons collection
298
+ * in the theme's extended details overlay.
299
+ *
300
+ * @author Vova Feldman (@svovaf)
301
+ * @since 1.2.2.7
302
+ */
303
+ $('.theme-overlay').contentChange(function () {
304
+ if (0 === $('.theme-overlay.active').length) {
305
+ // Add opt-in/out button only to the currently active theme.
306
+ return;
307
+ }
308
+
309
+ if ($('#fs_theme_opt_in_out').length > 0){
310
+ // Button already there.
311
+ return;
312
+ }
313
+
314
+ var label = (('stop_tracking' == action) ?
315
+ '<?php echo esc_js( $opt_out_text ) ?>' :
316
+ '<?php echo esc_js( $opt_in_text ) ?>'),
317
+ href = (('stop_tracking' != action) ?
318
+ '<?php echo ( $fs->is_registered() ? '' : esc_js( $reconnect_url ) ) ?>' :
319
+ '');
320
+
321
+ var $actionLink = $('<a id="fs_theme_opt_in_out" href="' + encodeURI(href) + '" class="button">' + label + '</a>');
322
+
323
+ actionLinkSelector = '#fs_theme_opt_in_out';
324
+
325
+ $modal.data( 'action', action );
326
+
327
+ $('.theme-wrap .theme-actions .active-theme').append($actionLink);
328
+
329
+ if ('' === href) {
330
+ registerActionLinkClick();
331
+ }
332
+ });
333
+ <?php endif ?>
334
+ });
335
+ })( jQuery );
336
+ </script>
freemius/templates/partials/network-activation.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
  /**
3
  * @var array $VARS
4
  * @var Freemius $fs
@@ -86,4 +91,4 @@
86
  </tbody>
87
  </table>
88
  </div>
89
- </div>
1
  <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
  /**
8
  * @var array $VARS
9
  * @var Freemius $fs
91
  </tbody>
92
  </table>
93
  </div>
94
+ </div>
freemius/templates/sticky-admin-notice-js.php CHANGED
@@ -23,7 +23,9 @@
23
 
24
  notice.fadeOut( 'fast', function() {
25
  var data = {
26
- action : 'fs_dismiss_notice_action_' + ajaxActionSuffix,
 
 
27
  message_id: id
28
  };
29
 
@@ -36,4 +38,4 @@
36
  });
37
  });
38
  });
39
- </script>
23
 
24
  notice.fadeOut( 'fast', function() {
25
  var data = {
26
+ action : 'fs_dismiss_notice_action_' + ajaxActionSuffix,
27
+ // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
28
+ _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_dismiss_notice_action' ) ); ?>,
29
  message_id: id
30
  };
31
 
38
  });
39
  });
40
  });
41
+ </script>
license.txt CHANGED
@@ -1,674 +1,674 @@
1
- GNU GENERAL PUBLIC LICENSE
2
- Version 3, 29 June 2007
3
-
4
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
- Everyone is permitted to copy and distribute verbatim copies
6
- of this license document, but changing it is not allowed.
7
-
8
- Preamble
9
-
10
- The GNU General Public License is a free, copyleft license for
11
- software and other kinds of works.
12
-
13
- The licenses for most software and other practical works are designed
14
- to take away your freedom to share and change the works. By contrast,
15
- the GNU General Public License is intended to guarantee your freedom to
16
- share and change all versions of a program--to make sure it remains free
17
- software for all its users. We, the Free Software Foundation, use the
18
- GNU General Public License for most of our software; it applies also to
19
- any other work released this way by its authors. You can apply it to
20
- your programs, too.
21
-
22
- When we speak of free software, we are referring to freedom, not
23
- price. Our General Public Licenses are designed to make sure that you
24
- have the freedom to distribute copies of free software (and charge for
25
- them if you wish), that you receive source code or can get it if you
26
- want it, that you can change the software or use pieces of it in new
27
- free programs, and that you know you can do these things.
28
-
29
- To protect your rights, we need to prevent others from denying you
30
- these rights or asking you to surrender the rights. Therefore, you have
31
- certain responsibilities if you distribute copies of the software, or if
32
- you modify it: responsibilities to respect the freedom of others.
33
-
34
- For example, if you distribute copies of such a program, whether
35
- gratis or for a fee, you must pass on to the recipients the same
36
- freedoms that you received. You must make sure that they, too, receive
37
- or can get the source code. And you must show them these terms so they
38
- know their rights.
39
-
40
- Developers that use the GNU GPL protect your rights with two steps:
41
- (1) assert copyright on the software, and (2) offer you this License
42
- giving you legal permission to copy, distribute and/or modify it.
43
-
44
- For the developers' and authors' protection, the GPL clearly explains
45
- that there is no warranty for this free software. For both users' and
46
- authors' sake, the GPL requires that modified versions be marked as
47
- changed, so that their problems will not be attributed erroneously to
48
- authors of previous versions.
49
-
50
- Some devices are designed to deny users access to install or run
51
- modified versions of the software inside them, although the manufacturer
52
- can do so. This is fundamentally incompatible with the aim of
53
- protecting users' freedom to change the software. The systematic
54
- pattern of such abuse occurs in the area of products for individuals to
55
- use, which is precisely where it is most unacceptable. Therefore, we
56
- have designed this version of the GPL to prohibit the practice for those
57
- products. If such problems arise substantially in other domains, we
58
- stand ready to extend this provision to those domains in future versions
59
- of the GPL, as needed to protect the freedom of users.
60
-
61
- Finally, every program is threatened constantly by software patents.
62
- States should not allow patents to restrict development and use of
63
- software on general-purpose computers, but in those that do, we wish to
64
- avoid the special danger that patents applied to a free program could
65
- make it effectively proprietary. To prevent this, the GPL assures that
66
- patents cannot be used to render the program non-free.
67
-
68
- The precise terms and conditions for copying, distribution and
69
- modification follow.
70
-
71
- TERMS AND CONDITIONS
72
-
73
- 0. Definitions.
74
-
75
- "This License" refers to version 3 of the GNU General Public License.
76
-
77
- "Copyright" also means copyright-like laws that apply to other kinds of
78
- works, such as semiconductor masks.
79
-
80
- "The Program" refers to any copyrightable work licensed under this
81
- License. Each licensee is addressed as "you". "Licensees" and
82
- "recipients" may be individuals or organizations.
83
-
84
- To "modify" a work means to copy from or adapt all or part of the work
85
- in a fashion requiring copyright permission, other than the making of an
86
- exact copy. The resulting work is called a "modified version" of the
87
- earlier work or a work "based on" the earlier work.
88
-
89
- A "covered work" means either the unmodified Program or a work based
90
- on the Program.
91
-
92
- To "propagate" a work means to do anything with it that, without
93
- permission, would make you directly or secondarily liable for
94
- infringement under applicable copyright law, except executing it on a
95
- computer or modifying a private copy. Propagation includes copying,
96
- distribution (with or without modification), making available to the
97
- public, and in some countries other activities as well.
98
-
99
- To "convey" a work means any kind of propagation that enables other
100
- parties to make or receive copies. Mere interaction with a user through
101
- a computer network, with no transfer of a copy, is not conveying.
102
-
103
- An interactive user interface displays "Appropriate Legal Notices"
104
- to the extent that it includes a convenient and prominently visible
105
- feature that (1) displays an appropriate copyright notice, and (2)
106
- tells the user that there is no warranty for the work (except to the
107
- extent that warranties are provided), that licensees may convey the
108
- work under this License, and how to view a copy of this License. If
109
- the interface presents a list of user commands or options, such as a
110
- menu, a prominent item in the list meets this criterion.
111
-
112
- 1. Source Code.
113
-
114
- The "source code" for a work means the preferred form of the work
115
- for making modifications to it. "Object code" means any non-source
116
- form of a work.
117
-
118
- A "Standard Interface" means an interface that either is an official
119
- standard defined by a recognized standards body, or, in the case of
120
- interfaces specified for a particular programming language, one that
121
- is widely used among developers working in that language.
122
-
123
- The "System Libraries" of an executable work include anything, other
124
- than the work as a whole, that (a) is included in the normal form of
125
- packaging a Major Component, but which is not part of that Major
126
- Component, and (b) serves only to enable use of the work with that
127
- Major Component, or to implement a Standard Interface for which an
128
- implementation is available to the public in source code form. A
129
- "Major Component", in this context, means a major essential component
130
- (kernel, window system, and so on) of the specific operating system
131
- (if any) on which the executable work runs, or a compiler used to
132
- produce the work, or an object code interpreter used to run it.
133
-
134
- The "Corresponding Source" for a work in object code form means all
135
- the source code needed to generate, install, and (for an executable
136
- work) run the object code and to modify the work, including scripts to
137
- control those activities. However, it does not include the work's
138
- System Libraries, or general-purpose tools or generally available free
139
- programs which are used unmodified in performing those activities but
140
- which are not part of the work. For example, Corresponding Source
141
- includes interface definition files associated with source files for
142
- the work, and the source code for shared libraries and dynamically
143
- linked subprograms that the work is specifically designed to require,
144
- such as by intimate data communication or control flow between those
145
- subprograms and other parts of the work.
146
-
147
- The Corresponding Source need not include anything that users
148
- can regenerate automatically from other parts of the Corresponding
149
- Source.
150
-
151
- The Corresponding Source for a work in source code form is that
152
- same work.
153
-
154
- 2. Basic Permissions.
155
-
156
- All rights granted under this License are granted for the term of
157
- copyright on the Program, and are irrevocable provided the stated
158
- conditions are met. This License explicitly affirms your unlimited
159
- permission to run the unmodified Program. The output from running a
160
- covered work is covered by this License only if the output, given its
161
- content, constitutes a covered work. This License acknowledges your
162
- rights of fair use or other equivalent, as provided by copyright law.
163
-
164
- You may make, run and propagate covered works that you do not
165
- convey, without conditions so long as your license otherwise remains
166
- in force. You may convey covered works to others for the sole purpose
167
- of having them make modifications exclusively for you, or provide you
168
- with facilities for running those works, provided that you comply with
169
- the terms of this License in conveying all material for which you do
170
- not control copyright. Those thus making or running the covered works
171
- for you must do so exclusively on your behalf, under your direction
172
- and control, on terms that prohibit them from making any copies of
173
- your copyrighted material outside their relationship with you.
174
-
175
- Conveying under any other circumstances is permitted solely under
176
- the conditions stated below. Sublicensing is not allowed; section 10
177
- makes it unnecessary.
178
-
179
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
-
181
- No covered work shall be deemed part of an effective technological
182
- measure under any applicable law fulfilling obligations under article
183
- 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
- similar laws prohibiting or restricting circumvention of such
185
- measures.
186
-
187
- When you convey a covered work, you waive any legal power to forbid
188
- circumvention of technological measures to the extent such circumvention
189
- is effected by exercising rights under this License with respect to
190
- the covered work, and you disclaim any intention to limit operation or
191
- modification of the work as a means of enforcing, against the work's
192
- users, your or third parties' legal rights to forbid circumvention of
193
- technological measures.
194
-
195
- 4. Conveying Verbatim Copies.
196
-
197
- You may convey verbatim copies of the Program's source code as you
198
- receive it, in any medium, provided that you conspicuously and
199
- appropriately publish on each copy an appropriate copyright notice;
200
- keep intact all notices stating that this License and any
201
- non-permissive terms added in accord with section 7 apply to the code;
202
- keep intact all notices of the absence of any warranty; and give all
203
- recipients a copy of this License along with the Program.
204
-
205
- You may charge any price or no price for each copy that you convey,
206
- and you may offer support or warranty protection for a fee.
207
-
208
- 5. Conveying Modified Source Versions.
209
-
210
- You may convey a work based on the Program, or the modifications to
211
- produce it from the Program, in the form of source code under the
212
- terms of section 4, provided that you also meet all of these conditions:
213
-
214
- a) The work must carry prominent notices stating that you modified
215
- it, and giving a relevant date.
216
-
217
- b) The work must carry prominent notices stating that it is
218
- released under this License and any conditions added under section
219
- 7. This requirement modifies the requirement in section 4 to
220
- "keep intact all notices".
221
-
222
- c) You must license the entire work, as a whole, under this
223
- License to anyone who comes into possession of a copy. This
224
- License will therefore apply, along with any applicable section 7
225
- additional terms, to the whole of the work, and all its parts,
226
- regardless of how they are packaged. This License gives no
227
- permission to license the work in any other way, but it does not
228
- invalidate such permission if you have separately received it.
229
-
230
- d) If the work has interactive user interfaces, each must display
231
- Appropriate Legal Notices; however, if the Program has interactive
232
- interfaces that do not display Appropriate Legal Notices, your
233
- work need not make them do so.
234
-
235
- A compilation of a covered work with other separate and independent
236
- works, which are not by their nature extensions of the covered work,
237
- and which are not combined with it such as to form a larger program,
238
- in or on a volume of a storage or distribution medium, is called an
239
- "aggregate" if the compilation and its resulting copyright are not
240
- used to limit the access or legal rights of the compilation's users
241
- beyond what the individual works permit. Inclusion of a covered work
242
- in an aggregate does not cause this License to apply to the other
243
- parts of the aggregate.
244
-
245
- 6. Conveying Non-Source Forms.
246
-
247
- You may convey a covered work in object code form under the terms
248
- of sections 4 and 5, provided that you also convey the
249
- machine-readable Corresponding Source under the terms of this License,
250
- in one of these ways:
251
-
252
- a) Convey the object code in, or embodied in, a physical product
253
- (including a physical distribution medium), accompanied by the
254
- Corresponding Source fixed on a durable physical medium
255
- customarily used for software interchange.
256
-
257
- b) Convey the object code in, or embodied in, a physical product
258
- (including a physical distribution medium), accompanied by a
259
- written offer, valid for at least three years and valid for as
260
- long as you offer spare parts or customer support for that product
261
- model, to give anyone who possesses the object code either (1) a
262
- copy of the Corresponding Source for all the software in the
263
- product that is covered by this License, on a durable physical
264
- medium customarily used for software interchange, for a price no
265
- more than your reasonable cost of physically performing this
266
- conveying of source, or (2) access to copy the
267
- Corresponding Source from a network server at no charge.
268
-
269
- c) Convey individual copies of the object code with a copy of the
270
- written offer to provide the Corresponding Source. This
271
- alternative is allowed only occasionally and non commercially, and
272
- only if you received the object code with such an offer, in accord
273
- with subsection 6b.
274
-
275
- d) Convey the object code by offering access from a designated
276
- place (gratis or for a charge), and offer equivalent access to the
277
- Corresponding Source in the same way through the same place at no
278
- further charge. You need not require recipients to copy the
279
- Corresponding Source along with the object code. If the place to
280
- copy the object code is a network server, the Corresponding Source
281
- may be on a different server (operated by you or a third party)
282
- that supports equivalent copying facilities, provided you maintain
283
- clear directions next to the object code saying where to find the
284
- Corresponding Source. Regardless of what server hosts the
285
- Corresponding Source, you remain obligated to ensure that it is
286
- available for as long as needed to satisfy these requirements.
287
-
288
- e) Convey the object code using peer-to-peer transmission, provided
289
- you inform other peers where the object code and Corresponding
290
- Source of the work are being offered to the general public at no
291
- charge under subsection 6d.
292
-
293
- A separable portion of the object code, whose source code is excluded
294
- from the Corresponding Source as a System Library, need not be
295
- included in conveying the object code work.
296
-
297
- A "User Product" is either (1) a "consumer product", which means any
298
- tangible personal property which is normally used for personal, family,
299
- or household purposes, or (2) anything designed or sold for incorporation
300
- into a dwelling. In determining whether a product is a consumer product,
301
- doubtful cases shall be resolved in favor of coverage. For a particular
302
- product received by a particular user, "normally used" refers to a
303
- typical or common use of that class of product, regardless of the status
304
- of the particular user or of the way in which the particular user
305
- actually uses, or expects or is expected to use, the product. A product
306
- is a consumer product regardless of whether the product has substantial
307
- commercial, industrial or non-consumer uses, unless such uses represent
308
- the only significant mode of use of the product.
309
-
310
- "Installation Information" for a User Product means any methods,
311
- procedures, authorization keys, or other information required to install
312
- and execute modified versions of a covered work in that User Product from
313
- a modified version of its Corresponding Source. The information must
314
- suffice to ensure that the continued functioning of the modified object
315
- code is in no case prevented or interfered with solely because
316
- modification has been made.
317
-
318
- If you convey an object code work under this section in, or with, or
319
- specifically for use in, a User Product, and the conveying occurs as
320
- part of a transaction in which the right of possession and use of the
321
- User Product is transferred to the recipient in perpetuity or for a
322
- fixed term (regardless of how the transaction is characterized), the
323
- Corresponding Source conveyed under this section must be accompanied
324
- by the Installation Information. But this requirement does not apply
325
- if neither you nor any third party retains the ability to install
326
- modified object code on the User Product (for example, the work has
327
- been installed in ROM).
328
-
329
- The requirement to provide Installation Information does not include a
330
- requirement to continue to provide support service, warranty, or updates
331
- for a work that has been modified or installed by the recipient, or for
332
- the User Product in which it has been modified or installed. Access to a
333
- network may be denied when the modification itself materially and
334
- adversely affects the operation of the network or violates the rules and
335
- protocols for communication across the network.
336
-
337
- Corresponding Source conveyed, and Installation Information provided,
338
- in accord with this section must be in a format that is publicly
339
- documented (and with an implementation available to the public in
340
- source code form), and must require no special password or key for
341
- unpacking, reading or copying.
342
-
343
- 7. Additional Terms.
344
-
345
- "Additional permissions" are terms that supplement the terms of this
346
- License by making exceptions from one or more of its conditions.
347
- Additional permissions that are applicable to the entire Program shall
348
- be treated as though they were included in this License, to the extent
349
- that they are valid under applicable law. If additional permissions
350
- apply only to part of the Program, that part may be used separately
351
- under those permissions, but the entire Program remains governed by
352
- this License without regard to the additional permissions.
353
-
354
- When you convey a copy of a covered work, you may at your option
355
- remove any additional permissions from that copy, or from any part of
356
- it. (Additional permissions may be written to require their own
357
- removal in certain cases when you modify the work.) You may place
358
- additional permissions on material, added by you to a covered work,
359
- for which you have or can give appropriate copyright permission.
360
-
361
- Notwithstanding any other provision of this License, for material you
362
- add to a covered work, you may (if authorized by the copyright holders of
363
- that material) supplement the terms of this License with terms:
364
-
365
- a) Disclaiming warranty or limiting liability differently from the
366
- terms of sections 15 and 16 of this License; or
367
-
368
- b) Requiring preservation of specified reasonable legal notices or
369
- author attributions in that material or in the Appropriate Legal
370
- Notices displayed by works containing it; or
371
-
372
- c) Prohibiting misrepresentation of the origin of that material, or
373
- requiring that modified versions of such material be marked in
374
- reasonable ways as different from the original version; or
375
-
376
- d) Limiting the use for publicity purposes of names of licensors or
377
- authors of the material; or
378
-
379
- e) Declining to grant rights under trademark law for use of some
380
- trade names, trademarks, or service marks; or
381
-
382
- f) Requiring indemnification of licensors and authors of that
383
- material by anyone who conveys the material (or modified versions of
384
- it) with contractual assumptions of liability to the recipient, for
385
- any liability that these contractual assumptions directly impose on
386
- those licensors and authors.
387
-
388
- All other non-permissive additional terms are considered "further
389
- restrictions" within the meaning of section 10. If the Program as you
390
- received it, or any part of it, contains a notice stating that it is
391
- governed by this License along with a term that is a further
392
- restriction, you may remove that term. If a license document contains
393
- a further restriction but permits relicensing or conveying under this
394
- License, you may add to a covered work material governed by the terms
395
- of that license document, provided that the further restriction does
396
- not survive such relicensing or conveying.
397
-
398
- If you add terms to a covered work in accord with this section, you
399
- must place, in the relevant source files, a statement of the
400
- additional terms that apply to those files, or a notice indicating
401
- where to find the applicable terms.
402
-
403
- Additional terms, permissive or non-permissive, may be stated in the
404
- form of a separately written license, or stated as exceptions;
405
- the above requirements apply either way.
406
-
407
- 8. Termination.
408
-
409
- You may not propagate or modify a covered work except as expressly
410
- provided under this License. Any attempt otherwise to propagate or
411
- modify it is void, and will automatically terminate your rights under
412
- this License (including any patent licenses granted under the third
413
- paragraph of section 11).
414
-
415
- However, if you cease all violation of this License, then your
416
- license from a particular copyright holder is reinstated (a)
417
- provisionally, unless and until the copyright holder explicitly and
418
- finally terminates your license, and (b) permanently, if the copyright
419
- holder fails to notify you of the violation by some reasonable means
420
- prior to 60 days after the cessation.
421
-
422
- Moreover, your license from a particular copyright holder is
423
- reinstated permanently if the copyright holder notifies you of the
424
- violation by some reasonable means, this is the first time you have
425
- received notice of violation of this License (for any work) from that
426
- copyright holder, and you cure the violation prior to 30 days after
427
- your receipt of the notice.
428
-
429
- Termination of your rights under this section does not terminate the
430
- licenses of parties who have received copies or rights from you under
431
- this License. If your rights have been terminated and not permanently
432
- reinstated, you do not qualify to receive new licenses for the same
433
- material under section 10.
434
-
435
- 9. Acceptance Not Required for Having Copies.
436
-
437
- You are not required to accept this License in order to receive or
438
- run a copy of the Program. Ancillary propagation of a covered work
439
- occurring solely as a consequence of using peer-to-peer transmission
440
- to receive a copy likewise does not require acceptance. However,
441
- nothing other than this License grants you permission to propagate or
442
- modify any covered work. These actions infringe copyright if you do
443
- not accept this License. Therefore, by modifying or propagating a
444
- covered work, you indicate your acceptance of this License to do so.
445
-
446
- 10. Automatic Licensing of Downstream Recipients.
447
-
448
- Each time you convey a covered work, the recipient automatically
449
- receives a license from the original licensors, to run, modify and
450
- propagate that work, subject to this License. You are not responsible
451
- for enforcing compliance by third parties with this License.
452
-
453
- An "entity transaction" is a transaction transferring control of an
454
- organization, or substantially all assets of one, or subdividing an
455
- organization, or merging organizations. If propagation of a covered
456
- work results from an entity transaction, each party to that
457
- transaction who receives a copy of the work also receives whatever
458
- licenses to the work the party's predecessor in interest had or could
459
- give under the previous paragraph, plus a right to possession of the
460
- Corresponding Source of the work from the predecessor in interest, if
461
- the predecessor has it or can get it with reasonable efforts.
462
-
463
- You may not impose any further restrictions on the exercise of the
464
- rights granted or affirmed under this License. For example, you may
465
- not impose a license fee, royalty, or other charge for exercise of
466
- rights granted under this License, and you may not initiate litigation
467
- (including a cross-claim or counterclaim in a lawsuit) alleging that
468
- any patent claim is infringed by making, using, selling, offering for
469
- sale, or importing the Program or any portion of it.
470
-
471
- 11. Patents.
472
-
473
- A "contributor" is a copyright holder who authorizes use under this
474
- License of the Program or a work on which the Program is based. The
475
- work thus licensed is called the contributor's "contributor version".
476
-
477
- A contributor's "essential patent claims" are all patent claims
478
- owned or controlled by the contributor, whether already acquired or
479
- hereafter acquired, that would be infringed by some manner, permitted
480
- by this License, of making, using, or selling its contributor version,
481
- but do not include claims that would be infringed only as a
482
- consequence of further modification of the contributor version. For
483
- purposes of this definition, "control" includes the right to grant
484
- patent sublicenses in a manner consistent with the requirements of
485
- this License.
486
-
487
- Each contributor grants you a non-exclusive, worldwide, royalty-free
488
- patent license under the contributor's essential patent claims, to
489
- make, use, sell, offer for sale, import and otherwise run, modify and
490
- propagate the contents of its contributor version.
491
-
492
- In the following three paragraphs, a "patent license" is any express
493
- agreement or commitment, however denominated, not to enforce a patent
494
- (such as an express permission to practice a patent or covenant not to
495
- sue for patent infringement). To "grant" such a patent license to a
496
- party means to make such an agreement or commitment not to enforce a
497
- patent against the party.
498
-
499
- If you convey a covered work, knowingly relying on a patent license,
500
- and the Corresponding Source of the work is not available for anyone
501
- to copy, free of charge and under the terms of this License, through a
502
- publicly available network server or other readily accessible means,
503
- then you must either (1) cause the Corresponding Source to be so
504
- available, or (2) arrange to deprive yourself of the benefit of the
505
- patent license for this particular work, or (3) arrange, in a manner
506
- consistent with the requirements of this License, to extend the patent
507
- license to downstream recipients. "Knowingly relying" means you have
508
- actual knowledge that, but for the patent license, your conveying the
509
- covered work in a country, or your recipient's use of the covered work
510
- in a country, would infringe one or more identifiable patents in that
511
- country that you have reason to believe are valid.
512
-
513
- If, pursuant to or in connection with a single transaction or
514
- arrangement, you convey, or propagate by procuring conveyance of, a
515
- covered work, and grant a patent license to some of the parties
516
- receiving the covered work authorizing them to use, propagate, modify
517
- or convey a specific copy of the covered work, then the patent license
518
- you grant is automatically extended to all recipients of the covered
519
- work and works based on it.
520
-
521
- A patent license is "discriminatory" if it does not include within
522
- the scope of its coverage, prohibits the exercise of, or is
523
- conditioned on the non-exercise of one or more of the rights that are
524
- specifically granted under this License. You may not convey a covered
525
- work if you are a party to an arrangement with a third party that is
526
- in the business of distributing software, under which you make payment
527
- to the third party based on the extent of your activity of conveying
528
- the work, and under which the third party grants, to any of the
529
- parties who would receive the covered work from you, a discriminatory
530
- patent license (a) in connection with copies of the covered work
531
- conveyed by you (or copies made from those copies), or (b) primarily
532
- for and in connection with specific products or compilations that
533
- contain the covered work, unless you entered into that arrangement,
534
- or that patent license was granted, prior to 28 March 2007.
535
-
536
- Nothing in this License shall be construed as excluding or limiting
537
- any implied license or other defenses to infringement that may
538
- otherwise be available to you under applicable patent law.
539
-
540
- 12. No Surrender of Others' Freedom.
541
-
542
- If conditions are imposed on you (whether by court order, agreement or
543
- otherwise) that contradict the conditions of this License, they do not
544
- excuse you from the conditions of this License. If you cannot convey a
545
- covered work so as to satisfy simultaneously your obligations under this
546
- License and any other pertinent obligations, then as a consequence you may
547
- not convey it at all. For example, if you agree to terms that obligate you
548
- to collect a royalty for further conveying from those to whom you convey
549
- the Program, the only way you could satisfy both those terms and this
550
- License would be to refrain entirely from conveying the Program.
551
-
552
- 13. Use with the GNU Affero General Public License.
553
-
554
- Notwithstanding any other provision of this License, you have
555
- permission to link or combine any covered work with a work licensed
556
- under version 3 of the GNU Affero General Public License into a single
557
- combined work, and to convey the resulting work. The terms of this
558
- License will continue to apply to the part which is the covered work,
559
- but the special requirements of the GNU Affero General Public License,
560
- section 13, concerning interaction through a network will apply to the
561
- combination as such.
562
-
563
- 14. Revised Versions of this License.
564
-
565
- The Free Software Foundation may publish revised and/or new versions of
566
- the GNU General Public License from time to time. Such new versions will
567
- be similar in spirit to the present version, but may differ in detail to
568
- address new problems or concerns.
569
-
570
- Each version is given a distinguishing version number. If the
571
- Program specifies that a certain numbered version of the GNU General
572
- Public License "or any later version" applies to it, you have the
573
- option of following the terms and conditions either of that numbered
574
- version or of any later version published by the Free Software
575
- Foundation. If the Program does not specify a version number of the
576
- GNU General Public License, you may choose any version ever published
577
- by the Free Software Foundation.
578
-
579
- If the Program specifies that a proxy can decide which future
580
- versions of the GNU General Public License can be used, that proxy's
581
- public statement of acceptance of a version permanently authorizes you
582
- to choose that version for the Program.
583
-
584
- Later license versions may give you additional or different
585
- permissions. However, no additional obligations are imposed on any
586
- author or copyright holder as a result of your choosing to follow a
587
- later version.
588
-
589
- 15. Disclaimer of Warranty.
590
-
591
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
- APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
- OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
- IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
- ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
-
600
- 16. Limitation of Liability.
601
-
602
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
- THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
- GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
- USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
- PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
- EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
- SUCH DAMAGES.
611
-
612
- 17. Interpretation of Sections 15 and 16.
613
-
614
- If the disclaimer of warranty and limitation of liability provided
615
- above cannot be given local legal effect according to their terms,
616
- reviewing courts shall apply local law that most closely approximates
617
- an absolute waiver of all civil liability in connection with the
618
- Program, unless a warranty or assumption of liability accompanies a
619
- copy of the Program in return for a fee.
620
-
621
- END OF TERMS AND CONDITIONS
622
-
623
- How to Apply These Terms to Your New Programs
624
-
625
- If you develop a new program, and you want it to be of the greatest
626
- possible use to the public, the best way to achieve this is to make it
627
- free software which everyone can redistribute and change under these terms.
628
-
629
- To do so, attach the following notices to the program. It is safest
630
- to attach them to the start of each source file to most effectively
631
- state the exclusion of warranty; and each file should have at least
632
- the "copyright" line and a pointer to where the full notice is found.
633
-
634
- <one line to give the program's name and a brief idea of what it does.>
635
- Copyright (C) <year> <name of author>
636
-
637
- This program is free software: you can redistribute it and/or modify
638
- it under the terms of the GNU General Public License as published by
639
- the Free Software Foundation, either version 3 of the License, or
640
- (at your option) any later version.
641
-
642
- This program is distributed in the hope that it will be useful,
643
- but WITHOUT ANY WARRANTY; without even the implied warranty of
644
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
- GNU General Public License for more details.
646
-
647
- You should have received a copy of the GNU General Public License
648
- along with this program. If not, see <http://www.gnu.org/licenses/>.
649
-
650
- Also add information on how to contact you by electronic and paper mail.
651
-
652
- If the program does terminal interaction, make it output a short
653
- notice like this when it starts in an interactive mode:
654
-
655
- <program> Copyright (C) <year> <name of author>
656
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
- This is free software, and you are welcome to redistribute it
658
- under certain conditions; type `show c' for details.
659
-
660
- The hypothetical commands `show w' and `show c' should show the appropriate
661
- parts of the General Public License. Of course, your program's commands
662
- might be different; for a GUI interface, you would use an "about box".
663
-
664
- You should also get your employer (if you work as a programmer) or school,
665
- if any, to sign a "copyright disclaimer" for the program, if necessary.
666
- For more information on this, and how to apply and follow the GNU GPL, see
667
- <http://www.gnu.org/licenses/>.
668
-
669
- The GNU General Public License does not permit incorporating your program
670
- into proprietary programs. If your program is a subroutine library, you
671
- may consider it more useful to permit linking proprietary applications with
672
- the library. If this is what you want to do, use the GNU Lesser General
673
- Public License instead of this License. But first, please read
674
  <http://www.gnu.org/philosophy/why-not-lgpl.html>.
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and non commercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <http://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
  <http://www.gnu.org/philosophy/why-not-lgpl.html>.
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: bradvin, fooplugins
3
  Donate link: http://fooplugins.com
4
  Tags: lightbox,modal,popup,images,gallery,media
5
  Requires at least: 3.5.1
6
- Tested up to: 5.9
7
- Stable tag: 2.7.16
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -103,6 +103,11 @@ There is a setting to try and disable hard coded lightboxes, but this is not a s
103
 
104
  == Changelog ==
105
 
 
 
 
 
 
106
  = 2.7.16 =
107
  * Updated 01/12/2020
108
  * Fix : fixed settings page CSS due to conflict with some themes
3
  Donate link: http://fooplugins.com
4
  Tags: lightbox,modal,popup,images,gallery,media
5
  Requires at least: 3.5.1
6
+ Tested up to: 6.1
7
+ Stable tag: 2.7.17
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
103
 
104
  == Changelog ==
105
 
106
+ = 2.7.17 =
107
+ * Updated 01/02/2022
108
+ * Fix : Security Fix in wp-admin
109
+ * Update : Update to Freemius SDK
110
+
111
  = 2.7.16 =
112
  * Updated 01/12/2020
113
  * Fix : fixed settings page CSS due to conflict with some themes