Version Description
- Updated localization - pot file updated, French and Italian po mo updated.
- Fixed - Approve button color issue.
- Fixed - Duplicate text message on user registration by invitation code.
- Fixed - Rest API notice.
- Improvement - When using invitation code user will not be created if invition code is not given or incorrect invitation code is used.
- Improvement - When user successfully registers via invitation code the welcome email not sent, instead Approve email is sent and success message appears.
Download this release
Release Info
Developer | wpexpertsio |
Plugin | ![]() |
Version | 2.5 |
Comparing to | |
See all releases |
Code changes from version 2.4.1 to 2.5
- assets/css/nua-admin-style.css +54 -3
- freemius/assets/css/admin/account.css +1 -1
- freemius/assets/css/admin/add-ons.css +1 -2
- freemius/assets/css/admin/affiliation.css +1 -1
- freemius/assets/css/admin/clone-resolution.css +1 -0
- freemius/assets/css/admin/common.css +1 -2
- freemius/assets/css/admin/connect.css +1 -1
- freemius/assets/css/admin/debug.css +1 -1
- freemius/assets/css/admin/dialog-boxes.css +1 -2
- freemius/assets/css/admin/gdpr-optin-notice.css +1 -1
- freemius/assets/css/admin/optout.css +1 -0
- freemius/assets/css/customizer.css +1 -1
- freemius/config.php +5 -5
- freemius/includes/class-freemius-abstract.php +4 -63
- freemius/includes/class-freemius.php +2226 -1050
- freemius/includes/class-fs-admin-notices.php +56 -24
- freemius/includes/class-fs-api.php +27 -3
- freemius/includes/class-fs-lock.php +110 -0
- freemius/includes/class-fs-logger.php +2 -1
- freemius/includes/class-fs-plugin-updater.php +9 -7
- freemius/includes/class-fs-storage.php +106 -80
- freemius/includes/class-fs-user-lock.php +10 -46
- freemius/includes/customizer/class-fs-customizer-upsell-control.php +2 -2
- freemius/includes/entities/class-fs-affiliate-terms.php +4 -0
- freemius/includes/entities/class-fs-site.php +22 -21
- freemius/includes/entities/class-fs-user.php +12 -1
- freemius/includes/fs-core-functions.php +10 -22
- freemius/includes/fs-essential-functions.php +7 -97
- freemius/includes/fs-plugin-info-dialog.php +1 -1
- freemius/includes/managers/class-fs-admin-notice-manager.php +75 -20
- freemius/includes/managers/class-fs-clone-manager.php +1660 -0
- freemius/includes/managers/class-fs-key-value-storage.php +10 -0
- freemius/includes/managers/class-fs-option-manager.php +35 -80
- freemius/includes/managers/class-fs-permission-manager.php +698 -0
- freemius/includes/managers/class-fs-plugin-manager.php +18 -5
- freemius/includes/sdk/FreemiusBase.php +169 -171
- freemius/includes/sdk/FreemiusWordPress.php +5 -5
- freemius/includes/supplements/fs-migration-2.5.1.php +31 -0
- freemius/languages/freemius-cs_CZ.mo +0 -0
- freemius/languages/freemius-da_DK.mo +0 -0
- freemius/languages/freemius-de_DE.mo +0 -0
- freemius/languages/freemius-en.mo +0 -0
- freemius/languages/freemius-es_ES.mo +0 -0
- freemius/languages/freemius-fr_FR.mo +0 -0
- freemius/languages/freemius-he_IL.mo +0 -0
- freemius/languages/freemius-hu_HU.mo +0 -0
- freemius/languages/freemius-it_IT.mo +0 -0
- freemius/languages/freemius-ja.mo +0 -0
- freemius/languages/freemius-nl_NL.mo +0 -0
- freemius/languages/freemius-ru_RU.mo +0 -0
- freemius/languages/freemius-ta.mo +0 -0
- freemius/languages/freemius-zh_CN.mo +0 -0
- freemius/languages/freemius.pot +794 -568
- freemius/require.php +2 -0
- freemius/start.php +6 -2
- freemius/templates/account.php +65 -30
- freemius/templates/account/billing.php +1 -1
- freemius/templates/account/partials/disconnect-button.php +104 -0
- freemius/templates/account/partials/site.php +8 -6
- freemius/templates/account/payments.php +10 -11
- freemius/templates/admin-notice.php +4 -1
- freemius/templates/auto-installation.php +1 -1
- freemius/templates/clone-resolution-js.php +79 -0
- freemius/templates/connect.php +151 -142
- freemius/templates/connect/index.php +3 -0
- freemius/templates/connect/permission.php +43 -0
- freemius/templates/connect/permissions-group.php +72 -0
- freemius/templates/contact.php +1 -1
- freemius/templates/debug.php +78 -16
- freemius/templates/firewall-issues-js.php +1 -2
- freemius/templates/forms/affiliation.php +6 -6
- freemius/templates/forms/data-debug-mode.php +1 -1
- freemius/templates/forms/deactivation/form.php +174 -51
- freemius/templates/forms/email-address-update.php +347 -0
- freemius/templates/forms/license-activation.php +38 -18
- freemius/templates/forms/optout.php +147 -301
- freemius/templates/forms/resend-key.php +5 -2
- freemius/templates/forms/trial-start.php +1 -1
- freemius/templates/forms/user-change.php +1 -1
- freemius/templates/gdpr-optin-js.php +1 -1
- freemius/templates/js/permissions.php +546 -0
- freemius/templates/partials/network-activation.php +1 -1
- freemius/templates/plugin-icon.php +3 -1
- freemius/templates/plugin-info/features.php +1 -1
- freemius/templates/powered-by.php +7 -7
- freemius/templates/pricing.php +12 -11
- freemius/templates/sticky-admin-notice-js.php +1 -2
- freemius/templates/tabs-capture-js.php +1 -1
- includes/admin-approve.php +14 -10
- includes/invitation-code.php +111 -4
- includes/messages.php +18 -0
- includes/zapier/includes/rest-api.php +17 -14
- localization/new-user-approve-fr_FR.mo +0 -0
- localization/new-user-approve-fr_FR.po +473 -218
- localization/new-user-approve-it_IT.mo +0 -0
- localization/new-user-approve-it_IT.po +450 -207
- localization/new-user-approve.pot +371 -127
- new-user-approve.php +16 -13
- readme.txt +11 -3
assets/css/nua-admin-style.css
CHANGED
@@ -68,16 +68,67 @@ body.new-users-approve_page_nua-invitation-code {
|
|
68 |
float: right;
|
69 |
}
|
70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
#pw_denied_users .button-primary {
|
72 |
float: none;
|
73 |
}
|
74 |
|
75 |
-
#
|
76 |
-
#
|
77 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
background: #eb5a46;
|
79 |
color: #FFF;
|
80 |
border-color: #f3463a;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
|
83 |
#nua-approve-admin .postbox-header {
|
68 |
float: right;
|
69 |
}
|
70 |
|
71 |
+
|
72 |
+
#pw_pending_users table.widefat thead {
|
73 |
+
|
74 |
+
width:606px;
|
75 |
+
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
#pw_pending_users table.widefat thead th {
|
80 |
+
|
81 |
+
width:151px;
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
.users_edit_links {
|
86 |
+
display:block;
|
87 |
+
margin-top:-33px;
|
88 |
+
margin-left:38px;
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
#pw_denied_users .button-primary {
|
93 |
float: none;
|
94 |
}
|
95 |
|
96 |
+
#pw_approved_users .button {
|
97 |
+
background: #eb5a46;
|
98 |
+
color: #FFF;
|
99 |
+
border-color: #f3463a;
|
100 |
+
}
|
101 |
+
|
102 |
+
|
103 |
+
|
104 |
+
|
105 |
+
#pw_pending_users .approve-btn {
|
106 |
+
|
107 |
+
background: #61bd4f;
|
108 |
+
color: #FFF;
|
109 |
+
border-color: #73e831;
|
110 |
+
}
|
111 |
+
|
112 |
+
#pw_pending_users .deny-btn {
|
113 |
+
|
114 |
background: #eb5a46;
|
115 |
color: #FFF;
|
116 |
border-color: #f3463a;
|
117 |
+
margin-left:20px;
|
118 |
+
}
|
119 |
+
|
120 |
+
#pw_pending_users .deny-btn, #pw_pending_users .approve-btn {
|
121 |
+
|
122 |
+
width:81px;
|
123 |
+
text-align:center;
|
124 |
+
align-self: center;
|
125 |
+
margin-left:20px;
|
126 |
+
}
|
127 |
+
|
128 |
+
#pw_denied_users .button {
|
129 |
+
background: #61bd4f;
|
130 |
+
color: #FFF;
|
131 |
+
border-color: #73e831;
|
132 |
}
|
133 |
|
134 |
#nua-approve-admin .postbox-header {
|
freemius/assets/css/admin/account.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-notice[data-id=
|
1 |
+
label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-notice[data-id=license_not_whitelabeled].success,.fs-notice[data-id=license_whitelabeled].success{color:inherit;border-left-color:#00a0d2}.fs-notice[data-id=license_not_whitelabeled].success label.fs-plugin-title,.fs-notice[data-id=license_whitelabeled].success label.fs-plugin-title{display:none}#fs_account .postbox,#fs_account .widefat{max-width:800px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #f1f1f1}#fs_account h3 .dashicons{width:26px;height:26px;font-size:1.3em}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}#fs_account_details .button-group{float:right}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table code{line-height:28px}.fs-key-value-table var,.fs-key-value-table code,.fs-key-value-table input[type=text]{color:#0073aa;font-size:16px;background:none}.fs-key-value-table input[type=text]{width:100%;font-weight:bold}.fs-field-beta_program label{margin-left:7px}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_sites .fs-scrollable-table .fs-table-body{max-height:200px;overflow:auto;border:1px solid #e5e5e5}#fs_sites .fs-scrollable-table .fs-table-body>table.widefat{border:none !important}#fs_sites .fs-scrollable-table .fs-main-column{width:100%}#fs_sites .fs-scrollable-table .fs-site-details td:first-of-type{text-align:right;color:gray;width:1px}#fs_sites .fs-scrollable-table .fs-site-details td:last-of-type{text-align:right}#fs_sites .fs-scrollable-table .fs-install-details table tr td{width:1px;white-space:nowrap}#fs_sites .fs-scrollable-table .fs-install-details table tr td:last-of-type{width:auto}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons thead{white-space:nowrap}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold}#fs_billing_address{width:100%}#fs_billing_address tr td{width:50%;padding:5px}#fs_billing_address tr:first-of-type td{padding-top:0}#fs_billing_address span{font-weight:bold}#fs_billing_address input,#fs_billing_address select{display:block;width:100%;margin-top:5px}#fs_billing_address input::-moz-placeholder,#fs_billing_address select::-moz-placeholder{color:transparent;opacity:1}#fs_billing_address input:-ms-input-placeholder,#fs_billing_address select:-ms-input-placeholder{color:transparent}#fs_billing_address input::-webkit-input-placeholder,#fs_billing_address select::-webkit-input-placeholder{color:transparent}#fs_billing_address input.fs-read-mode,#fs_billing_address select.fs-read-mode{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode td span{display:none}#fs_billing_address.fs-read-mode input,#fs_billing_address.fs-read-mode select{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode input::-moz-placeholder,#fs_billing_address.fs-read-mode select::-moz-placeholder{color:#ccc;opacity:1}#fs_billing_address.fs-read-mode input:-ms-input-placeholder,#fs_billing_address.fs-read-mode select:-ms-input-placeholder{color:#ccc}#fs_billing_address.fs-read-mode input::-webkit-input-placeholder,#fs_billing_address.fs-read-mode select::-webkit-input-placeholder{color:#ccc}#fs_billing_address button{display:block;width:100%}@media screen and (max-width: 639px){#fs_account .fs-header-actions{position:static;padding:0 15px 12px 15px;margin:0 0 12px 0}#fs_account .fs-header-actions li{float:none;display:inline-block}#fs_account #fs_account_details{display:block}#fs_account #fs_account_details tbody,#fs_account #fs_account_details tr,#fs_account #fs_account_details td,#fs_account #fs_account_details th{display:block}#fs_account #fs_account_details tr td:first-child{text-align:left}#fs_account #fs_account_details tr td:nth-child(2){padding:0 12px}#fs_account #fs_account_details tr td:nth-child(2) code{margin:0;padding:0}#fs_account #fs_account_details tr td:nth-child(2) label{margin-left:0}#fs_account #fs_account_details tr td:nth-child(3){text-align:left}#fs_account #fs_account_details tr.fs-field-plan td:nth-child(2) .button-group{float:none;margin:12px 0}}
|
freemius/assets/css/admin/add-ons.css
CHANGED
@@ -1,2 +1 @@
|
|
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)}#fs_addons .fs-cards-list{list-style:none}#fs_addons .fs-cards-list .fs-card{float:left;height:152px;width:310px;padding:0;margin:0 0 30px 30px;font-size:14px;list-style:none;border:1px solid #ddd;cursor:pointer;position:relative}#fs_addons .fs-cards-list .fs-card .fs-overlay{position:absolute;left:0;right:0;bottom:0;top:0;z-index:9}#fs_addons .fs-cards-list .fs-card .fs-inner{background-color:#fff;overflow:hidden;height:100%;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner>ul{-moz-transition:all,0.15s;-o-transition:all,0.15s;-ms-transition:all,0.15s;-webkit-transition:all,0.15s;transition:all,0.15s;left:0;right:0;top:0;position:absolute}#fs_addons .fs-cards-list .fs-card .fs-inner>ul>li{list-style:none;line-height:18px;padding:0 15px;width:100%;display:block;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner{padding:0;margin:0;line-height:0;display:block;height:100px;background-repeat:repeat-x;background-size:100% 100%;-moz-transition:all,0.15s;-o-transition:all,0.15s;-ms-transition:all,0.15s;-webkit-transition:all,0.15s;transition:all,0.15s}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner .fs-badge.fs-installed-addon-badge{font-size:1.02em;line-height:1.3em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-title{margin:10px 0 0 0;height:18px;overflow:hidden;color:#000;white-space:nowrap;text-overflow:ellipsis;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-offer{font-size:0.9em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-description{background-color:#f9f9f9;padding:10px 15px 100px 15px;border-top:1px solid #eee;margin:0 0 10px 0;color:#777}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-tag{position:absolute;top:10px;right:0px;background:greenyellow;display:block;padding:2px 10px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.3);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.3);box-shadow:1px 1px 1px rgba(0,0,0,0.3);text-transform:uppercase;font-size:0.9em;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button,#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button-group{position:absolute;top:112px;right:10px}@media screen and (min-width: 960px){#fs_addons .fs-cards-list .fs-card:hover .fs-overlay{border:2px solid #29abe1;margin-left:-1px;margin-top:-1px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner ul{top:-100px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-title,#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-offer{color:#29abe1}}
|
2 |
-
#TB_window,#TB_window iframe{width:821px !important}#plugin-information .fyi{width:266px !important}#plugin-information #section-holder{margin-right:299px}#plugin-information #section-description h2,#plugin-information #section-description h3,#plugin-information #section-description p,#plugin-information #section-description b,#plugin-information #section-description i,#plugin-information #section-description blockquote,#plugin-information #section-description li,#plugin-information #section-description ul,#plugin-information #section-description ol{clear:none}#plugin-information #section-description iframe{max-width:100%}#plugin-information #section-description .fs-selling-points{padding-bottom:10px;border-bottom:1px solid #ddd}#plugin-information #section-description .fs-selling-points ul{margin:0}#plugin-information #section-description .fs-selling-points ul li{padding:0;list-style:none outside none}#plugin-information #section-description .fs-selling-points ul li i.dashicons{color:#71ae00;font-size:3em;vertical-align:middle;line-height:30px;float:left;margin:0 0 0 -15px}#plugin-information #section-description .fs-selling-points ul li h3{margin:1em 30px !important}#plugin-information #section-description .fs-screenshots:after{content:"";display:table;clear:both}#plugin-information #section-description .fs-screenshots ul{list-style:none;margin:0}#plugin-information #section-description .fs-screenshots ul li{width:225px;height:225px;float:left;margin-bottom:20px;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#plugin-information #section-description .fs-screenshots ul li a{display:block;width:100%;height:100%;border:1px solid;-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);background-size:cover}#plugin-information #section-description .fs-screenshots ul li.odd{margin-right:20px}#plugin-information .plugin-information-pricing{margin:-16px;border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan h3{margin-top:0;padding:20px;font-size:16px}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper{border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab{cursor:pointer;position:relative;padding:0 10px;font-size:0.9em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab label{text-transform:uppercase;color:green;background:greenyellow;position:absolute;left:-1px;right:-1px;bottom:100%;border:1px solid darkgreen;padding:2px;text-align:center;font-size:0.9em;line-height:1em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab.nav-tab-active{cursor:default;background:#fffeec;border-bottom-color:#fffeec}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle h3{background:#fffeec;margin:0;padding-bottom:0;color:#0073aa}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .nav-tab-wrapper,#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .fs-billing-frequency{display:none}#plugin-information .plugin-information-pricing .fs-plan .fs-pricing-body{background:#fffeec;padding:20px}#plugin-information .plugin-information-pricing .fs-plan .button{width:100%;text-align:center;font-weight:bold;text-transform:uppercase;font-size:1.1em}#plugin-information .plugin-information-pricing .fs-plan label{white-space:nowrap}#plugin-information .plugin-information-pricing .fs-plan var{font-style:normal}#plugin-information .plugin-information-pricing .fs-plan .fs-billing-frequency,#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-align:center;display:block;font-weight:bold;margin-bottom:10px;text-transform:uppercase;background:#F3F3F3;padding:2px;border:1px solid #ccc}#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-transform:none;color:green;background:greenyellow}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms{font-size:0.9em}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms i{float:left;margin:0 0 0 -15px}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms li{margin:10px 0 0 0}#plugin-information #section-features .fs-features{margin:-20px -26px}#plugin-information #section-features table{width:100%;border-spacing:0;border-collapse:separate}#plugin-information #section-features table thead th{padding:10px 0}#plugin-information #section-features table thead .fs-price{color:#71ae00;font-weight:normal;display:block;text-align:center}#plugin-information #section-features table tbody td{border-top:1px solid #ccc;padding:10px 0;text-align:center;width:100px;color:#71ae00}#plugin-information #section-features table tbody td:first-child{text-align:left;width:auto;color:inherit;padding-left:26px}#plugin-information #section-features table tbody tr.fs-odd td{background:#fefefe}#plugin-information #section-features .dashicons-yes{width:30px;height:30px;font-size:30px}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .button,#plugin-information .fs-dropdown .button-group .button{position:relative;width:auto;top:0;right:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .button:focus,#plugin-information .fs-dropdown .button-group .button:focus{z-index:10}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .fs-dropdown-arrow,#plugin-information .fs-dropdown .button-group .fs-dropdown-arrow{border-top:6px solid white;border-right:4px solid transparent;border-left:4px solid transparent;top:12px;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active:not(.up) .button:not(.fs-dropdown-arrow-button),#plugin-information .fs-dropdown.active:not(.up) .button:not(.fs-dropdown-arrow-button){border-bottom-left-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active:not(.up) .fs-dropdown-arrow-button,#plugin-information .fs-dropdown.active:not(.up) .fs-dropdown-arrow-button{border-bottom-right-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active.up .button:not(.fs-dropdown-arrow-button),#plugin-information .fs-dropdown.active.up .button:not(.fs-dropdown-arrow-button){border-top-left-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active.up .fs-dropdown-arrow-button,#plugin-information .fs-dropdown.active.up .fs-dropdown-arrow-button{border-top-right-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list,#plugin-information .fs-dropdown .fs-dropdown-list{position:absolute;right:-1px;top:100%;margin-left:auto;padding:3px 0;border:1px solid #bfbfbf;background-color:#fff;z-index:1;width:230px;text-align:left;-moz-box-shadow:0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12);-webkit-box-shadow:0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12);box-shadow:0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li,#plugin-information .fs-dropdown .fs-dropdown-list li{margin:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li a,#plugin-information .fs-dropdown .fs-dropdown-list li a{display:block;padding:5px 10px;text-decoration:none;text-shadow:none}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li:hover,#plugin-information .fs-dropdown .fs-dropdown-list li:hover{background-color:#0074a3;color:#fff}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li:hover a,#plugin-information .fs-dropdown .fs-dropdown-list li:hover a{color:#fff}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown:not(.up) .fs-dropdown-list,#plugin-information .fs-dropdown:not(.up) .fs-dropdown-list{-moz-border-radius:3px 0 3px 3px;-webkit-border-radius:3px 0 3px 3px;border-radius:3px 0 3px 3px}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.up .fs-dropdown-list,#plugin-information .fs-dropdown.up .fs-dropdown-list{-moz-border-radius:3px 3px 0 3px;-webkit-border-radius:3px 3px 0 3px;border-radius:3px 3px 0 3px}#plugin-information .fs-dropdown .button-group{width:100%}#plugin-information .fs-dropdown .button-group .button{float:none;font-size:14px;font-weight:normal;text-transform:none}#plugin-information .fs-dropdown .fs-dropdown-list{margin-top:1px}#plugin-information .fs-dropdown.up .fs-dropdown-list{top:auto;bottom:100%;margin-bottom:2px}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group{text-align:center;display:table}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group .button{display:table-cell}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group .button:not(.fs-dropdown-arrow-button){left:1px;width:100%}#plugin-information-footer>.button,#plugin-information-footer .fs-dropdown{position:relative;top:3px}#plugin-information-footer>.button.left,#plugin-information-footer .fs-dropdown.left{float:left}#plugin-information-footer>.right,#plugin-information-footer .fs-dropdown{float:right}@media screen and (max-width: 961px){#fs_addons .fs-cards-list .fs-card{height:265px}}
|
1 |
+
.fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:#fff;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,.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,.3);box-shadow:0 2px 1px -1px rgba(0,0,0,.3)}#fs_addons .fs-cards-list{list-style:none}#fs_addons .fs-cards-list .fs-card{float:left;height:152px;width:310px;padding:0;margin:0 0 30px 30px;font-size:14px;list-style:none;border:1px solid #ddd;cursor:pointer;position:relative}#fs_addons .fs-cards-list .fs-card .fs-overlay{position:absolute;left:0;right:0;bottom:0;top:0;z-index:9}#fs_addons .fs-cards-list .fs-card .fs-inner{background-color:#fff;overflow:hidden;height:100%;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner>ul{-moz-transition:all,.15s;-o-transition:all,.15s;-ms-transition:all,.15s;-webkit-transition:all,.15s;transition:all,.15s;left:0;right:0;top:0;position:absolute}#fs_addons .fs-cards-list .fs-card .fs-inner>ul>li{list-style:none;line-height:18px;padding:0 15px;width:100%;display:block;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner{padding:0;margin:0;line-height:0;display:block;height:100px;background-repeat:repeat-x;background-size:100% 100%;-moz-transition:all,.15s;-o-transition:all,.15s;-ms-transition:all,.15s;-webkit-transition:all,.15s;transition:all,.15s}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner .fs-badge.fs-installed-addon-badge{font-size:1.02em;line-height:1.3em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-title{margin:10px 0 0 0;height:18px;overflow:hidden;color:#000;white-space:nowrap;text-overflow:ellipsis;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-offer{font-size:.9em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-description{background-color:#f9f9f9;padding:10px 15px 100px 15px;border-top:1px solid #eee;margin:0 0 10px 0;color:#777}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-tag{position:absolute;top:10px;right:0px;background:#adff2f;display:block;padding:2px 10px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.3);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.3);box-shadow:1px 1px 1px rgba(0,0,0,.3);text-transform:uppercase;font-size:.9em;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button,#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button-group{position:absolute;top:112px;right:10px}@media screen and (min-width: 960px){#fs_addons .fs-cards-list .fs-card:hover .fs-overlay{border:2px solid #29abe1;margin-left:-1px;margin-top:-1px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner ul{top:-100px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-title,#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-offer{color:#29abe1}}#TB_window,#TB_window iframe{width:821px !important}#plugin-information .fyi{width:266px !important}#plugin-information #section-holder{margin-right:299px}#plugin-information #section-description h2,#plugin-information #section-description h3,#plugin-information #section-description p,#plugin-information #section-description b,#plugin-information #section-description i,#plugin-information #section-description blockquote,#plugin-information #section-description li,#plugin-information #section-description ul,#plugin-information #section-description ol{clear:none}#plugin-information #section-description iframe{max-width:100%}#plugin-information #section-description .fs-selling-points{padding-bottom:10px;border-bottom:1px solid #ddd}#plugin-information #section-description .fs-selling-points ul{margin:0}#plugin-information #section-description .fs-selling-points ul li{padding:0;list-style:none outside none}#plugin-information #section-description .fs-selling-points ul li i.dashicons{color:#71ae00;font-size:3em;vertical-align:middle;line-height:30px;float:left;margin:0 0 0 -15px}#plugin-information #section-description .fs-selling-points ul li h3{margin:1em 30px !important}#plugin-information #section-description .fs-screenshots:after{content:"";display:table;clear:both}#plugin-information #section-description .fs-screenshots ul{list-style:none;margin:0}#plugin-information #section-description .fs-screenshots ul li{width:225px;height:225px;float:left;margin-bottom:20px;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#plugin-information #section-description .fs-screenshots ul li a{display:block;width:100%;height:100%;border:1px solid;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2);background-size:cover}#plugin-information #section-description .fs-screenshots ul li.odd{margin-right:20px}#plugin-information .plugin-information-pricing{margin:-16px;border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan h3{margin-top:0;padding:20px;font-size:16px}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper{border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab{cursor:pointer;position:relative;padding:0 10px;font-size:.9em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab label{text-transform:uppercase;color:green;background:#adff2f;position:absolute;left:-1px;right:-1px;bottom:100%;border:1px solid #006400;padding:2px;text-align:center;font-size:.9em;line-height:1em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab.nav-tab-active{cursor:default;background:#fffeec;border-bottom-color:#fffeec}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle h3{background:#fffeec;margin:0;padding-bottom:0;color:#0073aa}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .nav-tab-wrapper,#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .fs-billing-frequency{display:none}#plugin-information .plugin-information-pricing .fs-plan .fs-pricing-body{background:#fffeec;padding:20px}#plugin-information .plugin-information-pricing .fs-plan .button{width:100%;text-align:center;font-weight:bold;text-transform:uppercase;font-size:1.1em}#plugin-information .plugin-information-pricing .fs-plan label{white-space:nowrap}#plugin-information .plugin-information-pricing .fs-plan var{font-style:normal}#plugin-information .plugin-information-pricing .fs-plan .fs-billing-frequency,#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-align:center;display:block;font-weight:bold;margin-bottom:10px;text-transform:uppercase;background:#f3f3f3;padding:2px;border:1px solid #ccc}#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-transform:none;color:green;background:#adff2f}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms{font-size:.9em}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms i{float:left;margin:0 0 0 -15px}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms li{margin:10px 0 0 0}#plugin-information #section-features .fs-features{margin:-20px -26px}#plugin-information #section-features table{width:100%;border-spacing:0;border-collapse:separate}#plugin-information #section-features table thead th{padding:10px 0}#plugin-information #section-features table thead .fs-price{color:#71ae00;font-weight:normal;display:block;text-align:center}#plugin-information #section-features table tbody td{border-top:1px solid #ccc;padding:10px 0;text-align:center;width:100px;color:#71ae00}#plugin-information #section-features table tbody td:first-child{text-align:left;width:auto;color:inherit;padding-left:26px}#plugin-information #section-features table tbody tr.fs-odd td{background:#fefefe}#plugin-information #section-features .dashicons-yes{width:30px;height:30px;font-size:30px}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .button,#plugin-information .fs-dropdown .button-group .button{position:relative;width:auto;top:0;right:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .button:focus,#plugin-information .fs-dropdown .button-group .button:focus{z-index:10}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .fs-dropdown-arrow,#plugin-information .fs-dropdown .button-group .fs-dropdown-arrow{border-top:6px solid #fff;border-right:4px solid transparent;border-left:4px solid transparent;top:12px;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active:not(.up) .button:not(.fs-dropdown-arrow-button),#plugin-information .fs-dropdown.active:not(.up) .button:not(.fs-dropdown-arrow-button){border-bottom-left-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active:not(.up) .fs-dropdown-arrow-button,#plugin-information .fs-dropdown.active:not(.up) .fs-dropdown-arrow-button{border-bottom-right-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active.up .button:not(.fs-dropdown-arrow-button),#plugin-information .fs-dropdown.active.up .button:not(.fs-dropdown-arrow-button){border-top-left-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active.up .fs-dropdown-arrow-button,#plugin-information .fs-dropdown.active.up .fs-dropdown-arrow-button{border-top-right-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list,#plugin-information .fs-dropdown .fs-dropdown-list{position:absolute;right:-1px;top:100%;margin-left:auto;padding:3px 0;border:1px solid #bfbfbf;background-color:#fff;z-index:1;width:230px;text-align:left;-moz-box-shadow:0px 2px 4px -1px rgba(0,0,0,.2),0px 4px 5px 0px rgba(0,0,0,.14),0px 1px 10px 0px rgba(0,0,0,.12);-webkit-box-shadow:0px 2px 4px -1px rgba(0,0,0,.2),0px 4px 5px 0px rgba(0,0,0,.14),0px 1px 10px 0px rgba(0,0,0,.12);box-shadow:0px 2px 4px -1px rgba(0,0,0,.2),0px 4px 5px 0px rgba(0,0,0,.14),0px 1px 10px 0px rgba(0,0,0,.12)}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li,#plugin-information .fs-dropdown .fs-dropdown-list li{margin:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li a,#plugin-information .fs-dropdown .fs-dropdown-list li a{display:block;padding:5px 10px;text-decoration:none;text-shadow:none}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li:hover,#plugin-information .fs-dropdown .fs-dropdown-list li:hover{background-color:#0074a3;color:#fff}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li:hover a,#plugin-information .fs-dropdown .fs-dropdown-list li:hover a{color:#fff}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown:not(.up) .fs-dropdown-list,#plugin-information .fs-dropdown:not(.up) .fs-dropdown-list{-moz-border-radius:3px 0 3px 3px;-webkit-border-radius:3px 0 3px 3px;border-radius:3px 0 3px 3px}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.up .fs-dropdown-list,#plugin-information .fs-dropdown.up .fs-dropdown-list{-moz-border-radius:3px 3px 0 3px;-webkit-border-radius:3px 3px 0 3px;border-radius:3px 3px 0 3px}#plugin-information .fs-dropdown .button-group{width:100%}#plugin-information .fs-dropdown .button-group .button{float:none;font-size:14px;font-weight:normal;text-transform:none}#plugin-information .fs-dropdown .fs-dropdown-list{margin-top:1px}#plugin-information .fs-dropdown.up .fs-dropdown-list{top:auto;bottom:100%;margin-bottom:2px}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group{text-align:center;display:table}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group .button{display:table-cell}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group .button:not(.fs-dropdown-arrow-button){left:1px;width:100%}#plugin-information-footer>.button,#plugin-information-footer .fs-dropdown{position:relative;top:3px}#plugin-information-footer>.button.left,#plugin-information-footer .fs-dropdown.left{float:left}#plugin-information-footer>.right,#plugin-information-footer .fs-dropdown{float:right}@media screen and (max-width: 961px){#fs_addons .fs-cards-list .fs-card{height:265px}}
|
|
freemius/assets/css/admin/affiliation.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
|
1 |
+
#fs_affiliation_content_wrapper #messages{margin-top:25px}#fs_affiliation_content_wrapper h3{font-size:24px;padding:0;margin-left:0}#fs_affiliation_content_wrapper ul li{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;list-style-type:none}#fs_affiliation_content_wrapper ul li:before{content:"✓";margin-right:10px;font-weight:bold}#fs_affiliation_content_wrapper p:not(.description),#fs_affiliation_content_wrapper li,#fs_affiliation_content_wrapper label{font-size:16px !important;line-height:26px !important}#fs_affiliation_content_wrapper .button{margin-top:20px;margin-bottom:7px;line-height:35px;height:40px;font-size:16px}#fs_affiliation_content_wrapper .button#cancel_button{margin-right:5px}#fs_affiliation_content_wrapper form .input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form .input-container .input-label{font-weight:bold;display:block;width:100%}#fs_affiliation_content_wrapper form .input-container.input-container-text label,#fs_affiliation_content_wrapper form .input-container.input-container-text input,#fs_affiliation_content_wrapper form .input-container.input-container-text textarea{display:block}#fs_affiliation_content_wrapper form .input-container #add_domain,#fs_affiliation_content_wrapper form .input-container .remove-domain{text-decoration:none;display:inline-block;margin-top:3px}#fs_affiliation_content_wrapper form .input-container #add_domain:focus,#fs_affiliation_content_wrapper form .input-container .remove-domain:focus{box-shadow:none}#fs_affiliation_content_wrapper form .input-container #add_domain.disabled,#fs_affiliation_content_wrapper form .input-container .remove-domain.disabled{color:#aaa;cursor:default}#fs_affiliation_content_wrapper form #extra_domains_container .description{margin-top:0;position:relative;top:-4px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain{display:inline-block;margin-right:5px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain:last-of-type{margin-bottom:0}
|
freemius/assets/css/admin/clone-resolution.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
.fs-notice[data-id^=clone_resolution_options_notice]{padding:0;color:inherit !important}.fs-notice[data-id^=clone_resolution_options_notice] .fs-notice-body{padding:0;margin-bottom:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-notice-header{padding:5px 10px}.fs-notice[data-id^=clone_resolution_options_notice] ol{margin-top:0;margin-bottom:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-options-container{display:flex;flex-direction:row;padding:0 10px 10px}@media(max-width: 750px){.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-options-container{flex-direction:column}}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option{border:1px solid #ccc;padding:10px 10px 15px 10px;flex:auto;margin:5px}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option:first-child{margin-left:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option:last-child{margin-right:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option strong{font-size:1.2em;padding:2px;line-height:1.5em}.fs-notice[data-id^=clone_resolution_options_notice] a{text-decoration:none}.fs-notice[data-id^=clone_resolution_options_notice] .button{margin-right:10px}.rtl .fs-notice[data-id^=clone_resolution_options_notice] .button{margin-right:0;margin-left:10px}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-documentation-container{padding:0 10px 15px}.fs-notice[data-id=temporary_duplicate_notice] #fs_clone_resolution_error_message{border:1px solid #d3135a;background:#fee;color:#d3135a;padding:10px}.fs-notice[data-id=temporary_duplicate_notice] ol{margin-top:0}
|
freemius/assets/css/admin/common.css
CHANGED
@@ -1,2 +1 @@
|
|
1 |
-
.fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color
|
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}
|
1 |
+
.fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:#fff;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,.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,.3);box-shadow:0 2px 1px -1px rgba(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,.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,.1),inset 0 1px 3px 0 rgba(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,.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,.5);z-index:999;-moz-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:.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}body.fs-loading,body.fs-loading *{cursor:wait !important}#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}}.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,.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,.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,.3);box-shadow:0 2px 2px rgba(6,113,6,.3);opacity:.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:"↳";padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:"↲"}.fs-submenu-item.pricing.upgrade-mode{color:#adff2f}.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{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}
|
1 |
+
.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .dashicons{float:none !important}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:rgba(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,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(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,.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_connect{width:484px;margin:60px auto 20px auto}#fs_connect a{color:inherit}#fs_connect a:not(.button){text-decoration:underline}#fs_connect .fs-box-container{box-shadow:0 1px 2px rgba(0,0,0,.3);border-radius:3px;overflow:hidden;padding-top:40px;background:#f0f0f1}@media screen and (max-width: 483px){#fs_connect{width:auto;margin:30px 0 0 -10px}#fs_connect .fs-box-container{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}}#fs_connect .fs-content{background:#fff;padding:30px 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,.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 1px 0 rgba(0,0,0,.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content h2{line-height:1.5em}#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-content{padding-bottom:10px}#fs_connect.require-license-key .fs-actions{border-top:none}#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:#fff;border-width:1px 0;border-style:solid;border-color:#f1f1f1}#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:" ➜"}#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:#fff;-moz-transition:background .5s ease;-o-transition:background .5s ease;-ms-transition:background .5s ease;-webkit-transition:background .5s ease;transition:background .5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions>.fs-trigger{font-size:.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions>.fs-trigger .fs-arrow::after{content:"→";width:20px;display:inline-block}#fs_connect .fs-permissions.fs-open>.fs-trigger .fs-arrow::after{content:"↓" !important}#fs_connect .fs-permissions ul li{padding-left:0;padding-right:0}@media screen and (max-width: 483px){#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:inherit;text-decoration:underline}#fs_connect .fs-header{padding:0;line-height:0;height:0;position:relative}#fs_connect .fs-header .fs-site-icon,#fs_connect .fs-header .fs-connect-logo{position:absolute;top:-8px;border-radius:50%}#fs_connect .fs-header .fs-site-icon{left:152px}#fs_connect .fs-header .fs-connect-logo{right:152px}#fs_connect .fs-header .fs-site-icon,#fs_connect .fs-header img,#fs_connect .fs-header object{width:50px;height:50px;border-radius:50%}#fs_connect .fs-header .fs-plugin-icon{position:absolute;overflow:hidden;top:-23px;left:50%;margin-left:-44px;border-radius:50%;z-index:1}#fs_connect .fs-header .fs-plugin-icon,#fs_connect .fs-header .fs-plugin-icon img{width:80px;height:80px}#fs_connect .fs-header .dashicons-wordpress-alt{font-size:40px;background:#01749a;color:#fff;width:40px;height:40px;padding:5px;border-radius:50%}#fs_connect .fs-header .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-header .dashicons-plus.fs-first{left:28%}#fs_connect .fs-header .dashicons-plus.fs-second{left:65%}#fs_connect .fs-header .fs-plugin-icon,#fs_connect .fs-header .fs-connect-logo,#fs_connect .fs-header .fs-site-icon{border:1px solid #efefef;padding:3px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:.85em;padding:10px 5px}#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:20px;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_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{border-radius:3px}.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:" »"}.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-header .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-header .fs-connect-logo{right:auto;left:20px}.rtl #fs_connect .fs-permissions>.fs-trigger .fs-arrow::after{content:"←"}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(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:#fff;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:0;margin-bottom:20px}#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:.9em;margin-top:10px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .dashicons{float:none !important}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:rgba(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,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(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,.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-permissions .fs-permission.fs-disabled{color:#aaa}.fs-permissions .fs-permission.fs-disabled .fs-permission-description span{color:#aaa}.fs-permissions .fs-permission .fs-switch-feedback{position:absolute;right:15px;top:52px}.fs-permissions ul{height:0;overflow:hidden;margin:0}.fs-permissions ul li{padding:17px 15px;margin:0;position:relative}.fs-permissions ul li>i.dashicons{float:left;font-size:30px;width:30px;height:30px;padding:5px}.fs-permissions ul li .fs-switch{float:right}.fs-permissions ul li .fs-permission-description{margin-left:55px}.fs-permissions ul li .fs-permission-description span{font-size:14px;font-weight:500;color:#23282d}.fs-permissions ul li .fs-permission-description .fs-tooltip{font-size:13px;font-weight:bold}.fs-permissions ul li .fs-permission-description .fs-tooltip-trigger .dashicons{margin:-1px 2px 0 2px}.fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}.fs-permissions.fs-open{background:#fff}.fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 0 10px 0}.fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-right:10px}.fs-permissions .fs-switch-feedback.success{color:#71ae00}.rtl .fs-permissions .fs-switch-feedback{right:auto;left:15px}.rtl .fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-left:10px;margin-right:0}.rtl .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl .fs-permissions ul li .fs-switch{float:left}.rtl .fs-permissions ul li i.dashicons{float:right}
|
freemius/assets/css/admin/debug.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.fs-switch-label{font-size:20px;line-height:31px;margin:0 5px}#fs_log_book table{font-family:Consolas,Monaco,monospace;font-size:12px}#fs_log_book table th{color:#ccc}#fs_log_book table tr{background:#232525}#fs_log_book table tr.alternate{background:#2b2b2b}#fs_log_book table tr td.fs-col--logger{color:#5a7435}#fs_log_book table tr td.fs-col--type{color:#ffc861}#fs_log_book table tr td.fs-col--function{color:#a7b7b1;font-weight:bold}#fs_log_book table tr td.fs-col--message,#fs_log_book table tr td.fs-col--message a{color:#9a73ac !important}#fs_log_book table tr td.fs-col--file{color:#d07922}#fs_log_book table tr td.fs-col--timestamp{color:#6596be}
|
1 |
+
label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-switch-label{font-size:20px;line-height:31px;margin:0 5px}#fs_log_book table{font-family:Consolas,Monaco,monospace;font-size:12px}#fs_log_book table th{color:#ccc}#fs_log_book table tr{background:#232525}#fs_log_book table tr.alternate{background:#2b2b2b}#fs_log_book table tr td.fs-col--logger{color:#5a7435}#fs_log_book table tr td.fs-col--type{color:#ffc861}#fs_log_book table tr td.fs-col--function{color:#a7b7b1;font-weight:bold}#fs_log_book table tr td.fs-col--message,#fs_log_book table tr td.fs-col--message a{color:#9a73ac !important}#fs_log_book table tr td.fs-col--file{color:#d07922}#fs_log_book table tr td.fs-col--timestamp{color:#6596be}
|
freemius/assets/css/admin/dialog-boxes.css
CHANGED
@@ -1,2 +1 @@
|
|
1 |
-
.fs-modal{position:fixed;overflow:auto;height:100%;width:100%;top:0;z-index:100000;display:none;background:rgba(0,0,0,0.6)}.fs-modal .dashicons{vertical-align:middle}.fs-modal .fs-modal-dialog{background:transparent;position:absolute;left:50%;margin-left:-298px;padding-bottom:30px;top:-100%;z-index:100001;width:596px}@media (max-width: 650px){.fs-modal .fs-modal-dialog{margin-left:-50%;box-sizing:border-box;padding-left:10px;padding-right:10px;width:100%}.fs-modal .fs-modal-dialog .fs-modal-panel>h3>strong{font-size:1.3em}}.fs-modal.active{display:block}.fs-modal.active:before{display:block}.fs-modal.active .fs-modal-dialog{top:10%}.fs-modal.fs-success .fs-modal-header{border-bottom-color:#46b450}.fs-modal.fs-success .fs-modal-body{background-color:#f7fff7}.fs-modal.fs-warn .fs-modal-header{border-bottom-color:#ffb900}.fs-modal.fs-warn .fs-modal-body{background-color:#fff8e5}.fs-modal.fs-error .fs-modal-header{border-bottom-color:#dc3232}.fs-modal.fs-error .fs-modal-body{background-color:#ffeaea}.fs-modal .fs-modal-body,.fs-modal .fs-modal-footer{border:0;background:#fefefe;padding:20px}.fs-modal .fs-modal-header{border-bottom:#eeeeee solid 1px;background:#fbfbfb;padding:15px 20px;position:relative;margin-bottom:-10px}.fs-modal .fs-modal-header h4{margin:0;padding:0;text-transform:uppercase;font-size:1.2em;font-weight:bold;color:#cacaca;text-shadow:1px 1px 1px #fff;letter-spacing:0.6px;-webkit-font-smoothing:antialiased}.fs-modal .fs-modal-header .fs-close{position:absolute;right:10px;top:12px;cursor:pointer;color:#bbb;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;padding:3px;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.fs-modal .fs-modal-header .fs-close:hover{color:#fff;background:#aaa}.fs-modal .fs-modal-header .fs-close .dashicons,.fs-modal .fs-modal-header .fs-close:hover .dashicons{text-decoration:none}.fs-modal .fs-modal-body{border-bottom:0}.fs-modal .fs-modal-body p{font-size:14px}.fs-modal .fs-modal-body h2{font-size:20px;line-height:1.5em}.fs-modal .fs-modal-body>div{margin-top:10px}.fs-modal .fs-modal-body>div h2{font-weight:bold;font-size:20px;margin-top:0}.fs-modal .fs-modal-footer{border-top:#eeeeee solid 1px;text-align:right}.fs-modal .fs-modal-footer>.button{margin:0 7px}.fs-modal .fs-modal-footer>.button:first-child{margin:0}.fs-modal .fs-modal-panel>.notice.inline{margin:0;display:none}.fs-modal .fs-modal-panel:not(.active){display:none}.rtl .fs-modal .fs-modal-header .fs-close{right:auto;left:20px}body.has-fs-modal{overflow:hidden}.fs-modal.fs-modal-deactivation-feedback .reason-input,.fs-modal.fs-modal-deactivation-feedback .internal-message{margin:3px 0 3px 22px}.fs-modal.fs-modal-deactivation-feedback .reason-input input,.fs-modal.fs-modal-deactivation-feedback .reason-input textarea,.fs-modal.fs-modal-deactivation-feedback .internal-message input,.fs-modal.fs-modal-deactivation-feedback .internal-message textarea{width:100%}.fs-modal.fs-modal-deactivation-feedback li.reason.has-internal-message .internal-message{border:1px solid #ccc;padding:7px;display:none}@media (max-width: 650px){.fs-modal.fs-modal-deactivation-feedback li.reason li.reason{margin-bottom:10px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .reason-input,.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .internal-message{margin-left:29px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label{display:table}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label>span{display:table-cell;font-size:1.3em}}.fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label{float:left}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel{margin-top:0 !important}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel h3{margin-top:0;line-height:1.5em}#the-list .deactivate>.fs-slug{display:none}.fs-modal.fs-modal-subscription-cancellation .fs-price-increase-warning{color:red;font-weight:bold;padding:0 25px;margin-bottom:0}.fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label input{float:left;top:5px;position:relative}.rtl .fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label input{float:right}.fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label span{display:block;margin-left:24px}.rtl .fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label span{margin-left:0;margin-right:24px}.fs-modal.fs-modal-license-activation .fs-modal-body input.fs-license-key{width:100%}.fs-license-options-container table,.fs-license-options-container table select,.fs-license-options-container table .fs-available-license-key{width:100%}.fs-license-options-container table td:first-child{width:1%}.fs-license-options-container table .fs-other-license-key-container label{position:relative;top:6px;float:left;margin-right:5px}.fs-license-options-container table .fs-other-license-key-container div{overflow:hidden;width:auto;height:30px;display:block;top:2px;position:relative}.fs-license-options-container table .fs-other-license-key-container div input{margin:0}.fs-sites-list-container td{cursor:pointer}.fs-modal.fs-modal-user-change .fs-modal-body input#fs_other_email_address{width:100%}.fs-user-change-options-container table{width:100%;border-collapse:collapse}.fs-user-change-options-container table tr{display:block;margin-bottom:2px}.fs-user-change-options-container table .fs-email-address-container td{display:inline-block}.fs-user-change-options-container table .fs-email-address-container input[type="radio"]{margin-bottom:0;margin-top:0}.fs-user-change-options-container table .fs-other-email-address-container{width:100%}.fs-user-change-options-container table .fs-other-email-address-container>div{display:table;width:100%}.fs-user-change-options-container table .fs-other-email-address-container>div label,.fs-user-change-options-container table .fs-other-email-address-container>div>div{display:table-cell}.fs-user-change-options-container table .fs-other-email-address-container>div label{width:1%;padding-left:3px;padding-right:3px}.fs-user-change-options-container table .fs-other-email-address-container>div>div{width:auto}.fs-user-change-options-container table .fs-other-email-address-container>div>div input{width:100%}.fs-modal.fs-modal-developer-license-debug-mode .fs-modal-body input.fs-license-or-user-key{width:100%}.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-modal.fs-modal-license-key-resend .email-address-container{overflow:hidden;padding-right:2px}.fs-modal.fs-modal-license-key-resend.fs-freemium input.email-address{width:300px}.fs-modal.fs-modal-license-key-resend.fs-freemium label{display:block;margin-bottom:10px}.fs-modal.fs-modal-license-key-resend.fs-premium input.email-address{width:100%}.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{float:right;margin-left:7px}@media (max-width: 650px){.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{margin-top:2px}}
|
2 |
-
.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .input-container>.email-address-container{padding-left:2px;padding-right:0}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .button-container{float:left;margin-right:7px;margin-left:0}a.show-license-resend-modal{margin-top:4px;display:inline-block}.fs-ajax-loader{position:relative;width:170px;height:20px;margin:auto}.fs-ajax-loader .fs-ajax-loader-bar{position:absolute;top:0;background-color:#0074a3;width:20px;height:20px;-webkit-animation-name:bounce_ajaxLoader;-moz-animation-name:bounce_ajaxLoader;-ms-animation-name:bounce_ajaxLoader;-o-animation-name:bounce_ajaxLoader;animation-name:bounce_ajaxLoader;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s;animation-duration:1.5s;animation-iteration-count:infinite;-o-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-webkit-animation-direction:normal;-moz-animation-direction:normal;-ms-animation-direction:normal;-o-animation-direction:normal;animation-direction:normal;-moz-transform:0.3;-o-transform:0.3;-ms-transform:0.3;-webkit-transform:0.3;transform:0.3}.fs-ajax-loader .fs-ajax-loader-bar-1{left:0px;animation-delay:0.6s;-o-animation-delay:0.6s;-ms-animation-delay:0.6s;-webkit-animation-delay:0.6s;-moz-animation-delay:0.6s}.fs-ajax-loader .fs-ajax-loader-bar-2{left:19px;animation-delay:0.75s;-o-animation-delay:0.75s;-ms-animation-delay:0.75s;-webkit-animation-delay:0.75s;-moz-animation-delay:0.75s}.fs-ajax-loader .fs-ajax-loader-bar-3{left:38px;animation-delay:0.9s;-o-animation-delay:0.9s;-ms-animation-delay:0.9s;-webkit-animation-delay:0.9s;-moz-animation-delay:0.9s}.fs-ajax-loader .fs-ajax-loader-bar-4{left:57px;animation-delay:1.05s;-o-animation-delay:1.05s;-ms-animation-delay:1.05s;-webkit-animation-delay:1.05s;-moz-animation-delay:1.05s}.fs-ajax-loader .fs-ajax-loader-bar-5{left:76px;animation-delay:1.2s;-o-animation-delay:1.2s;-ms-animation-delay:1.2s;-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s}.fs-ajax-loader .fs-ajax-loader-bar-6{left:95px;animation-delay:1.35s;-o-animation-delay:1.35s;-ms-animation-delay:1.35s;-webkit-animation-delay:1.35s;-moz-animation-delay:1.35s}.fs-ajax-loader .fs-ajax-loader-bar-7{left:114px;animation-delay:1.5s;-o-animation-delay:1.5s;-ms-animation-delay:1.5s;-webkit-animation-delay:1.5s;-moz-animation-delay:1.5s}.fs-ajax-loader .fs-ajax-loader-bar-8{left:133px;animation-delay:1.65s;-o-animation-delay:1.65s;-ms-animation-delay:1.65s;-webkit-animation-delay:1.65s;-moz-animation-delay:1.65s}@-moz-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-ms-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-o-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-webkit-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}.fs-modal-auto-install #request-filesystem-credentials-form h2,.fs-modal-auto-install #request-filesystem-credentials-form .request-filesystem-credentials-action-buttons{display:none}.fs-modal-auto-install #request-filesystem-credentials-form input[type=password],.fs-modal-auto-install #request-filesystem-credentials-form input[type=email],.fs-modal-auto-install #request-filesystem-credentials-form input[type=text]{-webkit-appearance:none;padding:10px 10px 5px 10px;width:300px;max-width:100%}.fs-modal-auto-install #request-filesystem-credentials-form>div,.fs-modal-auto-install #request-filesystem-credentials-form label,.fs-modal-auto-install #request-filesystem-credentials-form fieldset{width:300px;max-width:100%;margin:0 auto;display:block}.button-primary.warn{box-shadow:0 1px 0 #d2593c;text-shadow:0 -1px 1px #d2593c,1px 0 1px #d2593c,0 1px 1px #d2593c,-1px 0 1px #d2593c;background:#f56a48;border-color:#ec6544 #d2593c #d2593c}.button-primary.warn:hover{background:#fd6d4a;border-color:#d2593c}.button-primary.warn:focus{box-shadow:0 1px 0 #dd6041,0 0 2px 1px #e4a796}.button-primary.warn:active{background:#dd6041;border-color:#d2593c;box-shadow:inset 0 2px 0 #d2593c}.button-primary.warn.disabled{color:#f5b3a1 !important;background:#e76444 !important;border-color:#d85e40 !important;text-shadow:0 -1px 0 rgba(0,0,0,0.1) !important}
|
1 |
+
.fs-modal{position:fixed;overflow:auto;height:100%;width:100%;top:0;z-index:100000;display:none;background:rgba(0,0,0,.6)}@media(min-width: 961px){.fs-modal{padding-left:160px}.rtl .fs-modal{padding-left:0;padding-right:160px}}.fs-modal .dashicons{vertical-align:middle}.fs-modal .fs-modal-dialog{background:transparent;position:absolute;left:50%;margin-left:-298px;padding-bottom:30px;top:-100%;z-index:100001;width:596px}@media(max-width: 650px){.fs-modal .fs-modal-dialog{margin-left:-50%;box-sizing:border-box;padding-left:10px;padding-right:10px;width:100%}.fs-modal .fs-modal-dialog .fs-modal-panel>h3>strong{font-size:1.3em}}.fs-modal.active{display:block}.fs-modal.active:before{display:block}.fs-modal.active .fs-modal-dialog{top:10%}.fs-modal.fs-success .fs-modal-header{border-bottom-color:#46b450}.fs-modal.fs-success .fs-modal-body{background-color:#f7fff7}.fs-modal.fs-warn .fs-modal-header{border-bottom-color:#ffb900}.fs-modal.fs-warn .fs-modal-body{background-color:#fff8e5}.fs-modal.fs-error .fs-modal-header{border-bottom-color:#dc3232}.fs-modal.fs-error .fs-modal-body{background-color:#ffeaea}.fs-modal .fs-modal-body,.fs-modal .fs-modal-footer{border:0;background:#fefefe;padding:20px}.fs-modal .fs-modal-header{border-bottom:#eee solid 1px;background:#fbfbfb;padding:15px 20px;position:relative;margin-bottom:-10px}.fs-modal .fs-modal-header h4{margin:0;padding:0;text-transform:uppercase;font-size:1.2em;font-weight:bold;color:#cacaca;text-shadow:1px 1px 1px #fff;letter-spacing:.6px;-webkit-font-smoothing:antialiased}.fs-modal .fs-modal-header .fs-close{position:absolute;right:10px;top:12px;cursor:pointer;color:#bbb;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;padding:3px;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.fs-modal .fs-modal-header .fs-close:hover{color:#fff;background:#aaa}.fs-modal .fs-modal-header .fs-close .dashicons,.fs-modal .fs-modal-header .fs-close:hover .dashicons{text-decoration:none}.fs-modal .fs-modal-body{border-bottom:0}.fs-modal .fs-modal-body p{font-size:14px}.fs-modal .fs-modal-body h2{font-size:20px;line-height:1.5em}.fs-modal .fs-modal-body>div{margin-top:10px}.fs-modal .fs-modal-body>div h2{font-weight:bold;font-size:20px;margin-top:0}.fs-modal .fs-modal-footer{border-top:#eee solid 1px;text-align:right}.fs-modal .fs-modal-footer>.button{margin:0 7px}.fs-modal .fs-modal-footer>.button:last-of-type{margin:0}.fs-modal .fs-modal-panel>.notice.inline{margin:0;display:none}.fs-modal .fs-modal-panel:not(.active){display:none}.rtl .fs-modal .fs-modal-header .fs-close{right:auto;left:20px}.rtl .fs-modal .fs-modal-footer{text-align:left}body.has-fs-modal{overflow:hidden}.fs-modal.fs-modal-deactivation-feedback .reason-input,.fs-modal.fs-modal-deactivation-feedback .internal-message{margin:3px 0 3px 22px}.fs-modal.fs-modal-deactivation-feedback .reason-input input,.fs-modal.fs-modal-deactivation-feedback .reason-input textarea,.fs-modal.fs-modal-deactivation-feedback .internal-message input,.fs-modal.fs-modal-deactivation-feedback .internal-message textarea{width:100%}.fs-modal.fs-modal-deactivation-feedback li.reason.has-internal-message .internal-message{border:1px solid #ccc;padding:7px;display:none}@media(max-width: 650px){.fs-modal.fs-modal-deactivation-feedback li.reason li.reason{margin-bottom:10px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .reason-input,.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .internal-message{margin-left:29px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label{display:table}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label>span{display:table-cell;font-size:1.3em}}.fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label,.fs-modal.fs-modal-deactivation-feedback .feedback-from-snooze-label{float:left;line-height:30px}.rtl .fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label,.rtl .fs-modal.fs-modal-deactivation-feedback .feedback-from-snooze-label{float:right}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel{margin-top:0 !important}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel h3{margin-top:0;line-height:1.5em}#the-list .deactivate>.fs-slug{display:none}.fs-modal.fs-modal-subscription-cancellation .fs-price-increase-warning{color:red;font-weight:bold;padding:0 25px;margin-bottom:0}.fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label input{float:left;top:5px;position:relative}.rtl .fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label input{float:right}.fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label span{display:block;margin-left:24px}.rtl .fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label span{margin-left:0;margin-right:24px}.fs-modal.fs-modal-license-activation .fs-modal-body input.fs-license-key{width:100%}.fs-license-options-container table,.fs-license-options-container table select,.fs-license-options-container table .fs-available-license-key{width:100%}.fs-license-options-container table td:first-child{width:1%}.fs-license-options-container table .fs-other-license-key-container label{position:relative;top:6px;float:left;margin-right:5px}.fs-license-options-container table .fs-other-license-key-container div{overflow:hidden;width:auto;height:30px;display:block;top:2px;position:relative}.fs-license-options-container table .fs-other-license-key-container div input{margin:0}.fs-sites-list-container td{cursor:pointer}.fs-modal.fs-modal-user-change .fs-modal-body input#fs_other_email_address{width:100%}.fs-user-change-options-container table{width:100%;border-collapse:collapse}.fs-user-change-options-container table tr{display:block;margin-bottom:2px}.fs-user-change-options-container table .fs-email-address-container td{display:inline-block}.fs-user-change-options-container table .fs-email-address-container input[type=radio]{margin-bottom:0;margin-top:0}.fs-user-change-options-container table .fs-other-email-address-container{width:100%}.fs-user-change-options-container table .fs-other-email-address-container>div{display:table;width:100%}.fs-user-change-options-container table .fs-other-email-address-container>div label,.fs-user-change-options-container table .fs-other-email-address-container>div>div{display:table-cell}.fs-user-change-options-container table .fs-other-email-address-container>div label{width:1%;padding-left:3px;padding-right:3px}.fs-user-change-options-container table .fs-other-email-address-container>div>div{width:auto}.fs-user-change-options-container table .fs-other-email-address-container>div>div input{width:100%}.fs-modal.fs-modal-developer-license-debug-mode .fs-modal-body input.fs-license-or-user-key{width:100%}.fs-multisite-options-container{margin-top:20px;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-modal.fs-modal-license-key-resend .email-address-container{overflow:hidden;padding-right:2px}.fs-modal.fs-modal-license-key-resend.fs-freemium input.email-address{width:300px}.fs-modal.fs-modal-license-key-resend.fs-freemium label{display:block;margin-bottom:10px}.fs-modal.fs-modal-license-key-resend.fs-premium input.email-address{width:100%}.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{float:right;margin-left:7px}@media(max-width: 650px){.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{margin-top:2px}}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .input-container>.email-address-container{padding-left:2px;padding-right:0}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .button-container{float:left;margin-right:7px;margin-left:0}a.show-license-resend-modal{margin-top:4px;display:inline-block}.fs-modal.fs-modal-email-address-update .fs-modal-body input[type=text]{width:100%}.fs-modal.fs-modal-email-address-update p{margin-bottom:0}.fs-modal.fs-modal-email-address-update ul{margin:1em .5em}.fs-modal.fs-modal-email-address-update ul li label span{float:left;margin-top:0}.fs-modal.fs-modal-email-address-update ul li label span:last-child{display:block;float:none;margin-left:20px}.fs-ajax-loader{position:relative;width:170px;height:20px;margin:auto}.fs-ajax-loader .fs-ajax-loader-bar{position:absolute;top:0;background-color:#0074a3;width:20px;height:20px;-webkit-animation-name:bounce_ajaxLoader;-moz-animation-name:bounce_ajaxLoader;-ms-animation-name:bounce_ajaxLoader;-o-animation-name:bounce_ajaxLoader;animation-name:bounce_ajaxLoader;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s;animation-duration:1.5s;animation-iteration-count:infinite;-o-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-webkit-animation-direction:normal;-moz-animation-direction:normal;-ms-animation-direction:normal;-o-animation-direction:normal;animation-direction:normal;-moz-transform:.3;-o-transform:.3;-ms-transform:.3;-webkit-transform:.3;transform:.3}.fs-ajax-loader .fs-ajax-loader-bar-1{left:0px;animation-delay:0.6s;-o-animation-delay:0.6s;-ms-animation-delay:0.6s;-webkit-animation-delay:0.6s;-moz-animation-delay:0.6s}.fs-ajax-loader .fs-ajax-loader-bar-2{left:19px;animation-delay:0.75s;-o-animation-delay:0.75s;-ms-animation-delay:0.75s;-webkit-animation-delay:0.75s;-moz-animation-delay:0.75s}.fs-ajax-loader .fs-ajax-loader-bar-3{left:38px;animation-delay:0.9s;-o-animation-delay:0.9s;-ms-animation-delay:0.9s;-webkit-animation-delay:0.9s;-moz-animation-delay:0.9s}.fs-ajax-loader .fs-ajax-loader-bar-4{left:57px;animation-delay:1.05s;-o-animation-delay:1.05s;-ms-animation-delay:1.05s;-webkit-animation-delay:1.05s;-moz-animation-delay:1.05s}.fs-ajax-loader .fs-ajax-loader-bar-5{left:76px;animation-delay:1.2s;-o-animation-delay:1.2s;-ms-animation-delay:1.2s;-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s}.fs-ajax-loader .fs-ajax-loader-bar-6{left:95px;animation-delay:1.35s;-o-animation-delay:1.35s;-ms-animation-delay:1.35s;-webkit-animation-delay:1.35s;-moz-animation-delay:1.35s}.fs-ajax-loader .fs-ajax-loader-bar-7{left:114px;animation-delay:1.5s;-o-animation-delay:1.5s;-ms-animation-delay:1.5s;-webkit-animation-delay:1.5s;-moz-animation-delay:1.5s}.fs-ajax-loader .fs-ajax-loader-bar-8{left:133px;animation-delay:1.65s;-o-animation-delay:1.65s;-ms-animation-delay:1.65s;-webkit-animation-delay:1.65s;-moz-animation-delay:1.65s}@-moz-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-ms-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-o-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-webkit-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}.fs-modal-auto-install #request-filesystem-credentials-form h2,.fs-modal-auto-install #request-filesystem-credentials-form .request-filesystem-credentials-action-buttons{display:none}.fs-modal-auto-install #request-filesystem-credentials-form input[type=password],.fs-modal-auto-install #request-filesystem-credentials-form input[type=email],.fs-modal-auto-install #request-filesystem-credentials-form input[type=text]{-webkit-appearance:none;padding:10px 10px 5px 10px;width:300px;max-width:100%}.fs-modal-auto-install #request-filesystem-credentials-form>div,.fs-modal-auto-install #request-filesystem-credentials-form label,.fs-modal-auto-install #request-filesystem-credentials-form fieldset{width:300px;max-width:100%;margin:0 auto;display:block}.button-primary.warn{box-shadow:0 1px 0 #d2593c;text-shadow:0 -1px 1px #d2593c,1px 0 1px #d2593c,0 1px 1px #d2593c,-1px 0 1px #d2593c;background:#f56a48;border-color:#ec6544 #d2593c #d2593c}.button-primary.warn:hover{background:#fd6d4a;border-color:#d2593c}.button-primary.warn:focus{box-shadow:0 1px 0 #dd6041,0 0 2px 1px #e4a796}.button-primary.warn:active{background:#dd6041;border-color:#d2593c;box-shadow:inset 0 2px 0 #d2593c}.button-primary.warn.disabled{color:#f5b3a1 !important;background:#e76444 !important;border-color:#d85e40 !important;text-shadow:0 -1px 0 rgba(0,0,0,.1) !important}
|
|
freemius/assets/css/admin/gdpr-optin-notice.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.fs-notice[data-id^=
|
1 |
+
.fs-notice[data-id^=gdpr_optin_actions] .underlined{text-decoration:underline}.fs-notice[data-id^=gdpr_optin_actions] ul .button,.fs-notice[data-id^=gdpr_optin_actions] ul .action-description{vertical-align:middle}.fs-notice[data-id^=gdpr_optin_actions] ul .action-description{display:inline-block;margin-left:3px}
|
freemius/assets/css/admin/optout.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .dashicons{float:none !important}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:rgba(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,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(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,.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-permissions .fs-permission.fs-disabled{color:#aaa}.fs-permissions .fs-permission.fs-disabled .fs-permission-description span{color:#aaa}.fs-permissions .fs-permission .fs-switch-feedback{position:absolute;right:15px;top:52px}.fs-permissions ul{height:0;overflow:hidden;margin:0}.fs-permissions ul li{padding:17px 15px;margin:0;position:relative}.fs-permissions ul li>i.dashicons{float:left;font-size:30px;width:30px;height:30px;padding:5px}.fs-permissions ul li .fs-switch{float:right}.fs-permissions ul li .fs-permission-description{margin-left:55px}.fs-permissions ul li .fs-permission-description span{font-size:14px;font-weight:500;color:#23282d}.fs-permissions ul li .fs-permission-description .fs-tooltip{font-size:13px;font-weight:bold}.fs-permissions ul li .fs-permission-description .fs-tooltip-trigger .dashicons{margin:-1px 2px 0 2px}.fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}.fs-permissions.fs-open{background:#fff}.fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 0 10px 0}.fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-right:10px}.fs-permissions .fs-switch-feedback.success{color:#71ae00}.rtl .fs-permissions .fs-switch-feedback{right:auto;left:15px}.rtl .fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-left:10px;margin-right:0}.rtl .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl .fs-permissions ul li .fs-switch{float:left}.rtl .fs-permissions ul li i.dashicons{float:right}.fs-modal-opt-out .fs-modal-footer .fs-opt-out-button{line-height:30px;margin-right:10px}.fs-modal-opt-out .fs-permissions{margin-top:0 !important}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header .fs-group-opt-out-button{float:right;line-height:1.1em}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header .fs-switch-feedback{float:right;line-height:1.1em;margin-right:10px}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header .fs-switch-feedback .fs-ajax-spinner{margin:-2px 0 0}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header-title{font-size:1.1em;font-weight:600;text-transform:uppercase;display:block;line-height:1.1em;margin:.5em 0}.fs-modal-opt-out .fs-permissions .fs-permissions-section--desc{margin-top:0}.fs-modal-opt-out .fs-permissions hr{border:0;border-top:#eee solid 1px;margin:25px 0 20px 0}.fs-modal-opt-out .fs-permissions ul{border:1px solid #c3c4c7;border-radius:3px;margin:10px 0 0 0;box-shadow:0 1px 1px rgba(0,0,0,.04)}.fs-modal-opt-out .fs-permissions ul li{border-bottom:1px solid #d7dde1;border-left:4px solid #72aee6}.rtl .fs-modal-opt-out .fs-permissions ul li{border-left:none;border-right:4px solid #72aee6}.fs-modal-opt-out .fs-permissions ul li.fs-disabled{border-left-color:rgba(114,174,230,0)}.fs-modal-opt-out .fs-permissions ul li:last-child{border-bottom:none}
|
freemius/assets/css/customizer.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
#fs_customizer_upsell .fs-customizer-plan{padding:10px 20px 20px 20px;border-radius:3px;background:#fff}#fs_customizer_upsell .fs-customizer-plan h2{position:relative;margin:0;line-height:2em;text-transform:uppercase}#fs_customizer_upsell .fs-customizer-plan h2 .button-link{top:-2px}#fs_customizer_upsell .fs-feature{position:relative}#fs_customizer_upsell .dashicons-yes{color:#0085ba;font-size:2em;vertical-align:bottom;margin-left:-7px;margin-right:10px}.rtl #fs_customizer_upsell .dashicons-yes{margin-left:10px;margin-right:-7px}#fs_customizer_upsell .dashicons-editor-help{color:#bbb;cursor:help}#fs_customizer_upsell .dashicons-editor-help .fs-feature-desc{opacity:0;visibility:hidden;-moz-transition:opacity
|
1 |
+
#fs_customizer_upsell .fs-customizer-plan{padding:10px 20px 20px 20px;border-radius:3px;background:#fff}#fs_customizer_upsell .fs-customizer-plan h2{position:relative;margin:0;line-height:2em;text-transform:uppercase}#fs_customizer_upsell .fs-customizer-plan h2 .button-link{top:-2px}#fs_customizer_upsell .fs-feature{position:relative}#fs_customizer_upsell .dashicons-yes{color:#0085ba;font-size:2em;vertical-align:bottom;margin-left:-7px;margin-right:10px}.rtl #fs_customizer_upsell .dashicons-yes{margin-left:10px;margin-right:-7px}#fs_customizer_upsell .dashicons-editor-help{color:#bbb;cursor:help}#fs_customizer_upsell .dashicons-editor-help .fs-feature-desc{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:#000;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,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2);line-height:1.3em;font-weight:bold;text-align:left}.rtl #fs_customizer_upsell .dashicons-editor-help .fs-feature-desc{text-align:right}#fs_customizer_upsell .dashicons-editor-help .fs-feature-desc::after{content:" ";display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:#000 transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl #fs_customizer_upsell .dashicons-editor-help .fs-feature-desc::after{right:21px;left:auto}#fs_customizer_upsell .dashicons-editor-help:hover .fs-feature-desc{visibility:visible;opacity:1}#fs_customizer_upsell .button-primary{display:block;text-align:center;margin-top:10px}#fs_customizer_support{display:block !important}#fs_customizer_support .button{float:right}#fs_customizer_support .button-group{width:100%;display:block;margin-top:10px}#fs_customizer_support .button-group .button{float:none;width:50%;text-align:center}#customize-theme-controls #accordion-section-freemius_upsell{border-top:1px solid #0085ba !important;border-bottom:1px solid #0085ba !important}#customize-theme-controls #accordion-section-freemius_upsell h3.accordion-section-title{color:#fff;background-color:#0085ba;border-left:4px solid #0085ba;transition:.15s background-color ease-in-out,.15s border-color ease-in-out;outline:none;border-bottom:none !important}#customize-theme-controls #accordion-section-freemius_upsell h3.accordion-section-title:hover{background-color:#008ec2;border-left-color:#0073aa}#customize-theme-controls #accordion-section-freemius_upsell h3.accordion-section-title:after{color:#fff}#customize-theme-controls #accordion-section-freemius_upsell .rtl h3.accordion-section-title{border-left:none;border-right:4px solid #0085ba}#customize-theme-controls #accordion-section-freemius_upsell .rtl h3.accordion-section-title:hover{border-right-color:#0073aa}
|
freemius/config.php
CHANGED
@@ -354,7 +354,7 @@
|
|
354 |
is_multisite() &&
|
355 |
( is_network_admin() ||
|
356 |
( ( defined( 'DOING_AJAX' ) && DOING_AJAX &&
|
357 |
-
( isset( $_REQUEST['_fs_network_admin'] ) /*||
|
358 |
( ! empty( $_REQUEST['action'] ) && 'delete-plugin' === $_REQUEST['action'] )*/ )
|
359 |
) ||
|
360 |
// Plugin uninstall.
|
@@ -385,7 +385,7 @@
|
|
385 |
|
386 |
if ( ! defined( 'WP_FS__DEMO_MODE' ) ) {
|
387 |
define( 'WP_FS__DEMO_MODE', false );
|
388 |
-
}
|
389 |
-
if ( ! defined( 'FS_SDK__SSLVERIFY' ) ) {
|
390 |
-
define( 'FS_SDK__SSLVERIFY', false );
|
391 |
-
}
|
354 |
is_multisite() &&
|
355 |
( is_network_admin() ||
|
356 |
( ( defined( 'DOING_AJAX' ) && DOING_AJAX &&
|
357 |
+
( isset( $_REQUEST['_fs_network_admin'] ) && 'true' === $_REQUEST['_fs_network_admin'] /*||
|
358 |
( ! empty( $_REQUEST['action'] ) && 'delete-plugin' === $_REQUEST['action'] )*/ )
|
359 |
) ||
|
360 |
// Plugin uninstall.
|
385 |
|
386 |
if ( ! defined( 'WP_FS__DEMO_MODE' ) ) {
|
387 |
define( 'WP_FS__DEMO_MODE', false );
|
388 |
+
}
|
389 |
+
if ( ! defined( 'FS_SDK__SSLVERIFY' ) ) {
|
390 |
+
define( 'FS_SDK__SSLVERIFY', false );
|
391 |
+
}
|
freemius/includes/class-freemius-abstract.php
CHANGED
@@ -37,9 +37,12 @@
|
|
37 |
* `$fs->is_registered() && $fs->is_tracking_allowed()`
|
38 |
*
|
39 |
* @since 1.0.1
|
|
|
|
|
|
|
40 |
* @return bool
|
41 |
*/
|
42 |
-
abstract function is_registered();
|
43 |
|
44 |
/**
|
45 |
* Check if the user skipped connecting the account with Freemius.
|
@@ -61,68 +64,6 @@
|
|
61 |
|
62 |
#endregion
|
63 |
|
64 |
-
#----------------------------------------------------------------------------------
|
65 |
-
#region Usage Tracking
|
66 |
-
#----------------------------------------------------------------------------------
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Returns TRUE if the user opted-in and didn't disconnect (opt-out).
|
70 |
-
*
|
71 |
-
* @author Leo Fajardo (@leorw)
|
72 |
-
* @since 1.2.1.5
|
73 |
-
*
|
74 |
-
* @return bool
|
75 |
-
*/
|
76 |
-
abstract function is_tracking_allowed();
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Returns TRUE if the user never opted-in or manually opted-out.
|
80 |
-
*
|
81 |
-
* @author Vova Feldman (@svovaf)
|
82 |
-
* @since 1.2.1.5
|
83 |
-
*
|
84 |
-
* @return bool
|
85 |
-
*/
|
86 |
-
function is_tracking_prohibited() {
|
87 |
-
return ! $this->is_registered() || ! $this->is_tracking_allowed();
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Opt-out from usage tracking.
|
92 |
-
*
|
93 |
-
* Note: This will not delete the account information but will stop all tracking.
|
94 |
-
*
|
95 |
-
* Returns:
|
96 |
-
* 1. FALSE - If the user never opted-in.
|
97 |
-
* 2. TRUE - If successfully opted-out.
|
98 |
-
* 3. object - API Result on failure.
|
99 |
-
*
|
100 |
-
* @author Leo Fajardo (@leorw)
|
101 |
-
* @since 1.2.1.5
|
102 |
-
*
|
103 |
-
* @return bool|object
|
104 |
-
*/
|
105 |
-
abstract function stop_tracking();
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Opt-in back into usage tracking.
|
109 |
-
*
|
110 |
-
* Note: This will only work if the user opted-in previously.
|
111 |
-
*
|
112 |
-
* Returns:
|
113 |
-
* 1. FALSE - If the user never opted-in.
|
114 |
-
* 2. TRUE - If successfully opted-in back to usage tracking.
|
115 |
-
* 3. object - API result on failure.
|
116 |
-
*
|
117 |
-
* @author Leo Fajardo (@leorw)
|
118 |
-
* @since 1.2.1.5
|
119 |
-
*
|
120 |
-
* @return bool|object
|
121 |
-
*/
|
122 |
-
abstract function allow_tracking();
|
123 |
-
|
124 |
-
#endregion
|
125 |
-
|
126 |
#----------------------------------------------------------------------------------
|
127 |
#region Module Type
|
128 |
#----------------------------------------------------------------------------------
|
37 |
* `$fs->is_registered() && $fs->is_tracking_allowed()`
|
38 |
*
|
39 |
* @since 1.0.1
|
40 |
+
*
|
41 |
+
* @param bool $ignore_anonymous_state Since 2.5.1
|
42 |
+
*
|
43 |
* @return bool
|
44 |
*/
|
45 |
+
abstract function is_registered( $ignore_anonymous_state = false );
|
46 |
|
47 |
/**
|
48 |
* Check if the user skipped connecting the account with Freemius.
|
64 |
|
65 |
#endregion
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
#----------------------------------------------------------------------------------
|
68 |
#region Module Type
|
69 |
#----------------------------------------------------------------------------------
|
freemius/includes/class-freemius.php
CHANGED
@@ -377,6 +377,8 @@
|
|
377 |
const REASON_DIDNT_WORK_AS_EXPECTED = 14;
|
378 |
const REASON_TEMPORARY_DEACTIVATION = 15;
|
379 |
|
|
|
|
|
380 |
/**
|
381 |
* @author Leo Fajardo (@leorw)
|
382 |
* @since 2.3.1
|
@@ -392,7 +394,8 @@
|
|
392 |
*/
|
393 |
private $_pricing_js_path = null;
|
394 |
|
395 |
-
|
|
|
396 |
|
397 |
/* Ctor
|
398 |
------------------------------------------------------------------------------------------------------------------*/
|
@@ -408,8 +411,10 @@
|
|
408 |
* @param bool $is_init Since 1.2.1 Is initiation sequence.
|
409 |
*/
|
410 |
private function __construct( $module_id, $slug = false, $is_init = false ) {
|
|
|
|
|
411 |
if ( $is_init && is_numeric( $module_id ) && is_string( $slug ) ) {
|
412 |
-
$this->store_id_slug_type_path_map( $module_id, $slug );
|
413 |
}
|
414 |
|
415 |
$this->_module_id = $module_id;
|
@@ -424,7 +429,7 @@
|
|
424 |
|
425 |
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->get_unique_affix(), WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
|
426 |
|
427 |
-
$this->_plugin_main_file_path = $this->_find_caller_plugin_file( $is_init );
|
428 |
$this->_plugin_dir_path = plugin_dir_path( $this->_plugin_main_file_path );
|
429 |
$this->_plugin_basename = $this->get_plugin_basename();
|
430 |
$this->_free_plugin_basename = str_replace( '-premium/', '/', $this->_plugin_basename );
|
@@ -519,7 +524,10 @@
|
|
519 |
* @author Leo Fajardo (@leorw)
|
520 |
* @since 1.2.2
|
521 |
*/
|
522 |
-
( is_object( $this->_plugin )
|
|
|
|
|
|
|
523 |
$this->get_unique_affix()
|
524 |
);
|
525 |
|
@@ -933,82 +941,27 @@
|
|
933 |
* @param string $sdk_version
|
934 |
*/
|
935 |
function _sdk_version_update( $sdk_prev_version, $sdk_version ) {
|
936 |
-
/**
|
937 |
-
* @since 1.1.7.3 Fixed unwanted connectivity test cleanup.
|
938 |
-
*/
|
939 |
if ( empty( $sdk_prev_version ) ) {
|
940 |
return;
|
941 |
}
|
942 |
|
943 |
-
if (
|
944 |
-
version_compare( $
|
945 |
-
|
946 |
-
$this->_storage->handle_gdpr_admin_notice = true;
|
947 |
-
}
|
948 |
-
|
949 |
-
if ( version_compare( $sdk_prev_version, '2.0.0', '<' ) &&
|
950 |
-
version_compare( $sdk_version, '2.0.0', '>=' )
|
951 |
-
) {
|
952 |
-
$this->migrate_to_subscriptions_collection();
|
953 |
-
|
954 |
-
$this->consolidate_licenses();
|
955 |
-
|
956 |
-
// Clear trial_plan since it's now loaded from the plans collection when needed.
|
957 |
-
$this->_storage->remove( 'trial_plan', true, false );
|
958 |
-
}
|
959 |
-
|
960 |
-
if ( version_compare( $sdk_prev_version, '1.2.3', '<' ) &&
|
961 |
-
version_compare( $sdk_version, '1.2.3', '>=' )
|
962 |
-
) {
|
963 |
-
/**
|
964 |
-
* Starting from version 1.2.3, paths are stored as relative instead of absolute and some of them can be
|
965 |
-
* invalid.
|
966 |
-
*
|
967 |
-
* @author Leo Fajardo (@leorw)
|
968 |
-
*/
|
969 |
-
$this->remove_invalid_paths();
|
970 |
-
}
|
971 |
-
|
972 |
-
if ( version_compare( $sdk_prev_version, '1.1.5', '<' ) &&
|
973 |
-
version_compare( $sdk_version, '1.1.5', '>=' )
|
974 |
) {
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
$connectivity_data = $this->_storage->connectivity_test;
|
981 |
-
$connectivity_data['is_active'] = $this->_storage->is_on['is_active'];
|
982 |
-
$connectivity_data['timestamp'] = $this->_storage->is_on['timestamp'];
|
983 |
-
|
984 |
-
// Override.
|
985 |
-
$this->_storage->connectivity_test = $connectivity_data;
|
986 |
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
|
|
|
991 |
}
|
992 |
}
|
993 |
-
|
994 |
-
if (
|
995 |
-
version_compare( $sdk_prev_version, '2.2.1', '<' ) &&
|
996 |
-
version_compare( $sdk_version, '2.2.1', '>=' )
|
997 |
-
) {
|
998 |
-
/**
|
999 |
-
* Clear the file cache without storing the previous path since it could be a wrong path. For example,
|
1000 |
-
* in the versions of the SDK lower than 2.2.1, it's possible for the path of an add-on to be the same
|
1001 |
-
* as the parent plugin's when the add-on was auto-installed since the relevant method names were not
|
1002 |
-
* skipped in the logic that determines the right path in the `get_caller_main_file_and_type` method
|
1003 |
-
* (e.g. `try_activate_plugin`). Since it was an auto-installation, the caller was the parent plugin
|
1004 |
-
* and so its path was used. In case the stored path is wrong, clearing the cache will resolve issues
|
1005 |
-
* related to data mix-up between plugins (e.g. titles and versions of an add-on and its parent plugin).
|
1006 |
-
*
|
1007 |
-
* @author Leo Fajardo (@leorw)
|
1008 |
-
* @since 2.2.1
|
1009 |
-
*/
|
1010 |
-
$this->clear_module_main_file_cache( false );
|
1011 |
-
}
|
1012 |
}
|
1013 |
|
1014 |
/**
|
@@ -1059,102 +1012,6 @@
|
|
1059 |
}
|
1060 |
}
|
1061 |
|
1062 |
-
/**
|
1063 |
-
* @author Leo Fajardo (@leorw)
|
1064 |
-
* @since 2.0.0
|
1065 |
-
*/
|
1066 |
-
private function migrate_to_subscriptions_collection() {
|
1067 |
-
if ( ! is_object( $this->_site ) ) {
|
1068 |
-
return;
|
1069 |
-
}
|
1070 |
-
|
1071 |
-
if ( isset( $this->_storage->subscription ) && is_object( $this->_storage->subscription ) ) {
|
1072 |
-
$this->_storage->subscriptions = array( fs_get_entity( $this->_storage->subscription, FS_Subscription::get_class_name() ) );
|
1073 |
-
}
|
1074 |
-
}
|
1075 |
-
|
1076 |
-
/**
|
1077 |
-
* @author Leo Fajardo (@leorw)
|
1078 |
-
* @since 2.0.0
|
1079 |
-
*/
|
1080 |
-
private function consolidate_licenses() {
|
1081 |
-
$plugin_licenses = self::get_account_option( 'licenses', WP_FS__MODULE_TYPE_PLUGIN );
|
1082 |
-
if ( isset( $plugin_licenses[ $this->_slug ] ) ) {
|
1083 |
-
$plugin_licenses = $plugin_licenses[ $this->_slug ];
|
1084 |
-
} else {
|
1085 |
-
$plugin_licenses = array();
|
1086 |
-
}
|
1087 |
-
|
1088 |
-
$theme_licenses = self::get_account_option( 'licenses', WP_FS__MODULE_TYPE_THEME );
|
1089 |
-
if ( isset( $theme_licenses[ $this->_slug ] ) ) {
|
1090 |
-
$theme_licenses = $theme_licenses[ $this->_slug ];
|
1091 |
-
} else {
|
1092 |
-
$theme_licenses = array();
|
1093 |
-
}
|
1094 |
-
|
1095 |
-
if ( empty( $plugin_licenses ) && empty( $theme_licenses ) ) {
|
1096 |
-
return;
|
1097 |
-
}
|
1098 |
-
|
1099 |
-
$all_licenses = array();
|
1100 |
-
$user_id_license_ids_map = array();
|
1101 |
-
|
1102 |
-
foreach ( $plugin_licenses as $user_id => $user_licenses ) {
|
1103 |
-
if ( is_array( $user_licenses ) ) {
|
1104 |
-
if ( ! isset( $user_license_ids[ $user_id ] ) ) {
|
1105 |
-
$user_id_license_ids_map[ $user_id ] = array();
|
1106 |
-
}
|
1107 |
-
|
1108 |
-
foreach ( $user_licenses as $user_license ) {
|
1109 |
-
$all_licenses[] = $user_license;
|
1110 |
-
$user_id_license_ids_map[ $user_id ][] = $user_license->id;
|
1111 |
-
}
|
1112 |
-
}
|
1113 |
-
}
|
1114 |
-
|
1115 |
-
foreach ( $theme_licenses as $user_id => $user_licenses ) {
|
1116 |
-
if ( is_array( $user_licenses ) ) {
|
1117 |
-
if ( ! isset( $user_license_ids[ $user_id ] ) ) {
|
1118 |
-
$user_id_license_ids_map[ $user_id ] = array();
|
1119 |
-
}
|
1120 |
-
|
1121 |
-
foreach ( $user_licenses as $user_license ) {
|
1122 |
-
$all_licenses[] = $user_license;
|
1123 |
-
$user_id_license_ids_map[ $user_id ][] = $user_license->id;
|
1124 |
-
}
|
1125 |
-
}
|
1126 |
-
}
|
1127 |
-
|
1128 |
-
self::store_user_id_license_ids_map(
|
1129 |
-
$user_id_license_ids_map,
|
1130 |
-
$this->_module_id
|
1131 |
-
);
|
1132 |
-
|
1133 |
-
$this->_store_licenses( true, $this->_module_id, $all_licenses );
|
1134 |
-
}
|
1135 |
-
|
1136 |
-
/**
|
1137 |
-
* Remove invalid paths.
|
1138 |
-
*
|
1139 |
-
* @author Leo Fajardo (@leorw)
|
1140 |
-
* @since 1.2.3
|
1141 |
-
*/
|
1142 |
-
private function remove_invalid_paths() {
|
1143 |
-
// Remove invalid path that is still associated with the current slug if there's any.
|
1144 |
-
$file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() );
|
1145 |
-
foreach ( $file_slug_map as $plugin_basename => $slug ) {
|
1146 |
-
if ( $slug === $this->_slug &&
|
1147 |
-
$plugin_basename !== $this->_plugin_basename &&
|
1148 |
-
! file_exists( $this->get_absolute_path( $plugin_basename ) )
|
1149 |
-
) {
|
1150 |
-
unset( $file_slug_map[ $plugin_basename ] );
|
1151 |
-
self::$_accounts->set_option( 'file_slug_map', $file_slug_map, true );
|
1152 |
-
|
1153 |
-
break;
|
1154 |
-
}
|
1155 |
-
}
|
1156 |
-
}
|
1157 |
-
|
1158 |
/**
|
1159 |
* @author Vova Feldman (@svovaf)
|
1160 |
* @since 1.2.2.7
|
@@ -1491,46 +1348,6 @@
|
|
1491 |
}
|
1492 |
}
|
1493 |
|
1494 |
-
/**
|
1495 |
-
* Add special parameter to WP admin AJAX calls so when we
|
1496 |
-
* process AJAX calls we can identify its source properly.
|
1497 |
-
*
|
1498 |
-
* @author Leo Fajardo (@leorw)
|
1499 |
-
* @since 2.0.0
|
1500 |
-
*/
|
1501 |
-
static function _enrich_ajax_url() {
|
1502 |
-
$admin_param = is_network_admin() ?
|
1503 |
-
'_fs_network_admin' :
|
1504 |
-
'_fs_blog_admin';
|
1505 |
-
?>
|
1506 |
-
<script type="text/javascript">
|
1507 |
-
(function ($) {
|
1508 |
-
$(document).ajaxSend(function (event, jqxhr, settings) {
|
1509 |
-
if (settings.url &&
|
1510 |
-
-1 < settings.url.indexOf('admin-ajax.php') &&
|
1511 |
-
! ( settings.url.indexOf( '<?php echo $admin_param ?>' ) > 0 )
|
1512 |
-
) {
|
1513 |
-
if (
|
1514 |
-
'string' === typeof settings.data &&
|
1515 |
-
settings.data.indexOf( 'action=heartbeat' ) > 0
|
1516 |
-
) {
|
1517 |
-
return;
|
1518 |
-
}
|
1519 |
-
|
1520 |
-
if (settings.url.indexOf('?') > 0) {
|
1521 |
-
settings.url += '&';
|
1522 |
-
} else {
|
1523 |
-
settings.url += '?';
|
1524 |
-
}
|
1525 |
-
|
1526 |
-
settings.url += '<?php echo $admin_param ?>=true';
|
1527 |
-
}
|
1528 |
-
});
|
1529 |
-
})(jQuery);
|
1530 |
-
</script>
|
1531 |
-
<?php
|
1532 |
-
}
|
1533 |
-
|
1534 |
/**
|
1535 |
* Opens the support forum subemenu item in a new browser page.
|
1536 |
*
|
@@ -1641,8 +1458,10 @@
|
|
1641 |
}
|
1642 |
|
1643 |
if ( $this->is_plugin() ) {
|
1644 |
-
if ( $
|
1645 |
add_action( 'wpmu_new_blog', array( $this, '_after_new_blog_callback' ), 10, 6 );
|
|
|
|
|
1646 |
}
|
1647 |
|
1648 |
register_deactivation_hook( $this->_plugin_main_file_path, array( &$this, '_deactivate_plugin_hook' ) );
|
@@ -1652,7 +1471,12 @@
|
|
1652 |
add_action( 'deactivate_blog', array( &$this, '_after_site_deactivated_callback' ) );
|
1653 |
add_action( 'archive_blog', array( &$this, '_after_site_deactivated_callback' ) );
|
1654 |
add_action( 'make_spam_blog', array( &$this, '_after_site_deactivated_callback' ) );
|
1655 |
-
|
|
|
|
|
|
|
|
|
|
|
1656 |
|
1657 |
add_action( 'activate_blog', array( &$this, '_after_site_reactivated_callback' ) );
|
1658 |
add_action( 'unarchive_blog', array( &$this, '_after_site_reactivated_callback' ) );
|
@@ -1677,6 +1501,7 @@
|
|
1677 |
add_action( 'admin_init', array( &$this, '_add_premium_version_upgrade_selection' ) );
|
1678 |
add_action( 'admin_init', array( &$this, '_add_beta_mode_update_handler' ) );
|
1679 |
add_action( 'admin_init', array( &$this, '_add_user_change_option' ) );
|
|
|
1680 |
|
1681 |
$this->add_ajax_action( 'update_billing', array( &$this, '_update_billing_ajax_action' ) );
|
1682 |
$this->add_ajax_action( 'start_trial', array( &$this, '_start_trial_ajax_action' ) );
|
@@ -2048,7 +1873,13 @@
|
|
2048 |
return;
|
2049 |
}
|
2050 |
|
2051 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2052 |
|
2053 |
if ( self::is_plugins_page() && $this->is_plugin() ) {
|
2054 |
$this->hook_plugin_action_links();
|
@@ -2094,20 +1925,27 @@
|
|
2094 |
/**
|
2095 |
* Leverage backtrace to find caller plugin file path.
|
2096 |
*
|
2097 |
-
* @
|
2098 |
-
* @
|
2099 |
-
*
|
2100 |
-
* @param bool $is_init Is initiation sequence.
|
2101 |
*
|
2102 |
* @return string
|
|
|
|
|
|
|
2103 |
*/
|
2104 |
-
private function _find_caller_plugin_file( $is_init = false ) {
|
2105 |
// Try to load the cached value of the file path.
|
2106 |
if ( isset( $this->_storage->plugin_main_file ) ) {
|
2107 |
$plugin_main_file = $this->_storage->plugin_main_file;
|
2108 |
if ( ! empty( $plugin_main_file->path ) ) {
|
2109 |
$absolute_path = $this->get_absolute_path( $plugin_main_file->path );
|
2110 |
if ( file_exists( $absolute_path ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
2111 |
return $absolute_path;
|
2112 |
}
|
2113 |
}
|
@@ -2148,12 +1986,11 @@
|
|
2148 |
* Only the original instantiator that calls dynamic_init can modify the module's path.
|
2149 |
*/
|
2150 |
// Find caller module.
|
2151 |
-
$id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map', array() );
|
2152 |
$this->_storage->plugin_main_file = (object) array(
|
2153 |
-
'path' => $
|
2154 |
);
|
2155 |
|
2156 |
-
return $this->get_absolute_path( $
|
2157 |
}
|
2158 |
|
2159 |
/**
|
@@ -2215,6 +2052,8 @@
|
|
2215 |
* @param number $module_id
|
2216 |
* @param string $slug
|
2217 |
*
|
|
|
|
|
2218 |
* @since 1.2.2
|
2219 |
*/
|
2220 |
private function store_id_slug_type_path_map( $module_id, $slug ) {
|
@@ -2236,20 +2075,52 @@
|
|
2236 |
$store_option = true;
|
2237 |
}
|
2238 |
|
2239 |
-
|
2240 |
-
|
2241 |
-
|
2242 |
-
|
2243 |
-
|
2244 |
-
|
2245 |
-
|
2246 |
-
|
2247 |
-
|
2248 |
-
|
2249 |
-
|
2250 |
-
|
2251 |
-
|
2252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2253 |
|
2254 |
$id_slug_type_path_map[ $module_id ]['type'] = $caller_main_file_and_type->module_type;
|
2255 |
$id_slug_type_path_map[ $module_id ]['path'] = $caller_main_file_and_type->path;
|
@@ -2260,6 +2131,8 @@
|
|
2260 |
if ( $store_option ) {
|
2261 |
self::$_accounts->set_option( 'id_slug_type_path_map', $id_slug_type_path_map, true );
|
2262 |
}
|
|
|
|
|
2263 |
}
|
2264 |
|
2265 |
/**
|
@@ -2273,8 +2146,10 @@
|
|
2273 |
* add-ons are relying on loading the SDK from the parent module, and also allows themes including the
|
2274 |
* SDK an internal file instead of directly from functions.php.
|
2275 |
* @since 1.2.1.7 Knows how to handle cases when an add-on includes the parent module logic.
|
|
|
|
|
2276 |
*/
|
2277 |
-
private function get_caller_main_file_and_type() {
|
2278 |
self::require_plugin_essentials();
|
2279 |
|
2280 |
$all_plugins = fs_get_plugins( true );
|
@@ -2413,10 +2288,12 @@
|
|
2413 |
}
|
2414 |
}
|
2415 |
|
2416 |
-
|
2417 |
'module_type' => $module_type,
|
2418 |
'path' => $caller_file_candidate
|
2419 |
);
|
|
|
|
|
2420 |
}
|
2421 |
|
2422 |
#----------------------------------------------------------------------------------
|
@@ -2433,6 +2310,13 @@
|
|
2433 |
* @since 1.1.2
|
2434 |
*/
|
2435 |
function _add_deactivation_feedback_dialog_box() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2436 |
$subscription_cancellation_dialog_box_template_params = $this->apply_filters( 'show_deactivation_subscription_cancellation', true ) ?
|
2437 |
$this->_get_subscription_cancellation_dialog_box_template_params() :
|
2438 |
array();
|
@@ -2440,7 +2324,7 @@
|
|
2440 |
/**
|
2441 |
* @since 2.3.0 Developers can optionally hide the deactivation feedback form using the 'show_deactivation_feedback_form' filter.
|
2442 |
*/
|
2443 |
-
$show_deactivation_feedback_form =
|
2444 |
if ( $this->has_filter( 'show_deactivation_feedback_form' ) ) {
|
2445 |
$show_deactivation_feedback_form = $this->apply_filters( 'show_deactivation_feedback_form', true );
|
2446 |
} else if ( $this->is_addon() ) {
|
@@ -2545,7 +2429,7 @@
|
|
2545 |
$reason_temporary_deactivation = array(
|
2546 |
'id' => self::REASON_TEMPORARY_DEACTIVATION,
|
2547 |
'text' => sprintf(
|
2548 |
-
$this->get_text_inline( "It's a temporary %s
|
2549 |
strtolower( $this->is_plugin() ?
|
2550 |
$this->get_text_inline( 'Deactivation', 'deactivation' ) :
|
2551 |
$this->get_text_inline( 'Theme Switch', 'theme-switch' )
|
@@ -2710,6 +2594,14 @@
|
|
2710 |
|
2711 |
$this->_storage->store( 'uninstall_reason', $reason );
|
2712 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2713 |
/**
|
2714 |
* If the module type is "theme", trigger the uninstall event here (on theme deactivation) since themes do
|
2715 |
* not support uninstall hook.
|
@@ -2731,6 +2623,73 @@
|
|
2731 |
exit;
|
2732 |
}
|
2733 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2734 |
/**
|
2735 |
* @author Leo Fajardo (@leorw)
|
2736 |
* @since 2.1.4
|
@@ -2927,6 +2886,13 @@
|
|
2927 |
return self::instance( $addon_id );
|
2928 |
}
|
2929 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2930 |
#endregion ------------------------------------------------------------------
|
2931 |
|
2932 |
/**
|
@@ -3437,7 +3403,9 @@
|
|
3437 |
add_action( 'plugins_loaded', array( 'Freemius', '_load_textdomain' ), 1 );
|
3438 |
}
|
3439 |
|
3440 |
-
|
|
|
|
|
3441 |
add_action( 'admin_footer', array( 'Freemius', '_open_support_forum_in_new_page' ) );
|
3442 |
|
3443 |
if ( self::is_plugins_page() || self::is_themes_page() ) {
|
@@ -3456,48 +3424,197 @@
|
|
3456 |
self::$_statics_loaded = true;
|
3457 |
}
|
3458 |
|
|
|
|
|
|
|
|
|
3459 |
/**
|
3460 |
* @author Leo Fajardo (@leorw)
|
|
|
3461 |
*
|
3462 |
-
* @
|
|
|
|
|
3463 |
*/
|
3464 |
-
private
|
3465 |
-
|
3466 |
-
|
3467 |
-
|
3468 |
-
$api_network_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true, true );
|
3469 |
-
$api_network_options->migrate_to_network();
|
3470 |
-
|
3471 |
-
// Migrate API cache to network level storage.
|
3472 |
-
FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME )->migrate_to_network();
|
3473 |
|
3474 |
-
|
3475 |
}
|
3476 |
|
3477 |
-
#----------------------------------------------------------------------------------
|
3478 |
-
#region Localization
|
3479 |
-
#----------------------------------------------------------------------------------
|
3480 |
-
|
3481 |
/**
|
3482 |
-
*
|
|
|
3483 |
*
|
3484 |
-
* @
|
3485 |
-
* @since 1.2.1
|
3486 |
*/
|
3487 |
-
|
3488 |
-
if ( !
|
3489 |
-
return;
|
3490 |
}
|
3491 |
|
3492 |
-
|
3493 |
|
3494 |
-
|
3495 |
-
|
3496 |
-
|
3497 |
-
|
3498 |
-
|
3499 |
-
|
3500 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3501 |
|
3502 |
#endregion
|
3503 |
|
@@ -3692,6 +3809,10 @@
|
|
3692 |
|
3693 |
switch_to_blog( $current_blog_id );
|
3694 |
}
|
|
|
|
|
|
|
|
|
3695 |
} else if ( fs_request_is_action( 'simulate_trial' ) ) {
|
3696 |
check_admin_referer( 'simulate_trial' );
|
3697 |
|
@@ -3740,55 +3861,69 @@
|
|
3740 |
}
|
3741 |
|
3742 |
/**
|
3743 |
-
* @author
|
3744 |
-
* @since
|
|
|
|
|
3745 |
*/
|
3746 |
-
static function
|
3747 |
self::$_static_logger->entrance();
|
3748 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3749 |
if ( ! is_multisite() ) {
|
3750 |
-
$
|
3751 |
-
|
|
|
|
|
|
|
|
|
|
|
3752 |
} else {
|
3753 |
$sites = self::get_sites();
|
3754 |
|
3755 |
-
$all_plugins_installs = array();
|
3756 |
-
$all_themes_installs = array();
|
3757 |
-
|
3758 |
foreach ( $sites as $site ) {
|
3759 |
$blog_id = self::get_site_blog_id( $site );
|
3760 |
|
3761 |
-
|
3762 |
-
|
3763 |
-
foreach ( $plugins_installs as $slug => $install ) {
|
3764 |
-
if ( ! isset( $all_plugins_installs[ $slug ] ) ) {
|
3765 |
-
$all_plugins_installs[ $slug ] = array();
|
3766 |
-
}
|
3767 |
-
|
3768 |
-
$install->blog_id = $blog_id;
|
3769 |
|
3770 |
-
$
|
3771 |
-
|
|
|
|
|
3772 |
|
3773 |
-
|
3774 |
|
3775 |
-
|
3776 |
-
if ( ! isset( $all_themes_installs[ $slug ] ) ) {
|
3777 |
-
$all_themes_installs[ $slug ] = array();
|
3778 |
}
|
3779 |
|
3780 |
-
$install->blog_id = $blog_id;
|
3781 |
-
|
3782 |
-
$all_themes_installs[ $slug ][] = $install;
|
3783 |
}
|
3784 |
}
|
3785 |
}
|
3786 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3787 |
$licenses_by_module_type = self::get_all_licenses_by_module_type();
|
3788 |
|
3789 |
$vars = array(
|
3790 |
-
'plugin_sites' => $
|
3791 |
-
'theme_sites' => $
|
3792 |
'users' => self::get_all_users(),
|
3793 |
'addons' => self::get_all_addons(),
|
3794 |
'account_addons' => self::get_all_account_addons(),
|
@@ -3820,6 +3955,10 @@
|
|
3820 |
function is_on() {
|
3821 |
self::$_static_logger->entrance();
|
3822 |
|
|
|
|
|
|
|
|
|
3823 |
if ( isset( $this->_is_on ) ) {
|
3824 |
return $this->_is_on;
|
3825 |
}
|
@@ -3908,18 +4047,24 @@
|
|
3908 |
|
3909 |
$is_update = $this->apply_filters( 'is_plugin_update', $this->is_plugin_update() );
|
3910 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3911 |
return $this->get_api_plugin_scope()->ping(
|
3912 |
$this->get_anonymous_id( $blog_id ),
|
3913 |
-
|
3914 |
-
'is_update' => json_encode( $is_update ),
|
3915 |
-
'version' => $version,
|
3916 |
-
'sdk' => $this->version,
|
3917 |
-
'is_admin' => json_encode( is_admin() ),
|
3918 |
-
'is_ajax' => json_encode( self::is_ajax() ),
|
3919 |
-
'is_cron' => json_encode( self::is_cron() ),
|
3920 |
-
'is_gdpr_test' => $is_gdpr_test,
|
3921 |
-
'is_http' => json_encode( WP_FS__IS_HTTP_REQUEST ),
|
3922 |
-
)
|
3923 |
);
|
3924 |
}
|
3925 |
|
@@ -4056,7 +4201,7 @@
|
|
4056 |
$unique_id = self::$_accounts->get_option( 'unique_id', null, $blog_id );
|
4057 |
|
4058 |
if ( empty( $unique_id ) || ! is_string( $unique_id ) ) {
|
4059 |
-
$key =
|
4060 |
|
4061 |
$secure_auth = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
|
4062 |
if ( empty( $secure_auth ) ||
|
@@ -4085,6 +4230,17 @@
|
|
4085 |
return $unique_id;
|
4086 |
}
|
4087 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4088 |
/**
|
4089 |
* @author Vova Feldman (@svovaf)
|
4090 |
* @since 1.1.7.4
|
@@ -4233,11 +4389,16 @@
|
|
4233 |
$install_previous_desc = $this->esc_html_inline( 'Uninstall this version and install the previous one.', 'install-previous-desc' );
|
4234 |
$fix_issue_title = $this->esc_html_inline( 'Yes - I\'m giving you a chance to fix it', 'fix-issue-title' );
|
4235 |
$fix_issue_desc = $this->esc_html_inline( 'We will do our best to whitelist your server and resolve this issue ASAP. You will get a follow-up email to %s once we have an update.', 'fix-issue-desc' );
|
4236 |
-
/* translators: %s: product title (e.g. "Awesome Plugin" requires
|
4237 |
-
$x_requires_access_to_api = $this->esc_html_inline( '%s requires
|
4238 |
$sysadmin_title = $this->esc_html_inline( 'I\'m a system administrator', 'sysadmin-title' );
|
4239 |
$happy_to_resolve_issue_asap = $this->esc_html_inline( 'We are sure it\'s an issue on our side and more than happy to resolve it for you ASAP if you give us a chance.', 'happy-to-resolve-issue-asap' );
|
4240 |
|
|
|
|
|
|
|
|
|
|
|
4241 |
$message = false;
|
4242 |
if ( is_object( $api_result ) &&
|
4243 |
isset( $api_result->error ) &&
|
@@ -4869,7 +5030,7 @@
|
|
4869 |
|
4870 |
/**
|
4871 |
* This should be executed even if Freemius is off for the core module,
|
4872 |
-
* otherwise, the add-ons
|
4873 |
* relevant when the developer decided to turn FS off for existing users.
|
4874 |
*
|
4875 |
* @author Vova Feldman (@svovaf)
|
@@ -4907,22 +5068,25 @@
|
|
4907 |
* @since 1.1.7.3
|
4908 |
*
|
4909 |
*/
|
4910 |
-
if ( $this->is_registered() ) {
|
4911 |
-
|
4912 |
-
$this->schedule_sync_cron();
|
4913 |
-
}
|
4914 |
}
|
4915 |
|
4916 |
/**
|
4917 |
* Check if requested for manual blocking background sync.
|
4918 |
*/
|
4919 |
if ( fs_request_has( 'background_sync' ) ) {
|
|
|
|
|
|
|
4920 |
$this->run_manual_sync();
|
4921 |
}
|
4922 |
}
|
4923 |
}
|
4924 |
|
4925 |
if ( $this->is_registered() ) {
|
|
|
|
|
4926 |
$this->hook_callback_to_install_sync();
|
4927 |
}
|
4928 |
|
@@ -4937,6 +5101,28 @@
|
|
4937 |
}
|
4938 |
|
4939 |
if ( $this->is_user_in_admin() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4940 |
if ( $this->is_addon() ) {
|
4941 |
if ( ! $this->is_parent_plugin_installed() ) {
|
4942 |
$parent_name = $this->get_option( $plugin_info, 'parent_name', null );
|
@@ -5041,7 +5227,7 @@
|
|
5041 |
* because the updater has some logic that needs to be executed
|
5042 |
* during AJAX calls.
|
5043 |
*
|
5044 |
-
* Currently we need to hook to the `http_request_host_is_external` filter.
|
5045 |
* In the future, there might be additional logic added.
|
5046 |
*
|
5047 |
* @author Vova Feldman
|
@@ -5060,7 +5246,8 @@
|
|
5060 |
*/
|
5061 |
( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this->premium_plugin_basename() ) ) )
|
5062 |
) &&
|
5063 |
-
$this->has_release_on_freemius()
|
|
|
5064 |
) {
|
5065 |
FS_Plugin_Updater::instance( $this );
|
5066 |
}
|
@@ -5129,150 +5316,70 @@
|
|
5129 |
}
|
5130 |
|
5131 |
/**
|
5132 |
-
* @
|
|
|
|
|
5133 |
*
|
5134 |
-
* @
|
5135 |
*/
|
5136 |
-
function
|
5137 |
$this->_logger->entrance();
|
5138 |
|
5139 |
-
$
|
5140 |
-
|
5141 |
-
|
5142 |
-
|
5143 |
-
if ( true === $result ) {
|
5144 |
-
self::shoot_ajax_success();
|
5145 |
-
}
|
5146 |
-
|
5147 |
-
$this->_logger->api_error( $result );
|
5148 |
-
|
5149 |
-
self::shoot_ajax_failure(
|
5150 |
-
sprintf( $this->get_text_inline( 'Unexpected API error. Please contact the %s\'s author with the following error.', 'unexpected-api-error' ), $this->_module_type ) .
|
5151 |
-
( $this->is_api_error( $result ) && isset( $result->error ) ?
|
5152 |
-
$result->error->message :
|
5153 |
-
var_export( $result, true ) )
|
5154 |
);
|
5155 |
-
}
|
5156 |
-
|
5157 |
-
/**
|
5158 |
-
* @author Leo Fajardo (@leorw)
|
5159 |
-
* @since 1.2.1.5
|
5160 |
-
*/
|
5161 |
-
function _allow_tracking_callback() {
|
5162 |
-
$this->_logger->entrance();
|
5163 |
-
|
5164 |
-
$this->check_ajax_referer( 'allow_tracking' );
|
5165 |
|
5166 |
-
$
|
5167 |
-
|
5168 |
-
if (
|
5169 |
-
|
5170 |
}
|
5171 |
|
5172 |
-
$this->
|
5173 |
-
|
5174 |
-
self::shoot_ajax_failure(
|
5175 |
-
sprintf( $this->get_text_inline( 'Unexpected API error. Please contact the %s\'s author with the following error.', 'unexpected-api-error' ), $this->_module_type ) .
|
5176 |
-
( $this->is_api_error( $result ) && isset( $result->error ) ?
|
5177 |
-
$result->error->message :
|
5178 |
-
var_export( $result, true ) )
|
5179 |
-
);
|
5180 |
-
}
|
5181 |
-
|
5182 |
-
/**
|
5183 |
-
* Opt-out from usage tracking.
|
5184 |
-
*
|
5185 |
-
* Note: This will not delete the account information but will stop all tracking.
|
5186 |
-
*
|
5187 |
-
* Returns:
|
5188 |
-
* 1. FALSE - If the user never opted-in.
|
5189 |
-
* 2. TRUE - If successfully opted-out.
|
5190 |
-
* 3. object - API result on failure.
|
5191 |
-
*
|
5192 |
-
* @author Leo Fajardo (@leorw)
|
5193 |
-
* @since 1.2.1.5
|
5194 |
-
*
|
5195 |
-
* @return bool|object
|
5196 |
-
*/
|
5197 |
-
function stop_site_tracking() {
|
5198 |
-
$this->_logger->entrance();
|
5199 |
-
|
5200 |
-
if ( ! $this->is_registered() ) {
|
5201 |
-
// User never opted-in.
|
5202 |
-
return false;
|
5203 |
-
}
|
5204 |
|
5205 |
-
if ( $
|
5206 |
-
|
5207 |
-
return true;
|
5208 |
}
|
5209 |
|
5210 |
-
|
5211 |
-
|
5212 |
-
|
5213 |
-
) );
|
5214 |
-
|
5215 |
-
if ( ! $this->is_api_result_entity( $result ) ||
|
5216 |
-
! isset( $result->is_disconnected ) ||
|
5217 |
-
! $result->is_disconnected
|
5218 |
) {
|
5219 |
$this->_logger->api_error( $result );
|
5220 |
|
5221 |
return $result;
|
5222 |
}
|
5223 |
|
5224 |
-
$this->_site->is_disconnected = $result->is_disconnected;
|
5225 |
-
$this->_store_site();
|
5226 |
-
|
5227 |
-
$this->clear_sync_cron();
|
5228 |
-
|
5229 |
-
// Successfully disconnected.
|
5230 |
return true;
|
5231 |
}
|
5232 |
|
5233 |
/**
|
5234 |
-
*
|
|
|
|
|
5235 |
*
|
5236 |
-
*
|
5237 |
-
*
|
5238 |
-
* Returns:
|
5239 |
-
* 1. FALSE - If the user never opted-in.
|
5240 |
-
* 2. TRUE - If successfully opted-out.
|
5241 |
-
* 3. object - API result on failure.
|
5242 |
-
*
|
5243 |
-
* @author Leo Fajardo (@leorw)
|
5244 |
-
* @since 1.2.1.5
|
5245 |
-
*
|
5246 |
-
* @return bool|object
|
5247 |
*/
|
5248 |
-
function
|
|
|
|
|
|
|
|
|
5249 |
$this->_logger->entrance();
|
5250 |
|
5251 |
-
if ( ! $this->is_registered() ) {
|
5252 |
-
// User never opted-in.
|
5253 |
-
return false;
|
5254 |
-
}
|
5255 |
-
|
5256 |
$install_id_2_blog_id = array();
|
5257 |
-
$
|
5258 |
-
|
5259 |
-
$opt_out_all = true;
|
5260 |
|
5261 |
-
$
|
5262 |
-
foreach ( $installs_map as $blog_id => $install ) {
|
5263 |
-
if ( $install->is_tracking_prohibited() ) {
|
5264 |
-
// Already opted-out.
|
5265 |
-
continue;
|
5266 |
-
}
|
5267 |
|
|
|
5268 |
if ( $this->is_site_delegated_connection( $blog_id ) ) {
|
5269 |
-
//
|
5270 |
-
$
|
5271 |
continue;
|
5272 |
}
|
5273 |
|
5274 |
-
$params[] = array( 'id' => $install->id );
|
5275 |
-
|
5276 |
$install_id_2_blog_id[ $install->id ] = $blog_id;
|
5277 |
}
|
5278 |
|
@@ -5280,171 +5387,188 @@
|
|
5280 |
return true;
|
5281 |
}
|
5282 |
|
5283 |
-
$params
|
|
|
|
|
|
|
|
|
5284 |
|
5285 |
// Send update to FS.
|
5286 |
-
$result = $this->get_current_or_network_user_api_scope()->call(
|
|
|
|
|
|
|
|
|
5287 |
|
5288 |
-
if ( ! $this->is_api_result_object( $result, '
|
5289 |
$this->_logger->api_error( $result );
|
5290 |
|
5291 |
return $result;
|
5292 |
}
|
5293 |
|
5294 |
-
foreach ( $result->installs as $r_install ) {
|
5295 |
-
$blog_id = $install_id_2_blog_id[ $r_install->id ];
|
5296 |
-
$install = $installs_map[ $blog_id ];
|
5297 |
-
$install->is_disconnected = $r_install->is_disconnected;
|
5298 |
-
$this->_store_site( true, $blog_id, $install );
|
5299 |
-
}
|
5300 |
-
|
5301 |
-
$this->clear_sync_cron( $opt_out_all );
|
5302 |
-
|
5303 |
-
// Successfully disconnected.
|
5304 |
return true;
|
5305 |
}
|
5306 |
|
5307 |
/**
|
5308 |
-
*
|
5309 |
-
*
|
5310 |
-
* Note: This will not delete the account information but will stop all tracking.
|
5311 |
-
*
|
5312 |
-
* Returns:
|
5313 |
-
* 1. FALSE - If the user never opted-in.
|
5314 |
-
* 2. TRUE - If successfully opted-out.
|
5315 |
-
* 3. object - API result on failure.
|
5316 |
-
*
|
5317 |
-
* @author Leo Fajardo (@leorw)
|
5318 |
-
* @since 1.2.1.5
|
5319 |
-
*
|
5320 |
-
* @param bool $is_network_action
|
5321 |
*
|
5322 |
-
* @return
|
5323 |
*/
|
5324 |
-
function
|
5325 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5326 |
|
5327 |
-
return $
|
5328 |
-
$this->stop_network_tracking() :
|
5329 |
-
$this->stop_site_tracking();
|
5330 |
}
|
5331 |
|
5332 |
/**
|
5333 |
-
*
|
5334 |
-
*
|
5335 |
-
* Note: This will only work if the user opted-in previously.
|
5336 |
-
*
|
5337 |
-
* Returns:
|
5338 |
-
* 1. FALSE - If the user never opted-in.
|
5339 |
-
* 2. TRUE - If successfully opted-in back to usage tracking.
|
5340 |
-
* 3. object - API result on failure.
|
5341 |
-
*
|
5342 |
-
* @author Leo Fajardo (@leorw)
|
5343 |
-
* @since 1.2.1.5
|
5344 |
-
*
|
5345 |
-
* @return bool|object
|
5346 |
*/
|
5347 |
-
function
|
5348 |
$this->_logger->entrance();
|
5349 |
|
5350 |
-
|
5351 |
-
// User never opted-in.
|
5352 |
-
return false;
|
5353 |
-
}
|
5354 |
|
5355 |
-
if ( $this->
|
5356 |
-
|
5357 |
-
return true;
|
5358 |
}
|
5359 |
|
5360 |
-
$
|
5361 |
-
|
5362 |
-
) );
|
5363 |
-
|
5364 |
-
if ( ! $this->is_api_result_entity( $result ) ||
|
5365 |
-
! isset( $result->is_disconnected ) ||
|
5366 |
-
$result->is_disconnected
|
5367 |
-
) {
|
5368 |
-
$this->_logger->api_error( $result );
|
5369 |
|
5370 |
-
|
|
|
5371 |
}
|
5372 |
|
5373 |
-
$
|
5374 |
-
$this->_store_site();
|
5375 |
|
5376 |
-
$this->
|
5377 |
|
5378 |
-
|
5379 |
-
|
|
|
|
|
|
|
5380 |
}
|
5381 |
|
5382 |
/**
|
5383 |
-
*
|
5384 |
-
*
|
5385 |
-
*
|
5386 |
-
*
|
5387 |
-
* Returns:
|
5388 |
-
* 1. FALSE - If the user never opted-in.
|
5389 |
-
* 2. TRUE - If successfully opted-in back to usage tracking.
|
5390 |
-
* 3. object - API result on failure.
|
5391 |
-
*
|
5392 |
-
* @author Leo Fajardo (@leorw)
|
5393 |
-
* @since 1.2.1.5
|
5394 |
*
|
5395 |
-
* @return bool|
|
5396 |
*/
|
5397 |
-
function
|
5398 |
-
$this->
|
5399 |
-
|
5400 |
-
if ( ! $this->is_registered() ) {
|
5401 |
// User never opted-in.
|
5402 |
return false;
|
5403 |
}
|
5404 |
|
5405 |
-
|
5406 |
-
|
5407 |
-
|
5408 |
-
|
5409 |
-
|
5410 |
-
|
5411 |
-
|
5412 |
-
}
|
5413 |
-
|
5414 |
-
$params[] = array( 'id' => $install->id );
|
5415 |
-
|
5416 |
-
$install_id_2_blog_id[ $install->id ] = $blog_id;
|
5417 |
}
|
5418 |
|
5419 |
-
|
5420 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5421 |
}
|
5422 |
|
5423 |
-
|
|
|
5424 |
|
5425 |
-
|
5426 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5427 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5428 |
|
5429 |
-
|
5430 |
-
|
|
|
5431 |
|
5432 |
-
|
5433 |
-
|
|
|
|
|
|
|
|
|
|
|
5434 |
|
5435 |
-
|
5436 |
-
|
5437 |
-
|
5438 |
-
$install->is_disconnected = $r_install->is_disconnected;
|
5439 |
-
$this->_store_site( true, $blog_id, $install );
|
5440 |
}
|
5441 |
|
5442 |
-
$this->
|
|
|
|
|
|
|
|
|
5443 |
|
5444 |
-
// Successfully reconnected.
|
5445 |
return true;
|
5446 |
}
|
5447 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5448 |
/**
|
5449 |
* Opt-in back into usage tracking.
|
5450 |
*
|
@@ -5458,16 +5582,18 @@
|
|
5458 |
* @author Leo Fajardo (@leorw)
|
5459 |
* @since 1.2.1.5
|
5460 |
*
|
5461 |
-
* @
|
5462 |
*
|
5463 |
* @return bool|object
|
5464 |
*/
|
5465 |
-
function
|
5466 |
$this->_logger->entrance();
|
5467 |
|
5468 |
-
return $
|
5469 |
-
$this->
|
5470 |
-
$
|
|
|
|
|
5471 |
}
|
5472 |
|
5473 |
/**
|
@@ -5488,8 +5614,7 @@
|
|
5488 |
|
5489 |
if ( ! fs_is_network_admin() || $is_context_single_site ) {
|
5490 |
if ( $this->is_tracking_prohibited() ) {
|
5491 |
-
$this->
|
5492 |
-
$this->_store_site();
|
5493 |
}
|
5494 |
} else {
|
5495 |
$installs_map = $this->get_blog_install_map();
|
@@ -5497,73 +5622,69 @@
|
|
5497 |
/**
|
5498 |
* @var FS_Site $install
|
5499 |
*/
|
5500 |
-
if ( $
|
5501 |
-
$
|
5502 |
-
$this->_store_site( true, $blog_id, $install );
|
5503 |
}
|
5504 |
}
|
5505 |
}
|
5506 |
}
|
5507 |
|
5508 |
/**
|
5509 |
-
*
|
5510 |
-
* @since 2.3.2
|
5511 |
*
|
5512 |
-
* @
|
|
|
|
|
|
|
|
|
5513 |
*/
|
5514 |
-
function
|
5515 |
-
|
5516 |
-
|
5517 |
-
$this->_storage->get( 'is_extensions_tracking_allowed', null )
|
5518 |
-
) );
|
5519 |
-
}
|
5520 |
|
5521 |
-
|
5522 |
-
|
5523 |
-
|
5524 |
-
*/
|
5525 |
-
function _update_tracking_permission_callback() {
|
5526 |
-
$this->_logger->entrance();
|
5527 |
|
5528 |
-
|
|
|
|
|
5529 |
|
5530 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5531 |
|
5532 |
-
|
5533 |
-
|
|
|
5534 |
}
|
5535 |
|
5536 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5537 |
|
5538 |
-
|
5539 |
-
case 'extensions':
|
5540 |
-
$this->update_extensions_tracking_flag( $is_enabled );
|
5541 |
-
break;
|
5542 |
-
default:
|
5543 |
$permission = 'no_match';
|
5544 |
-
|
5545 |
|
5546 |
-
|
5547 |
-
self::shoot_ajax_failure();
|
5548 |
}
|
5549 |
|
5550 |
-
|
5551 |
-
'permissions' => array(
|
5552 |
-
$permission => $is_enabled,
|
5553 |
-
)
|
5554 |
-
) );
|
5555 |
-
}
|
5556 |
-
|
5557 |
-
/**
|
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 |
/**
|
@@ -5769,8 +5890,7 @@
|
|
5769 |
if ( $this->is_activation_mode() ) {
|
5770 |
if ( ! is_admin() ) {
|
5771 |
/**
|
5772 |
-
* If in activation mode, don't execute Freemius outside
|
5773 |
-
* admin dashboard.
|
5774 |
*
|
5775 |
* @author Vova Feldman (@svovaf)
|
5776 |
* @since 1.1.7.3
|
@@ -6317,7 +6437,25 @@
|
|
6317 |
if ( ! isset( $this->_is_anonymous ) ) {
|
6318 |
if ( $this->is_network_anonymous() ) {
|
6319 |
$this->_is_anonymous = true;
|
6320 |
-
} else if (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6321 |
if ( ! isset( $this->_storage->is_anonymous ) ) {
|
6322 |
// Not skipped.
|
6323 |
$this->_is_anonymous = false;
|
@@ -6373,6 +6511,18 @@
|
|
6373 |
return $this->_storage->get( 'is_pending_activation', false );
|
6374 |
}
|
6375 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6376 |
/**
|
6377 |
* Check if plugin must be WordPress.org compliant.
|
6378 |
*
|
@@ -6449,9 +6599,11 @@
|
|
6449 |
private function get_cron_blog_id( $name ) {
|
6450 |
$this->_logger->entrance( $name );
|
6451 |
|
6452 |
-
|
6453 |
-
|
6454 |
-
|
|
|
|
|
6455 |
$cron_data = $this->get_cron_data( $name );
|
6456 |
|
6457 |
return ( is_object( $cron_data ) && is_numeric( $cron_data->blog_id ) ) ?
|
@@ -6562,18 +6714,23 @@
|
|
6562 |
return 0;
|
6563 |
}
|
6564 |
|
6565 |
-
if ( $this->_is_network_active
|
6566 |
-
|
6567 |
-
$except_blog_id != $this->_storage->network_install_blog_id &&
|
6568 |
-
self::is_site_active( $this->_storage->network_install_blog_id )
|
6569 |
-
) {
|
6570 |
-
// Try to run cron from the main network blog.
|
6571 |
-
$install = $this->get_install_by_blog_id( $this->_storage->network_install_blog_id );
|
6572 |
|
6573 |
-
if (
|
6574 |
-
|
|
|
|
|
6575 |
) {
|
6576 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6577 |
}
|
6578 |
}
|
6579 |
|
@@ -6582,7 +6739,7 @@
|
|
6582 |
foreach ( $installs as $blog_id => $install ) {
|
6583 |
if ( $except_blog_id != $blog_id &&
|
6584 |
self::is_site_active( $blog_id ) &&
|
6585 |
-
|
6586 |
) {
|
6587 |
return $blog_id;
|
6588 |
}
|
@@ -6614,7 +6771,7 @@
|
|
6614 |
/**
|
6615 |
* @var FS_Site $install
|
6616 |
*/
|
6617 |
-
if ( $
|
6618 |
$clear_cron = false;
|
6619 |
break;
|
6620 |
}
|
@@ -6625,14 +6782,7 @@
|
|
6625 |
return;
|
6626 |
}
|
6627 |
|
6628 |
-
|
6629 |
-
* @var object $cron_data
|
6630 |
-
*/
|
6631 |
-
$cron_data = $this->get_cron_data( $name );
|
6632 |
-
|
6633 |
-
$cron_blog_id = is_object( $cron_data ) && isset( $cron_data->blog_id ) ?
|
6634 |
-
$cron_data->blog_id :
|
6635 |
-
0;
|
6636 |
|
6637 |
$this->clear_cron_data( $name );
|
6638 |
|
@@ -6669,14 +6819,7 @@
|
|
6669 |
return false;
|
6670 |
}
|
6671 |
|
6672 |
-
|
6673 |
-
* @var object $cron_data
|
6674 |
-
*/
|
6675 |
-
$cron_data = $this->get_cron_data( $name );
|
6676 |
-
|
6677 |
-
$cron_blog_id = is_object( $cron_data ) && isset( $cron_data->blog_id ) ?
|
6678 |
-
$cron_data->blog_id :
|
6679 |
-
0;
|
6680 |
|
6681 |
if ( 0 < $cron_blog_id ) {
|
6682 |
switch_to_blog( $cron_blog_id );
|
@@ -6787,7 +6930,7 @@
|
|
6787 |
} else {
|
6788 |
$installs = $this->get_blog_install_map();
|
6789 |
foreach ( $installs as $blog_id => $install ) {
|
6790 |
-
if ( $this->
|
6791 |
if ( ! isset( $users_2_blog_ids[ $install->user_id ] ) ) {
|
6792 |
$users_2_blog_ids[ $install->user_id ] = array();
|
6793 |
}
|
@@ -6852,8 +6995,6 @@
|
|
6852 |
* @since 1.1.7.3
|
6853 |
*/
|
6854 |
private function run_manual_sync() {
|
6855 |
-
self::require_pluggable_essentials();
|
6856 |
-
|
6857 |
if ( ! $this->is_user_admin() ) {
|
6858 |
return;
|
6859 |
}
|
@@ -6937,6 +7078,24 @@
|
|
6937 |
return $this->is_cron_on( 'sync' );
|
6938 |
}
|
6939 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6940 |
/**
|
6941 |
* @author Vova Feldman (@svovaf)
|
6942 |
* @since 1.1.7.3
|
@@ -7043,6 +7202,10 @@
|
|
7043 |
* @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
|
7044 |
*/
|
7045 |
private function schedule_install_sync( $except_blog_id = 0 ) {
|
|
|
|
|
|
|
|
|
7046 |
$this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
|
7047 |
}
|
7048 |
|
@@ -7131,13 +7294,20 @@
|
|
7131 |
/**
|
7132 |
* Show a notice that activation is currently pending.
|
7133 |
*
|
|
|
|
|
7134 |
* @author Vova Feldman (@svovaf)
|
7135 |
* @since 1.0.7
|
7136 |
*
|
7137 |
* @param bool|string $email
|
7138 |
* @param bool $is_pending_trial Since 1.2.1.5
|
|
|
7139 |
*/
|
7140 |
-
function _add_pending_activation_notice(
|
|
|
|
|
|
|
|
|
7141 |
if ( ! is_string( $email ) ) {
|
7142 |
$current_user = self::_get_current_wp_user();
|
7143 |
$email = $current_user->user_email;
|
@@ -7193,6 +7363,20 @@
|
|
7193 |
/**
|
7194 |
* Don't redirect if activating multiple plugins at once (bulk activation).
|
7195 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7196 |
} else if ( ! $is_migration ) {
|
7197 |
$this->_redirect_on_activation_hook();
|
7198 |
return;
|
@@ -7206,7 +7390,7 @@
|
|
7206 |
if ( fs_request_is_action( $this->get_unique_affix() . '_skip_activation' ) ) {
|
7207 |
check_admin_referer( $this->get_unique_affix() . '_skip_activation' );
|
7208 |
|
7209 |
-
$this->skip_connection(
|
7210 |
|
7211 |
fs_redirect( $this->get_after_activation_url( 'after_skip_url' ) );
|
7212 |
}
|
@@ -7379,8 +7563,6 @@
|
|
7379 |
|
7380 |
fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' );
|
7381 |
fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' );
|
7382 |
-
|
7383 |
-
fs_enqueue_local_style( 'fs_connect', '/admin/connect.css' );
|
7384 |
}
|
7385 |
|
7386 |
/**
|
@@ -7416,14 +7598,14 @@
|
|
7416 |
<?php
|
7417 |
echo $this->apply_filters( 'optin_pointer_execute', "
|
7418 |
|
7419 |
-
|
7420 |
|
7421 |
-
|
7422 |
-
|
7423 |
-
|
7424 |
-
|
7425 |
|
7426 |
-
|
7427 |
}
|
7428 |
}
|
7429 |
});
|
@@ -7439,7 +7621,7 @@
|
|
7439 |
*
|
7440 |
* @return string
|
7441 |
*/
|
7442 |
-
function current_page_url() {
|
7443 |
$url = 'http';
|
7444 |
|
7445 |
if ( isset( $_SERVER["HTTPS"] ) ) {
|
@@ -7471,7 +7653,7 @@
|
|
7471 |
}
|
7472 |
|
7473 |
/* Events
|
7474 |
-
|
7475 |
/**
|
7476 |
* Delete site install from Database.
|
7477 |
*
|
@@ -7635,12 +7817,21 @@
|
|
7635 |
|
7636 |
/**
|
7637 |
* @author Leo Fajardo (@leorw)
|
7638 |
-
* @since 1.2.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7639 |
*
|
7640 |
-
* @return
|
7641 |
*/
|
7642 |
-
private function
|
7643 |
-
$slug = $this->get_previous_theme_slug();
|
7644 |
if ( false !== $slug && current_user_can( 'switch_themes' ) ) {
|
7645 |
$theme_instance = wp_get_theme( $slug );
|
7646 |
|
@@ -7737,6 +7928,10 @@
|
|
7737 |
( current_filter() !== ( 'activate_' . $this->_free_plugin_basename ) ) :
|
7738 |
$this->is_premium();
|
7739 |
|
|
|
|
|
|
|
|
|
7740 |
$this->_logger->info( 'Activating ' . ( $is_premium_version_activation ? 'premium' : 'free' ) . ' plugin version.' );
|
7741 |
|
7742 |
if ( $this->is_plugin() ) {
|
@@ -7803,7 +7998,9 @@
|
|
7803 |
$plugin_version = $this->_storage->is_anonymous_ms['version'];
|
7804 |
$network = true;
|
7805 |
} else {
|
7806 |
-
$plugin_version = $this->_storage->is_anonymous
|
|
|
|
|
7807 |
$network = false;
|
7808 |
}
|
7809 |
|
@@ -7951,7 +8148,7 @@
|
|
7951 |
);
|
7952 |
} else {
|
7953 |
// Activate the license.
|
7954 |
-
$install = $this->
|
7955 |
'/',
|
7956 |
'put',
|
7957 |
array( 'license_key' => $this->apply_filters( 'license_key', $license->secret_key ) )
|
@@ -8610,6 +8807,20 @@
|
|
8610 |
$this->_is_anonymous = $is_anonymous;
|
8611 |
}
|
8612 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8613 |
/**
|
8614 |
* @author Vova Feldman (@svovaf)
|
8615 |
* @since 2.0.0
|
@@ -8626,9 +8837,17 @@
|
|
8626 |
* @uses Freemius::is_network_anonymous() to check if the super-admin network skipped.
|
8627 |
* @uses Freemius::is_network_delegated_connection() to check if the super-admin network delegated the connection to the site admins.
|
8628 |
*/
|
8629 |
-
function _after_new_blog_callback( $blog_id, $user_id, $domain, $path, $network_id, $meta ) {
|
8630 |
$this->_logger->entrance();
|
8631 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8632 |
if ( $this->is_premium() &&
|
8633 |
$this->is_network_connected() &&
|
8634 |
is_object( $this->_license ) &&
|
@@ -8662,9 +8881,13 @@
|
|
8662 |
}
|
8663 |
}
|
8664 |
|
|
|
|
|
8665 |
$this->switch_to_blog( $current_blog_id );
|
8666 |
|
8667 |
-
if ( is_object( $
|
|
|
|
|
8668 |
// Already connected (with or without a license), so no need to continue.
|
8669 |
return;
|
8670 |
}
|
@@ -8697,6 +8920,8 @@
|
|
8697 |
false
|
8698 |
);
|
8699 |
|
|
|
|
|
8700 |
$this->switch_to_blog( $current_blog_id );
|
8701 |
} else {
|
8702 |
/**
|
@@ -8707,8 +8932,8 @@
|
|
8707 |
$has_delegated_site = false;
|
8708 |
|
8709 |
$sites = self::get_sites();
|
8710 |
-
foreach ( $sites as $
|
8711 |
-
$blog_id = self::get_site_blog_id( $
|
8712 |
|
8713 |
if ( $this->is_site_delegated_connection( $blog_id ) ) {
|
8714 |
$has_delegated_site = true;
|
@@ -8722,19 +8947,74 @@
|
|
8722 |
$this->skip_site_connection( $blog_id );
|
8723 |
}
|
8724 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8725 |
}
|
8726 |
|
8727 |
/**
|
8728 |
* @author Vova Feldman (@svovaf)
|
8729 |
* @since 1.1.3
|
8730 |
*
|
8731 |
-
* @param bool|int $
|
8732 |
*/
|
8733 |
-
private function reset_anonymous_mode( $
|
8734 |
-
if ( true === $
|
8735 |
-
|
8736 |
-
|
8737 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8738 |
}
|
8739 |
|
8740 |
/**
|
@@ -8745,11 +9025,7 @@
|
|
8745 |
* @author Leo Fajardo (@leorw)
|
8746 |
* @since 1.2.2
|
8747 |
*/
|
8748 |
-
if ( ! $this->_is_network_active
|
8749 |
-
0 === $network_or_blog_id ||
|
8750 |
-
get_current_blog_id() == $network_or_blog_id ||
|
8751 |
-
( true === $network_or_blog_id && fs_is_network_admin() )
|
8752 |
-
) {
|
8753 |
$this->_is_anonymous = null;
|
8754 |
}
|
8755 |
}
|
@@ -8795,44 +9071,42 @@
|
|
8795 |
* @author Vova Feldman (@svovaf)
|
8796 |
* @since 1.1.1
|
8797 |
*
|
8798 |
-
* @param
|
8799 |
-
* @param bool $skip_all_network Since 2.0.0. If true, skip connection for all sites.
|
8800 |
*/
|
8801 |
-
function skip_connection( $
|
8802 |
$this->_logger->entrance();
|
8803 |
|
8804 |
$this->_admin_notices->remove_sticky( 'connect_account' );
|
8805 |
|
8806 |
-
if ( $
|
8807 |
$this->set_anonymous_mode( true, true );
|
8808 |
-
}
|
8809 |
|
8810 |
-
|
8811 |
-
|
8812 |
-
|
8813 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8814 |
|
8815 |
-
|
8816 |
-
$
|
|
|
8817 |
|
8818 |
-
|
8819 |
-
|
8820 |
-
$
|
8821 |
-
$this->skip_site_connection( $blog_id, false );
|
8822 |
-
$uids[] = $this->get_anonymous_id( $blog_id );
|
8823 |
-
}
|
8824 |
-
} else if ( ! empty( $sites ) ) {
|
8825 |
-
foreach ( $sites as $site ) {
|
8826 |
-
$uids[] = $site['uid'];
|
8827 |
-
$this->skip_site_connection( $site['blog_id'], false );
|
8828 |
}
|
8829 |
}
|
|
|
8830 |
|
8831 |
-
|
8832 |
-
|
8833 |
-
$this->get_api_plugin_scope()->call( 'skip.json', 'put', array(
|
8834 |
-
'uids' => $uids,
|
8835 |
-
) );
|
8836 |
}
|
8837 |
|
8838 |
$this->network_upgrade_mode_completed();
|
@@ -8847,18 +9121,12 @@
|
|
8847 |
* @param int|null $blog_id
|
8848 |
* @param bool $send_skip
|
8849 |
*/
|
8850 |
-
private function skip_site_connection( $blog_id = null
|
8851 |
$this->_logger->entrance();
|
8852 |
|
8853 |
$this->_admin_notices->remove_sticky( 'connect_account', $blog_id );
|
8854 |
|
8855 |
$this->set_anonymous_mode( true, $blog_id );
|
8856 |
-
|
8857 |
-
if ( $send_skip ) {
|
8858 |
-
$this->get_api_plugin_scope()->call( 'skip.json', 'put', array(
|
8859 |
-
'uids' => array( $this->get_anonymous_id( $blog_id ) ),
|
8860 |
-
) );
|
8861 |
-
}
|
8862 |
}
|
8863 |
|
8864 |
/**
|
@@ -9230,7 +9498,7 @@
|
|
9230 |
* @param string[] $override
|
9231 |
* @param bool $include_plugins Since 1.1.8 by default include plugin changes.
|
9232 |
* @param bool $include_themes Since 1.1.8 by default include plugin changes.
|
9233 |
-
* @param bool $include_blog_data Since 2.3.0 by default include the current blog's data (language,
|
9234 |
*
|
9235 |
* @return array
|
9236 |
*/
|
@@ -9240,7 +9508,10 @@
|
|
9240 |
$include_themes = true,
|
9241 |
$include_blog_data = true
|
9242 |
) {
|
9243 |
-
|
|
|
|
|
|
|
9244 |
if ( ! defined( 'WP_FS__TRACK_PLUGINS' ) || false !== WP_FS__TRACK_PLUGINS ) {
|
9245 |
/**
|
9246 |
* @since 1.1.8 Also send plugin updates.
|
@@ -9268,21 +9539,23 @@
|
|
9268 |
|
9269 |
$versions = $this->get_versions();
|
9270 |
|
9271 |
-
$blog_data =
|
9272 |
-
|
9273 |
-
|
9274 |
-
|
9275 |
-
|
9276 |
-
|
9277 |
-
|
9278 |
-
|
|
|
|
|
|
|
9279 |
|
9280 |
return array_merge( $versions, $blog_data, array(
|
9281 |
'version' => $this->get_plugin_version(),
|
9282 |
'is_premium' => $this->is_premium(),
|
9283 |
// Special params.
|
9284 |
'is_active' => true,
|
9285 |
-
'is_disconnected' => $this->is_tracking_prohibited(),
|
9286 |
'is_uninstalled' => false,
|
9287 |
), $override );
|
9288 |
}
|
@@ -9297,6 +9570,7 @@
|
|
9297 |
*
|
9298 |
* @param string[] string $override
|
9299 |
* @param bool $only_diff
|
|
|
9300 |
* @param bool $include_plugins Since 1.1.8 by default include plugin changes.
|
9301 |
* @param bool $include_themes Since 1.1.8 by default include plugin changes.
|
9302 |
*
|
@@ -9305,6 +9579,7 @@
|
|
9305 |
private function get_installs_data_for_api(
|
9306 |
array $override,
|
9307 |
$only_diff = false,
|
|
|
9308 |
$include_plugins = true,
|
9309 |
$include_themes = true
|
9310 |
) {
|
@@ -9342,6 +9617,10 @@
|
|
9342 |
|
9343 |
$sites = self::get_sites();
|
9344 |
|
|
|
|
|
|
|
|
|
9345 |
foreach ( $sites as $site ) {
|
9346 |
$blog_id = self::get_site_blog_id( $site );
|
9347 |
|
@@ -9353,19 +9632,64 @@
|
|
9353 |
continue;
|
9354 |
}
|
9355 |
|
9356 |
-
if ( ! $this->
|
9357 |
// Don't send updates regarding opted-out installs.
|
9358 |
continue;
|
9359 |
}
|
9360 |
|
9361 |
-
$install_data = $this->get_site_info( $site );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9362 |
|
9363 |
-
|
|
|
|
|
|
|
|
|
|
|
9364 |
|
9365 |
unset( $install_data['blog_id'] );
|
9366 |
unset( $install_data['uid'] );
|
|
|
|
|
9367 |
|
9368 |
-
$install_data['is_disconnected'] = $install->is_disconnected;
|
9369 |
$install_data['is_active'] = $this->is_active_for_site( $blog_id );
|
9370 |
$install_data['is_uninstalled'] = $install->is_uninstalled;
|
9371 |
|
@@ -9388,18 +9712,26 @@
|
|
9388 |
$is_common_diff_for_any_site = $is_common_diff_for_any_site || $is_common_diff;
|
9389 |
}
|
9390 |
|
9391 |
-
if ( ! empty( $install_data ) || $is_common_diff ) {
|
9392 |
// Add install ID and site unique ID.
|
9393 |
$install_data['id'] = $install->id;
|
9394 |
$install_data['uid'] = $uid;
|
|
|
9395 |
|
9396 |
-
$
|
|
|
|
|
9397 |
}
|
9398 |
}
|
9399 |
}
|
9400 |
|
9401 |
restore_current_blog();
|
9402 |
|
|
|
|
|
|
|
|
|
|
|
9403 |
if ( 0 < count( $installs_data ) && ( $is_common_diff_for_any_site || ! $only_diff ) ) {
|
9404 |
if ( ! $only_diff ) {
|
9405 |
$installs_data[] = $common;
|
@@ -9437,8 +9769,12 @@
|
|
9437 |
if ( ( is_bool( $install->{$p} ) || ! empty( $install->{$p} ) ) &&
|
9438 |
$install->{$p} != $v
|
9439 |
) {
|
9440 |
-
$
|
9441 |
-
|
|
|
|
|
|
|
|
|
9442 |
}
|
9443 |
} else {
|
9444 |
$special[ $p ] = $v;
|
@@ -9463,6 +9799,78 @@
|
|
9463 |
return $diff;
|
9464 |
}
|
9465 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9466 |
/**
|
9467 |
* Update install only if changed.
|
9468 |
*
|
@@ -9471,10 +9879,11 @@
|
|
9471 |
*
|
9472 |
* @param string[] string $override
|
9473 |
* @param bool $flush
|
|
|
9474 |
*
|
9475 |
* @return false|object|string
|
9476 |
*/
|
9477 |
-
private function send_install_update( $override = array(), $flush = false ) {
|
9478 |
$this->_logger->entrance();
|
9479 |
|
9480 |
$check_properties = $this->get_install_data_for_api( $override );
|
@@ -9485,7 +9894,6 @@
|
|
9485 |
$params = $this->get_install_diff_for_api( $check_properties, $this->_site, $override );
|
9486 |
}
|
9487 |
|
9488 |
-
$keepalive_only_update = false;
|
9489 |
if ( empty( $params ) ) {
|
9490 |
$keepalive_only_update = $this->should_send_keepalive_update();
|
9491 |
|
@@ -9500,10 +9908,9 @@
|
|
9500 |
}
|
9501 |
}
|
9502 |
|
9503 |
-
if (
|
9504 |
/**
|
9505 |
-
*
|
9506 |
-
* updates sent.
|
9507 |
*
|
9508 |
* @author Leo Fajardo (@leorw)
|
9509 |
* @since 2.2.3
|
@@ -9519,11 +9926,11 @@
|
|
9519 |
$this->set_keepalive_timestamp();
|
9520 |
|
9521 |
// Send updated values to FS.
|
9522 |
-
$site = $this->
|
9523 |
|
9524 |
-
if (
|
9525 |
/**
|
9526 |
-
*
|
9527 |
*
|
9528 |
* @author Leo Fajardo (@leorw)
|
9529 |
* @since 2.2.3
|
@@ -9545,37 +9952,29 @@
|
|
9545 |
*
|
9546 |
* @param string[] string $override
|
9547 |
* @param bool $flush
|
|
|
9548 |
*
|
9549 |
* @return false|object|string
|
9550 |
*/
|
9551 |
-
private function send_installs_update( $override = array(), $flush = false ) {
|
9552 |
$this->_logger->entrance();
|
9553 |
|
9554 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
9555 |
|
9556 |
-
$
|
9557 |
-
if ( empty( $installs_data ) ) {
|
9558 |
-
/**
|
9559 |
-
* Pass `true` to use the network level storage since the update is for many installs.
|
9560 |
-
*
|
9561 |
-
* @author Leo Fajardo (@leorw)
|
9562 |
-
* @since 2.2.3
|
9563 |
-
*/
|
9564 |
-
$keepalive_only_update = $this->should_send_keepalive_update( true );
|
9565 |
|
9566 |
-
|
9567 |
-
|
9568 |
-
* There are no updates to send including keepalive.
|
9569 |
-
*
|
9570 |
-
* @author Leo Fajardo (@leorw)
|
9571 |
-
* @since 2.2.3
|
9572 |
-
*/
|
9573 |
-
return false;
|
9574 |
-
}
|
9575 |
}
|
9576 |
|
9577 |
-
if (
|
9578 |
-
// Update last install sync timestamp
|
9579 |
$this->set_cron_execution_timestamp( 'install_sync' );
|
9580 |
}
|
9581 |
|
@@ -9590,8 +9989,8 @@
|
|
9590 |
// Send updated values to FS.
|
9591 |
$result = $this->get_api_user_scope()->call( "/plugins/{$this->_plugin->id}/installs.json", 'put', $installs_data );
|
9592 |
|
9593 |
-
if (
|
9594 |
-
// I successfully sent
|
9595 |
$this->clear_install_sync_cron();
|
9596 |
}
|
9597 |
|
@@ -9641,10 +10040,10 @@
|
|
9641 |
* @param string[] string $override
|
9642 |
* @param bool $flush
|
9643 |
*/
|
9644 |
-
|
9645 |
$this->_logger->entrance();
|
9646 |
|
9647 |
-
$site = $this->send_install_update( $override, $flush );
|
9648 |
|
9649 |
if ( false === $site ) {
|
9650 |
// No sync required.
|
@@ -9673,7 +10072,7 @@
|
|
9673 |
private function sync_installs( $override = array(), $flush = false ) {
|
9674 |
$this->_logger->entrance();
|
9675 |
|
9676 |
-
$result = $this->send_installs_update( $override, $flush );
|
9677 |
|
9678 |
if ( false === $result ) {
|
9679 |
// No sync required.
|
@@ -9828,8 +10227,8 @@
|
|
9828 |
// Send uninstall event.
|
9829 |
$this->send_installs_update( $params );
|
9830 |
} else {
|
9831 |
-
// Send uninstall event.
|
9832 |
-
$this->
|
9833 |
}
|
9834 |
}
|
9835 |
|
@@ -9926,7 +10325,17 @@
|
|
9926 |
return;
|
9927 |
}
|
9928 |
|
9929 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9930 |
|
9931 |
$fs->do_action( 'after_uninstall' );
|
9932 |
}
|
@@ -10037,7 +10446,7 @@
|
|
10037 |
* @return string
|
10038 |
*/
|
10039 |
function get_premium_slug() {
|
10040 |
-
return is_object( $this->_plugin ) ?
|
10041 |
$this->_plugin->premium_slug :
|
10042 |
"{$this->_slug}-premium";
|
10043 |
}
|
@@ -10090,6 +10499,28 @@
|
|
10090 |
null;
|
10091 |
}
|
10092 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10093 |
/**
|
10094 |
* @author Vova Feldman (@svovaf)
|
10095 |
* @since 1.2.1.5
|
@@ -10134,7 +10565,7 @@
|
|
10134 |
function get_eula_url() {
|
10135 |
return $this->apply_filters(
|
10136 |
'eula_url',
|
10137 |
-
"https://freemius.com/
|
10138 |
);
|
10139 |
}
|
10140 |
|
@@ -10322,7 +10753,7 @@
|
|
10322 |
#endregion ------------------------------------------------------------------
|
10323 |
|
10324 |
/* Account
|
10325 |
-
|
10326 |
|
10327 |
/**
|
10328 |
* Find plugin's slug by plugin's basename.
|
@@ -10386,9 +10817,14 @@
|
|
10386 |
*/
|
10387 |
private static function get_all_sites(
|
10388 |
$module_type = WP_FS__MODULE_TYPE_PLUGIN,
|
10389 |
-
$blog_id = null
|
|
|
10390 |
) {
|
10391 |
-
$sites = self::get_account_option(
|
|
|
|
|
|
|
|
|
10392 |
|
10393 |
if ( ! is_array( $sites ) ) {
|
10394 |
$sites = array();
|
@@ -10748,10 +11184,20 @@
|
|
10748 |
*
|
10749 |
* @author Vova Feldman (@svovaf)
|
10750 |
* @since 1.0.1
|
|
|
|
|
|
|
10751 |
* @return bool
|
10752 |
*/
|
10753 |
-
function is_registered() {
|
10754 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10755 |
}
|
10756 |
|
10757 |
/**
|
@@ -10762,8 +11208,34 @@
|
|
10762 |
*
|
10763 |
* @return bool
|
10764 |
*/
|
10765 |
-
function is_tracking_allowed() {
|
10766 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10767 |
}
|
10768 |
|
10769 |
/**
|
@@ -10799,13 +11271,59 @@
|
|
10799 |
}
|
10800 |
|
10801 |
/**
|
10802 |
-
* @author Vova Feldman (@svovaf)
|
10803 |
-
* @since 1.0.3
|
10804 |
-
*
|
10805 |
-
* @return FS_Site
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10806 |
*/
|
10807 |
-
function
|
10808 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
10809 |
}
|
10810 |
|
10811 |
/**
|
@@ -12089,7 +12607,7 @@
|
|
12089 |
} else {
|
12090 |
$url = is_object( $site ) ?
|
12091 |
$site->siteurl :
|
12092 |
-
|
12093 |
|
12094 |
$disconnected_site_ids[] = $blog_id;
|
12095 |
}
|
@@ -12462,7 +12980,21 @@
|
|
12462 |
} else if ( $is_whitelabeled_flag ) {
|
12463 |
$is_whitelabeled = true;
|
12464 |
} else {
|
12465 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12466 |
$installed_addons = $this->get_installed_addons();
|
12467 |
foreach ( $installed_addons as $fs_addon ) {
|
12468 |
$addon_ids[] = $fs_addon->get_id();
|
@@ -12891,6 +13423,75 @@
|
|
12891 |
fs_require_template( 'forms/resend-key.php', $vars );
|
12892 |
}
|
12893 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12894 |
/**
|
12895 |
* Returns a collection of IDs of installs that are associated with the context product and its add-ons, and activated with foreign licenses.
|
12896 |
*
|
@@ -13098,10 +13699,15 @@
|
|
13098 |
( $is_network_admin && $this->is_network_active() && ! $this->is_network_delegated_connection() ) ||
|
13099 |
( ! $is_network_admin && ( ! $this->is_network_active() || $this->is_delegated_connection() ) )
|
13100 |
) {
|
13101 |
-
|
13102 |
-
|
13103 |
-
|
13104 |
-
|
|
|
|
|
|
|
|
|
|
|
13105 |
}
|
13106 |
}
|
13107 |
|
@@ -13273,7 +13879,7 @@
|
|
13273 |
self::shoot_ajax_failure();
|
13274 |
}
|
13275 |
|
13276 |
-
$site = $this->
|
13277 |
'',
|
13278 |
'put',
|
13279 |
array(
|
@@ -13326,7 +13932,8 @@
|
|
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 (
|
@@ -13571,6 +14178,9 @@
|
|
13571 |
* @param null|int $blog_id
|
13572 |
* @param null|number $plugin_id
|
13573 |
* @param null|number $license_owner_id
|
|
|
|
|
|
|
13574 |
*
|
13575 |
* @return array {
|
13576 |
* @var bool $success
|
@@ -13585,7 +14195,8 @@
|
|
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 |
|
@@ -13605,7 +14216,10 @@
|
|
13605 |
$this :
|
13606 |
$this->get_addon_instance( $plugin_id );
|
13607 |
|
13608 |
-
$this->
|
|
|
|
|
|
|
13609 |
|
13610 |
$error = false;
|
13611 |
$next_page = false;
|
@@ -13770,8 +14384,8 @@
|
|
13770 |
}
|
13771 |
}
|
13772 |
|
13773 |
-
$all_sites
|
13774 |
-
$
|
13775 |
|
13776 |
/**
|
13777 |
* Check if there are any sites that are not connected, skipped, nor delegated. For every site that falls into that category, if the product is freemium, skip the connection. If the product is premium only, delegate the connection to the site administrator.
|
@@ -13801,14 +14415,14 @@
|
|
13801 |
continue;
|
13802 |
}
|
13803 |
|
13804 |
-
$
|
13805 |
}
|
13806 |
|
13807 |
-
if ( ! empty( $
|
13808 |
if ( $fs->is_freemium() && $fs->is_enable_anonymous() ) {
|
13809 |
-
$fs->skip_connection( $
|
13810 |
} else {
|
13811 |
-
$fs->delegate_connection( $
|
13812 |
}
|
13813 |
}
|
13814 |
}
|
@@ -13886,7 +14500,7 @@
|
|
13886 |
|
13887 |
$addon_info = $fs->_get_addon_info( $addon_id, $is_installed );
|
13888 |
|
13889 |
-
if ( ! $addon_info['is_connected'] ) {
|
13890 |
// Add-on is not associated with an install entity.
|
13891 |
continue;
|
13892 |
}
|
@@ -13944,11 +14558,11 @@
|
|
13944 |
$this->delegate_connection();
|
13945 |
} else {
|
13946 |
if ( ! empty( $sites_by_action['delegate'] ) ) {
|
13947 |
-
$this->delegate_connection( $sites_by_action['delegate'] );
|
13948 |
}
|
13949 |
|
13950 |
if ( ! empty( $sites_by_action['skip'] ) ) {
|
13951 |
-
$this->skip_connection( $sites_by_action['skip'] );
|
13952 |
}
|
13953 |
|
13954 |
if ( empty( $sites_by_action['allow'] ) ) {
|
@@ -14266,15 +14880,37 @@
|
|
14266 |
return $this->_plugin->has_affiliate_program();
|
14267 |
}
|
14268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14269 |
/**
|
14270 |
* @author Leo Fajardo (@leorw)
|
14271 |
* @since 1.2.4
|
14272 |
*/
|
14273 |
private function fetch_affiliate_terms() {
|
14274 |
if ( ! is_object( $this->plugin_affiliate_terms ) ) {
|
14275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
14276 |
$affiliate_terms = $plugins_api->get( '/aff.json?type=affiliation', false );
|
14277 |
|
|
|
|
|
|
|
14278 |
if ( ! $this->is_api_result_entity( $affiliate_terms ) ) {
|
14279 |
return;
|
14280 |
}
|
@@ -14292,8 +14928,10 @@
|
|
14292 |
$application_data = $this->_storage->affiliate_application_data;
|
14293 |
$flush = ( ! isset( $application_data['status'] ) || 'pending' === $application_data['status'] );
|
14294 |
|
|
|
|
|
14295 |
$users_api = $this->get_api_user_scope();
|
14296 |
-
$result = $users_api->get( "/plugins/{$
|
14297 |
if ( $this->is_api_result_object( $result, 'affiliates' ) ) {
|
14298 |
if ( ! empty( $result->affiliates ) ) {
|
14299 |
$affiliate = new FS_Affiliate( $result->affiliates[0] );
|
@@ -14393,15 +15031,17 @@
|
|
14393 |
var_export( $next_page, true )
|
14394 |
);
|
14395 |
} else if ( $this->is_pending_activation() ) {
|
14396 |
-
self::shoot_ajax_failure( $this->get_text_inline( 'Account is pending activation.', 'account-is-pending-activation' ) );
|
14397 |
}
|
14398 |
}
|
14399 |
|
14400 |
$this->fetch_affiliate_terms();
|
14401 |
|
|
|
|
|
14402 |
$api = $this->get_api_user_scope();
|
14403 |
$result = $api->call(
|
14404 |
-
( "/plugins/{$
|
14405 |
'post',
|
14406 |
$affiliate
|
14407 |
);
|
@@ -14863,6 +15503,16 @@
|
|
14863 |
return ( defined( 'DOING_CRON' ) && DOING_CRON );
|
14864 |
}
|
14865 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14866 |
/**
|
14867 |
* Check if a real user is visiting the admin dashboard.
|
14868 |
*
|
@@ -14876,7 +15526,7 @@
|
|
14876 |
is_admin() &&
|
14877 |
! self::is_ajax() &&
|
14878 |
! self::is_cron() &&
|
14879 |
-
|
14880 |
);
|
14881 |
}
|
14882 |
|
@@ -15028,20 +15678,20 @@
|
|
15028 |
* @author Leo Fajardo (@leorw)
|
15029 |
* @since 2.0.0
|
15030 |
*
|
15031 |
-
* @param
|
15032 |
*/
|
15033 |
-
private function delegate_connection( $
|
15034 |
$this->_logger->entrance();
|
15035 |
|
15036 |
$this->_admin_notices->remove_sticky( 'connect_account' );
|
15037 |
|
15038 |
-
if (
|
15039 |
// All sites delegation.
|
15040 |
-
$this->_storage->store( 'is_delegated_connection', true, true
|
15041 |
} else {
|
15042 |
// Specified sites delegation.
|
15043 |
-
foreach ( $
|
15044 |
-
$this->delegate_site_connection( $
|
15045 |
}
|
15046 |
}
|
15047 |
|
@@ -15057,7 +15707,7 @@
|
|
15057 |
* @param int $blog_id
|
15058 |
*/
|
15059 |
private function delegate_site_connection( $blog_id ) {
|
15060 |
-
$this->_storage->store( 'is_delegated_connection', true, $blog_id
|
15061 |
}
|
15062 |
|
15063 |
/**
|
@@ -15097,7 +15747,7 @@
|
|
15097 |
}
|
15098 |
|
15099 |
/**
|
15100 |
-
* Check if delegated the connection. When running within the
|
15101 |
* and haven't specified the blog ID, checks if network level delegated. If running
|
15102 |
* within a site admin or specified a blog ID, check if delegated the connection for
|
15103 |
* the current context site.
|
@@ -15157,12 +15807,17 @@
|
|
15157 |
}
|
15158 |
|
15159 |
/**
|
|
|
|
|
15160 |
* @author Leo Fajardo (@leorw)
|
15161 |
* @since 2.0.0
|
15162 |
*
|
|
|
|
|
|
|
15163 |
* @return array Active & public sites collection.
|
15164 |
*/
|
15165 |
-
static function get_sites() {
|
15166 |
if ( ! is_multisite() ) {
|
15167 |
return array();
|
15168 |
}
|
@@ -15184,27 +15839,11 @@
|
|
15184 |
'mature' => 0,
|
15185 |
'spam' => 0,
|
15186 |
'deleted' => 0,
|
|
|
|
|
15187 |
);
|
15188 |
|
15189 |
-
|
15190 |
-
// For WP 4.6 and above.
|
15191 |
-
return get_sites( $args );
|
15192 |
-
} else if ( function_exists( 'wp_' . 'get_sites' ) ) {
|
15193 |
-
// For WP 3.7 to WP 4.5.
|
15194 |
-
/**
|
15195 |
-
* This is a hack suggested previously proposed by the TRT. Our SDK is compliant with older WP versions and we'd like to keep it that way.
|
15196 |
-
*
|
15197 |
-
* @todo Remove this hack once this false-positive error is removed from the Theme Sniffer.
|
15198 |
-
*
|
15199 |
-
* @since 2.3.3
|
15200 |
-
* @author Vova Feldman (@svovaf)
|
15201 |
-
*/
|
15202 |
-
$fn = 'wp_' . 'get_sites';
|
15203 |
-
return $fn( $args );
|
15204 |
-
} else {
|
15205 |
-
// For WP 3.6 and below.
|
15206 |
-
return get_blog_list( 0, 'all' );
|
15207 |
-
}
|
15208 |
}
|
15209 |
|
15210 |
/**
|
@@ -15253,7 +15892,7 @@
|
|
15253 |
$address_to_blog_map = array();
|
15254 |
foreach ( $sites as $site ) {
|
15255 |
$blog_id = self::get_site_blog_id( $site );
|
15256 |
-
$address =
|
15257 |
$address_to_blog_map[ $address ] = $blog_id;
|
15258 |
}
|
15259 |
|
@@ -15289,6 +15928,42 @@
|
|
15289 |
return $install_map;
|
15290 |
}
|
15291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15292 |
/**
|
15293 |
* Gets a map of module IDs that the given user has opted-in to.
|
15294 |
*
|
@@ -15373,11 +16048,16 @@
|
|
15373 |
*
|
15374 |
* @param int $blog_id
|
15375 |
* @param FS_Site $install
|
|
|
15376 |
*
|
15377 |
* @return bool Since 2.3.1 returns if a switch was made.
|
15378 |
*/
|
15379 |
-
function switch_to_blog( $blog_id, FS_Site $install = null ) {
|
15380 |
-
if ( ! is_numeric( $blog_id )
|
|
|
|
|
|
|
|
|
15381 |
return false;
|
15382 |
}
|
15383 |
|
@@ -15441,7 +16121,7 @@
|
|
15441 |
unset( $this->_site_api );
|
15442 |
unset( $this->_user_api );
|
15443 |
|
15444 |
-
return
|
15445 |
}
|
15446 |
|
15447 |
/**
|
@@ -15470,21 +16150,41 @@
|
|
15470 |
$site['blog_id'] );
|
15471 |
}
|
15472 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15473 |
/**
|
15474 |
* @author Leo Fajardo (@leorw)
|
15475 |
* @since 2.0.0
|
15476 |
*
|
15477 |
* @param array|WP_Site|null $site
|
|
|
15478 |
*
|
15479 |
* @return array
|
15480 |
*/
|
15481 |
-
function get_site_info( $site = null ) {
|
15482 |
$this->_logger->entrance();
|
15483 |
|
15484 |
$switched = false;
|
15485 |
|
|
|
|
|
15486 |
if ( is_null( $site ) ) {
|
15487 |
-
$url =
|
15488 |
$name = get_bloginfo( 'name' );
|
15489 |
$blog_id = null;
|
15490 |
} else {
|
@@ -15496,26 +16196,44 @@
|
|
15496 |
}
|
15497 |
|
15498 |
if ( $site instanceof WP_Site ) {
|
15499 |
-
$url
|
15500 |
-
$name
|
|
|
15501 |
} else {
|
15502 |
-
$url =
|
15503 |
$name = get_bloginfo( 'name' );
|
15504 |
}
|
15505 |
}
|
15506 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15507 |
$info = array(
|
15508 |
-
'uid'
|
15509 |
-
'url'
|
15510 |
-
'title' => $name,
|
15511 |
-
'language' => get_bloginfo( 'language' ),
|
15512 |
-
'charset' => get_bloginfo( 'charset' ),
|
15513 |
);
|
15514 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15515 |
if ( is_numeric( $blog_id ) ) {
|
15516 |
$info['blog_id'] = $blog_id;
|
15517 |
}
|
15518 |
|
|
|
|
|
|
|
|
|
15519 |
if ( $switched ) {
|
15520 |
restore_current_blog();
|
15521 |
}
|
@@ -15738,6 +16456,10 @@
|
|
15738 |
}
|
15739 |
}
|
15740 |
|
|
|
|
|
|
|
|
|
15741 |
if ( $this->is_sync_cron_scheduled() &&
|
15742 |
$context_blog_id == $this->get_sync_cron_blog_id()
|
15743 |
) {
|
@@ -15771,6 +16493,10 @@
|
|
15771 |
|
15772 |
$this->update_multisite_data_after_site_deactivation( $context_blog_id );
|
15773 |
|
|
|
|
|
|
|
|
|
15774 |
$current_blog_id = get_current_blog_id();
|
15775 |
|
15776 |
$this->switch_to_blog( $context_blog_id );
|
@@ -15804,6 +16530,10 @@
|
|
15804 |
|
15805 |
$this->update_multisite_data_after_site_deactivation( $context_blog_id );
|
15806 |
|
|
|
|
|
|
|
|
|
15807 |
$current_blog_id = get_current_blog_id();
|
15808 |
|
15809 |
$this->switch_to_blog( $context_blog_id );
|
@@ -15821,6 +16551,20 @@
|
|
15821 |
$this->switch_to_blog( $current_blog_id );
|
15822 |
}
|
15823 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15824 |
/**
|
15825 |
* Executed after site re-activation.
|
15826 |
*
|
@@ -15935,9 +16679,17 @@
|
|
15935 |
* @return bool
|
15936 |
*/
|
15937 |
function is_product_settings_page() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15938 |
return fs_starts_with(
|
15939 |
-
|
15940 |
-
$
|
|
|
15941 |
);
|
15942 |
}
|
15943 |
|
@@ -16017,10 +16769,11 @@
|
|
16017 |
*
|
16018 |
* @param bool|string $topic
|
16019 |
* @param bool|string $message
|
|
|
16020 |
*
|
16021 |
* @return string
|
16022 |
*/
|
16023 |
-
function contact_url( $topic = false, $message = false ) {
|
16024 |
$params = array();
|
16025 |
if ( is_string( $topic ) ) {
|
16026 |
$params['topic'] = $topic;
|
@@ -16029,6 +16782,10 @@
|
|
16029 |
$params['message'] = $message;
|
16030 |
}
|
16031 |
|
|
|
|
|
|
|
|
|
16032 |
if ( $this->is_addon() ) {
|
16033 |
$params['addon_id'] = $this->get_id();
|
16034 |
|
@@ -16067,7 +16824,7 @@
|
|
16067 |
}
|
16068 |
|
16069 |
/* Logger
|
16070 |
-
|
16071 |
/**
|
16072 |
* @param string $id
|
16073 |
* @param bool $prefix_slug
|
@@ -16092,7 +16849,7 @@
|
|
16092 |
}
|
16093 |
|
16094 |
/* Security
|
16095 |
-
|
16096 |
private static function _encrypt( $str ) {
|
16097 |
if ( is_null( $str ) ) {
|
16098 |
return null;
|
@@ -16312,20 +17069,6 @@
|
|
16312 |
) {
|
16313 |
// Load site.
|
16314 |
$this->_site = $site;
|
16315 |
-
|
16316 |
-
// Load plans.
|
16317 |
-
$this->_plans = $plans[ $this->_slug ];
|
16318 |
-
if ( ! is_array( $this->_plans ) || empty( $this->_plans ) ) {
|
16319 |
-
$this->_sync_plans();
|
16320 |
-
} else {
|
16321 |
-
for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) {
|
16322 |
-
if ( $this->_plans[ $i ] instanceof FS_Plugin_Plan ) {
|
16323 |
-
$this->_plans[ $i ] = self::decrypt_entity( $this->_plans[ $i ] );
|
16324 |
-
} else {
|
16325 |
-
unset( $this->_plans[ $i ] );
|
16326 |
-
}
|
16327 |
-
}
|
16328 |
-
}
|
16329 |
}
|
16330 |
|
16331 |
$user = null;
|
@@ -16354,7 +17097,30 @@
|
|
16354 |
/**
|
16355 |
* This is a special fault tolerance mechanism to handle a scenario that the user data is missing.
|
16356 |
*/
|
16357 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16358 |
}
|
16359 |
|
16360 |
$this->_user = ( $user instanceof FS_User ) ?
|
@@ -16368,6 +17134,23 @@
|
|
16368 |
}
|
16369 |
|
16370 |
if ( is_object( $this->_site ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16371 |
$this->_license = $this->_get_license_by_id( $this->_site->license_id );
|
16372 |
|
16373 |
if ( $this->_site->version != $this->get_plugin_version() ) {
|
@@ -16386,6 +17169,15 @@
|
|
16386 |
if ( $this->is_theme() ) {
|
16387 |
$this->_register_account_hooks();
|
16388 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16389 |
}
|
16390 |
|
16391 |
/**
|
@@ -16465,17 +17257,129 @@
|
|
16465 |
*/
|
16466 |
private function get_versions() {
|
16467 |
$versions = array();
|
16468 |
-
$versions['
|
16469 |
-
|
16470 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16471 |
|
16472 |
-
|
16473 |
-
|
16474 |
-
|
16475 |
-
|
|
|
|
|
|
|
16476 |
}
|
16477 |
|
16478 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16479 |
}
|
16480 |
|
16481 |
/**
|
@@ -16530,23 +17434,22 @@
|
|
16530 |
$versions = $this->get_versions();
|
16531 |
|
16532 |
$params = array_merge( $versions, array(
|
16533 |
-
'user_firstname'
|
16534 |
-
'user_lastname'
|
16535 |
-
'
|
16536 |
-
'
|
16537 |
-
'
|
16538 |
-
'
|
16539 |
-
'
|
16540 |
-
'
|
16541 |
-
'
|
16542 |
-
'return_url' => fs_nonce_url( $return_url, $activation_action ),
|
16543 |
-
'account_url' => fs_nonce_url( $this->_get_admin_page_url(
|
16544 |
'account',
|
16545 |
array( 'fs_action' => 'sync_user' )
|
16546 |
), 'sync_user' ),
|
16547 |
-
'is_premium'
|
16548 |
-
'is_active'
|
16549 |
-
'is_uninstalled'
|
|
|
16550 |
) );
|
16551 |
|
16552 |
if ( $this->is_addon() ) {
|
@@ -16567,12 +17470,17 @@
|
|
16567 |
|
16568 |
$site = $this->get_site_info( $site );
|
16569 |
|
16570 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16571 |
'site_uid' => $site['uid'],
|
16572 |
'site_url' => $site['url'],
|
16573 |
-
'site_name' => $site['title'],
|
16574 |
-
'language' => $site['language'],
|
16575 |
-
'charset' => $site['charset'],
|
16576 |
) );
|
16577 |
}
|
16578 |
|
@@ -16597,6 +17505,10 @@
|
|
16597 |
);
|
16598 |
}
|
16599 |
|
|
|
|
|
|
|
|
|
16600 |
return array_merge( $params, $override_with );
|
16601 |
}
|
16602 |
|
@@ -16615,9 +17527,10 @@
|
|
16615 |
* In this case, the user and site info will be sent to the server but no
|
16616 |
* data will be saved to the WP installation's database.
|
16617 |
* @param number|bool $trial_plan_id
|
16618 |
-
* @param bool $is_disconnected Whether
|
16619 |
* @param null|bool $is_marketing_allowed
|
16620 |
* @param array $sites If network-level opt-in, an array of containing details of sites.
|
|
|
16621 |
*
|
16622 |
* @return string|object
|
16623 |
* @use WP_Error
|
@@ -16631,7 +17544,8 @@
|
|
16631 |
$trial_plan_id = false,
|
16632 |
$is_disconnected = false,
|
16633 |
$is_marketing_allowed = null,
|
16634 |
-
$sites = array()
|
|
|
16635 |
) {
|
16636 |
$this->_logger->entrance();
|
16637 |
|
@@ -16655,7 +17569,7 @@
|
|
16655 |
$fs_user,
|
16656 |
false,
|
16657 |
$trial_plan_id,
|
16658 |
-
|
16659 |
true,
|
16660 |
$sites
|
16661 |
);
|
@@ -16723,13 +17637,15 @@
|
|
16723 |
$params['is_marketing_allowed'] = $is_marketing_allowed;
|
16724 |
}
|
16725 |
|
16726 |
-
$params['is_disconnected']
|
16727 |
-
$params['format']
|
|
|
|
|
16728 |
|
16729 |
$request = array(
|
16730 |
'method' => 'POST',
|
16731 |
'body' => $params,
|
16732 |
-
'timeout' =>
|
16733 |
);
|
16734 |
|
16735 |
$url = $this->add_show_pending( WP_FS__ADDRESS . '/action/service/user/install/' );
|
@@ -16815,7 +17731,8 @@
|
|
16815 |
true ),
|
16816 |
false,
|
16817 |
$filtered_license_key,
|
16818 |
-
! empty( $params['trial_plan_id'] )
|
|
|
16819 |
);
|
16820 |
} else if ( isset( $decoded->install_secret_key ) ) {
|
16821 |
return $this->install_with_new_user(
|
@@ -16828,6 +17745,9 @@
|
|
16828 |
( isset( $decoded->is_extensions_tracking_allowed ) && ! is_null( $decoded->is_extensions_tracking_allowed ) ?
|
16829 |
$decoded->is_extensions_tracking_allowed :
|
16830 |
null ),
|
|
|
|
|
|
|
16831 |
$decoded->install_id,
|
16832 |
$decoded->install_public_key,
|
16833 |
$decoded->install_secret_key,
|
@@ -16844,6 +17764,9 @@
|
|
16844 |
( isset( $decoded->is_extensions_tracking_allowed ) && ! is_null( $decoded->is_extensions_tracking_allowed ) ?
|
16845 |
$decoded->is_extensions_tracking_allowed :
|
16846 |
null ),
|
|
|
|
|
|
|
16847 |
$decoded->installs,
|
16848 |
false
|
16849 |
);
|
@@ -16941,15 +17864,11 @@
|
|
16941 |
$this->_admin_notices->remove_sticky( 'connect_account' );
|
16942 |
|
16943 |
if ( $this->is_pending_activation() || ! $this->has_settings_menu() ) {
|
16944 |
-
|
16945 |
-
$this->_admin_notices->remove_sticky( 'activation_pending' );
|
16946 |
-
|
16947 |
-
// Remove plugin from pending activation mode.
|
16948 |
-
unset( $this->_storage->is_pending_activation );
|
16949 |
|
16950 |
if ( ! $this->is_paying_or_trial() ) {
|
16951 |
$this->_admin_notices->add_sticky(
|
16952 |
-
sprintf( $this->get_text_inline( '%s
|
16953 |
'activation_complete'
|
16954 |
);
|
16955 |
}
|
@@ -17071,6 +17990,7 @@
|
|
17071 |
fs_request_get( 'user_secret_key' ),
|
17072 |
fs_request_get_bool( 'is_marketing_allowed', null ),
|
17073 |
fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
|
|
|
17074 |
$pending_sites_info['blog_ids'],
|
17075 |
$pending_sites_info['license_key'],
|
17076 |
$pending_sites_info['trial_plan_id']
|
@@ -17082,6 +18002,7 @@
|
|
17082 |
fs_request_get( 'user_secret_key' ),
|
17083 |
fs_request_get_bool( 'is_marketing_allowed', null ),
|
17084 |
fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
|
|
|
17085 |
fs_request_get( 'install_id' ),
|
17086 |
fs_request_get( 'install_public_key' ),
|
17087 |
fs_request_get( 'install_secret_key' ),
|
@@ -17090,7 +18011,13 @@
|
|
17090 |
);
|
17091 |
}
|
17092 |
} else if ( fs_request_has( 'pending_activation' ) ) {
|
17093 |
-
$this->set_pending_confirmation(
|
|
|
|
|
|
|
|
|
|
|
|
|
17094 |
}
|
17095 |
}
|
17096 |
}
|
@@ -17138,6 +18065,7 @@
|
|
17138 |
* @param string $user_secret_key
|
17139 |
* @param bool|null $is_marketing_allowed
|
17140 |
* @param bool|null $is_extensions_tracking_allowed Since 2.3.2
|
|
|
17141 |
* @param number $install_id
|
17142 |
* @param string $install_public_key
|
17143 |
* @param string $install_secret_key
|
@@ -17152,6 +18080,7 @@
|
|
17152 |
$user_secret_key,
|
17153 |
$is_marketing_allowed,
|
17154 |
$is_extensions_tracking_allowed,
|
|
|
17155 |
$install_id,
|
17156 |
$install_public_key,
|
17157 |
$install_secret_key,
|
@@ -17185,7 +18114,7 @@
|
|
17185 |
$site->secret_key = $install_secret_key;
|
17186 |
|
17187 |
$this->_site = $site;
|
17188 |
-
$site_result = $this->get_api_site_scope()->get();
|
17189 |
$site = new FS_Site( $site_result );
|
17190 |
$this->_site = $site;
|
17191 |
|
@@ -17193,7 +18122,10 @@
|
|
17193 |
$this->disable_opt_in_notice_and_lock_user();
|
17194 |
}
|
17195 |
|
17196 |
-
$this->
|
|
|
|
|
|
|
17197 |
|
17198 |
return $this->setup_account(
|
17199 |
$this->_user,
|
@@ -17214,6 +18146,7 @@
|
|
17214 |
* @param string $user_secret_key
|
17215 |
* @param bool|null $is_marketing_allowed
|
17216 |
* @param bool|null $is_extensions_tracking_allowed Since 2.3.2
|
|
|
17217 |
* @param array $site_ids
|
17218 |
* @param bool $license_key
|
17219 |
* @param bool $trial_plan_id
|
@@ -17227,6 +18160,7 @@
|
|
17227 |
$user_secret_key,
|
17228 |
$is_marketing_allowed,
|
17229 |
$is_extensions_tracking_allowed,
|
|
|
17230 |
$site_ids,
|
17231 |
$license_key = false,
|
17232 |
$trial_plan_id = false,
|
@@ -17238,7 +18172,10 @@
|
|
17238 |
$this->disable_opt_in_notice_and_lock_user();
|
17239 |
}
|
17240 |
|
17241 |
-
$this->
|
|
|
|
|
|
|
17242 |
|
17243 |
$sites = array();
|
17244 |
foreach ( $site_ids as $site_id ) {
|
@@ -17259,6 +18196,7 @@
|
|
17259 |
* @param string $user_secret_key
|
17260 |
* @param bool|null $is_marketing_allowed
|
17261 |
* @param bool|null $is_extensions_tracking_allowed Since 2.3.2
|
|
|
17262 |
* @param object[] $installs
|
17263 |
* @param bool $redirect
|
17264 |
* @param bool $auto_install Since 1.2.1.7 If `true` and setting up an account with a valid license, will redirect (or return a URL) to the account page with a special parameter to trigger the auto installation processes.
|
@@ -17271,6 +18209,7 @@
|
|
17271 |
$user_secret_key,
|
17272 |
$is_marketing_allowed,
|
17273 |
$is_extensions_tracking_allowed,
|
|
|
17274 |
array $installs,
|
17275 |
$redirect = true,
|
17276 |
$auto_install = false
|
@@ -17281,7 +18220,10 @@
|
|
17281 |
$this->disable_opt_in_notice_and_lock_user();
|
17282 |
}
|
17283 |
|
17284 |
-
$this->
|
|
|
|
|
|
|
17285 |
|
17286 |
$install_ids = array();
|
17287 |
|
@@ -17289,12 +18231,13 @@
|
|
17289 |
$install_ids[] = $install->id;
|
17290 |
}
|
17291 |
|
17292 |
-
$
|
17293 |
-
$
|
|
|
17294 |
|
17295 |
$installs = array();
|
17296 |
while ( $left > 0 ) {
|
17297 |
-
$result = $this->get_api_user_scope()->get( "/plugins/{$this->_module_id}/installs.json?ids=" . implode( ',', array_slice( $install_ids, $offset,
|
17298 |
|
17299 |
if ( ! $this->is_api_result_object( $result, 'installs' ) ) {
|
17300 |
// @todo Handle API error.
|
@@ -17302,7 +18245,8 @@
|
|
17302 |
|
17303 |
$installs = array_merge( $installs, $result->installs );
|
17304 |
|
17305 |
-
$left
|
|
|
17306 |
}
|
17307 |
|
17308 |
foreach ( $installs as &$install ) {
|
@@ -17332,7 +18276,8 @@
|
|
17332 |
$email = false,
|
17333 |
$redirect = true,
|
17334 |
$license_key = false,
|
17335 |
-
$is_pending_trial = false
|
|
|
17336 |
) {
|
17337 |
if ( $this->_ignore_pending_mode ) {
|
17338 |
/**
|
@@ -17342,12 +18287,12 @@
|
|
17342 |
* @author Vova Feldman
|
17343 |
* @since 1.2.1.6
|
17344 |
*/
|
17345 |
-
$this->skip_connection(
|
17346 |
} else {
|
17347 |
// Install must be activated via email since
|
17348 |
// user with the same email already exist.
|
17349 |
$this->_storage->is_pending_activation = true;
|
17350 |
-
$this->_add_pending_activation_notice( $email, $is_pending_trial );
|
17351 |
}
|
17352 |
|
17353 |
if ( ! empty( $license_key ) ) {
|
@@ -17362,8 +18307,8 @@
|
|
17362 |
|
17363 |
$next_page = $this->get_after_activation_url( 'after_pending_connect_url' );
|
17364 |
|
17365 |
-
// Reload the page with with pending activation message.
|
17366 |
if ( $redirect ) {
|
|
|
17367 |
fs_redirect( $next_page );
|
17368 |
}
|
17369 |
|
@@ -17392,7 +18337,10 @@
|
|
17392 |
*/
|
17393 |
$license_key = fs_request_get( 'license_secret_key' );
|
17394 |
|
17395 |
-
$this->
|
|
|
|
|
|
|
17396 |
|
17397 |
$this->install_with_current_user( $license_key );
|
17398 |
}
|
@@ -17410,7 +18358,7 @@
|
|
17410 |
*
|
17411 |
* @return object|string If redirect is `false`, returns the next page the user should be redirected to, or the API error object if failed to install.
|
17412 |
*/
|
17413 |
-
|
17414 |
$license_key = false,
|
17415 |
$trial_plan_id = false,
|
17416 |
$sites = array(),
|
@@ -17793,9 +18741,6 @@
|
|
17793 |
$this->send_installs_update();
|
17794 |
}
|
17795 |
|
17796 |
-
// Switch install context back to the first install.
|
17797 |
-
$this->_site = $first_install;
|
17798 |
-
|
17799 |
$current_blog = get_current_blog_id();
|
17800 |
|
17801 |
foreach ( $blog_2_install_map as $blog_id => $install ) {
|
@@ -17804,7 +18749,12 @@
|
|
17804 |
$this->do_action( 'after_account_connection', $this->_user, $install );
|
17805 |
}
|
17806 |
|
17807 |
-
|
|
|
|
|
|
|
|
|
|
|
17808 |
|
17809 |
$this->do_action( 'after_network_account_connection', $this->_user, $blog_2_install_map );
|
17810 |
}
|
@@ -17852,9 +18802,7 @@
|
|
17852 |
$parent_fs->_admin_notices->remove_sticky( 'connect_account' );
|
17853 |
|
17854 |
if ( $parent_fs->is_pending_activation() ) {
|
17855 |
-
$parent_fs->
|
17856 |
-
|
17857 |
-
unset( $parent_fs->_storage->is_pending_activation );
|
17858 |
}
|
17859 |
|
17860 |
// Get user information based on parent's plugin.
|
@@ -17908,6 +18856,10 @@
|
|
17908 |
// return;
|
17909 |
// }
|
17910 |
|
|
|
|
|
|
|
|
|
17911 |
/**
|
17912 |
* When running from a site admin with a network activated module and the connection
|
17913 |
* was NOT delegated and the user still haven't skipped or opted-in, then hide the
|
@@ -18862,7 +19814,7 @@
|
|
18862 |
*
|
18863 |
* @return string
|
18864 |
*/
|
18865 |
-
|
18866 |
$action = "fs_{$tag}";
|
18867 |
|
18868 |
if ( ! empty( $module_id ) ) {
|
@@ -18885,10 +19837,10 @@
|
|
18885 |
* @uses do_action()
|
18886 |
*/
|
18887 |
function do_action( $tag, $arg = '' ) {
|
18888 |
-
$this->_logger->entrance( $tag );
|
18889 |
-
|
18890 |
$args = func_get_args();
|
18891 |
|
|
|
|
|
18892 |
call_user_func_array( 'do_action', array_merge(
|
18893 |
array( $this->get_action_tag( $tag ) ),
|
18894 |
array_slice( $args, 1 ) )
|
@@ -19028,6 +19980,30 @@
|
|
19028 |
wp_send_json( $result );
|
19029 |
}
|
19030 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19031 |
/**
|
19032 |
* Apply filter, specific for the current context plugin.
|
19033 |
*
|
@@ -19042,9 +20018,10 @@
|
|
19042 |
* @uses apply_filters()
|
19043 |
*/
|
19044 |
function apply_filters( $tag, $value ) {
|
|
|
|
|
19045 |
$this->_logger->entrance( $tag );
|
19046 |
|
19047 |
-
$args = func_get_args();
|
19048 |
array_unshift( $args, $this->get_unique_affix() );
|
19049 |
|
19050 |
return call_user_func_array( 'fs_apply_filter', $args );
|
@@ -19105,7 +20082,7 @@
|
|
19105 |
}
|
19106 |
|
19107 |
/* Account Page
|
19108 |
-
|
19109 |
/**
|
19110 |
* Update site information.
|
19111 |
*
|
@@ -19116,7 +20093,7 @@
|
|
19116 |
* @param null|int $network_level_or_blog_id Since 2.0.0
|
19117 |
* @param \FS_Site $site Since 2.0.0
|
19118 |
*/
|
19119 |
-
private function _store_site( $store = true, $network_level_or_blog_id = null, FS_Site $site = null ) {
|
19120 |
$this->_logger->entrance();
|
19121 |
|
19122 |
if ( is_null( $site ) ) {
|
@@ -19131,9 +20108,12 @@
|
|
19131 |
|
19132 |
$site_clone = clone $site;
|
19133 |
|
19134 |
-
$sites = self::get_all_sites( $this->_module_type, $network_level_or_blog_id );
|
19135 |
|
19136 |
-
if (
|
|
|
|
|
|
|
19137 |
$this->sync_user_by_current_install( $site->user_id );
|
19138 |
|
19139 |
$prev_stored_user_id = $this->_storage->get( 'prev_user_id', false, $network_level_or_blog_id );
|
@@ -19158,7 +20138,26 @@
|
|
19158 |
|
19159 |
$sites[ $this->_slug ] = $site_clone;
|
19160 |
|
19161 |
-
$this->set_account_option(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19162 |
}
|
19163 |
|
19164 |
/**
|
@@ -20399,10 +21398,10 @@
|
|
20399 |
$this->switch_to_blog( $current_blog_id );
|
20400 |
}
|
20401 |
|
20402 |
-
$result = $this->send_install_update( array(), true );
|
20403 |
$is_valid = $this->is_api_result_entity( $result );
|
20404 |
} else {
|
20405 |
-
$result = $this->send_installs_update( array(), true );
|
20406 |
$is_valid = $this->is_api_result_object( $result, 'installs' );
|
20407 |
}
|
20408 |
|
@@ -20412,7 +21411,7 @@
|
|
20412 |
$this->switch_to_blog( $this->_storage->network_install_blog_id );
|
20413 |
}
|
20414 |
|
20415 |
-
// Show API
|
20416 |
if ( ! $background || $this->is_paying() ) {
|
20417 |
// Try to ping API to see if not blocked.
|
20418 |
if ( ! FS_Api::test() ) {
|
@@ -20422,25 +21421,49 @@
|
|
20422 |
* @author Vova Feldman (@svovaf)
|
20423 |
* @since 1.1.6 Only show message related to one of the Freemius powered plugins. Once it will be resolved it will fix the issue for all plugins anyways. There's no point to scare users with multiple error messages.
|
20424 |
*/
|
20425 |
-
$api = $this->get_api_site_scope();
|
20426 |
|
20427 |
if ( ! self::$_global_admin_notices->has_sticky( 'api_blocked' ) ) {
|
20428 |
-
|
20429 |
-
|
20430 |
-
|
20431 |
-
|
20432 |
-
|
20433 |
-
|
20434 |
-
|
20435 |
-
|
20436 |
-
|
20437 |
-
|
20438 |
-
|
20439 |
-
|
20440 |
-
|
20441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20442 |
}
|
20443 |
-
} else {
|
20444 |
// Authentication params are broken.
|
20445 |
$this->_admin_notices->add(
|
20446 |
$this->get_text_inline( 'It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.', 'wrong-authentication-param-message' ) . '<br> ' . $this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . var_export( $result->error, true ),
|
@@ -20454,6 +21477,9 @@
|
|
20454 |
return;
|
20455 |
}
|
20456 |
|
|
|
|
|
|
|
20457 |
if ( $is_site_level_sync ) {
|
20458 |
$site = new FS_Site( $result );
|
20459 |
} else {
|
@@ -20645,7 +21671,7 @@
|
|
20645 |
}
|
20646 |
|
20647 |
if ( ! $this->is_addon() &&
|
20648 |
-
$this->_site->is_beta() !== $site->is_beta
|
20649 |
) {
|
20650 |
// Beta flag updated.
|
20651 |
$this->_site = $site;
|
@@ -21200,8 +22226,7 @@
|
|
21200 |
if ( ! $this->is_api_result_entity( $plan ) ) {
|
21201 |
// Some API error while trying to start the trial.
|
21202 |
$this->_admin_notices->add(
|
21203 |
-
|
21204 |
-
. ' ' . var_export( $plan, true ),
|
21205 |
$oops_text,
|
21206 |
'error'
|
21207 |
);
|
@@ -21379,13 +22404,18 @@
|
|
21379 |
) {
|
21380 |
$this->_logger->entrance();
|
21381 |
|
|
|
|
|
|
|
|
|
21382 |
$switch_to_blog_id = null;
|
21383 |
|
21384 |
/**
|
21385 |
* @since 1.1.7.3 Check for plugin updates from Freemius only if opted-in.
|
21386 |
* @since 1.1.7.4 Also check updates for add-ons.
|
21387 |
*/
|
21388 |
-
if (
|
|
|
21389 |
! $this->_is_addon_id( $addon_id )
|
21390 |
) {
|
21391 |
if ( ! is_multisite() ) {
|
@@ -21395,6 +22425,10 @@
|
|
21395 |
$installs_map = $this->get_blog_install_map();
|
21396 |
|
21397 |
foreach ( $installs_map as $blog_id => $install ) {
|
|
|
|
|
|
|
|
|
21398 |
/**
|
21399 |
* @var FS_Site $install
|
21400 |
*/
|
@@ -21491,9 +22525,11 @@
|
|
21491 |
private function get_latest_download_api_url( $plugin_id = false ) {
|
21492 |
$this->_logger->entrance();
|
21493 |
|
21494 |
-
|
21495 |
$this->_get_latest_version_endpoint( $plugin_id, 'zip' )
|
21496 |
);
|
|
|
|
|
21497 |
}
|
21498 |
|
21499 |
/**
|
@@ -21688,7 +22724,6 @@
|
|
21688 |
private function update_email( $new_email ) {
|
21689 |
$this->_logger->entrance();
|
21690 |
|
21691 |
-
|
21692 |
$api = $this->get_api_user_scope();
|
21693 |
$user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,email,is_verified", 'put', array(
|
21694 |
'email' => $new_email,
|
@@ -21704,7 +22739,6 @@
|
|
21704 |
$this->_store_user();
|
21705 |
} else {
|
21706 |
// handle different error cases.
|
21707 |
-
|
21708 |
}
|
21709 |
|
21710 |
return $user;
|
@@ -21780,15 +22814,32 @@
|
|
21780 |
* @uses FS_Api
|
21781 |
*
|
21782 |
* @param string $candidate_email
|
|
|
21783 |
*
|
21784 |
* @return bool Is ownership change successfully initiated.
|
21785 |
*/
|
21786 |
-
private function init_change_owner( $candidate_email ) {
|
21787 |
$this->_logger->entrance();
|
21788 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21789 |
$api = $this->get_api_site_scope();
|
21790 |
$result = $api->call( "/users/{$this->_user->id}.json", 'put', array(
|
21791 |
'email' => $candidate_email,
|
|
|
|
|
21792 |
'after_confirm_url' => $this->_get_admin_page_url(
|
21793 |
'account',
|
21794 |
array( 'fs_action' => 'change_owner' )
|
@@ -21810,28 +22861,113 @@
|
|
21810 |
private function complete_change_owner() {
|
21811 |
$this->_logger->entrance();
|
21812 |
|
21813 |
-
$
|
21814 |
-
|
21815 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21816 |
|
21817 |
-
$
|
21818 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21819 |
|
21820 |
// Validate install's user and given user.
|
21821 |
if ( $user->id != $this->_site->user_id ) {
|
|
|
|
|
21822 |
return false;
|
21823 |
}
|
21824 |
|
21825 |
-
$
|
21826 |
-
$user->secret_key = fs_request_get( 'user_secret_key' );
|
21827 |
|
21828 |
// Fetch new user information.
|
21829 |
-
$this->_user = $user;
|
21830 |
$user_result = $this->get_api_user_scope( true )->get();
|
21831 |
$user = new FS_User( $user_result );
|
21832 |
$this->_user = $user;
|
21833 |
|
21834 |
-
$this->_set_account( $user, $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21835 |
|
21836 |
return true;
|
21837 |
}
|
@@ -22076,26 +23212,23 @@
|
|
22076 |
|
22077 |
if ( $is_parent_plugin_action ) {
|
22078 |
if ( $is_network_action && ! empty( $blog_id ) ) {
|
22079 |
-
if ( $this->is_registered() ) {
|
22080 |
-
if ( $this->is_tracking_prohibited() ) {
|
22081 |
-
if ( $this->
|
22082 |
$this->_admin_notices->add(
|
22083 |
-
sprintf( $this->get_text_inline( '
|
22084 |
$this->get_text_inline( 'Thank you!', 'thank-you' )
|
22085 |
);
|
22086 |
}
|
22087 |
} else {
|
22088 |
-
if ( $this->
|
|
|
|
|
22089 |
$this->_admin_notices->add(
|
22090 |
sprintf(
|
22091 |
-
$this->get_text_inline( '
|
22092 |
-
$
|
22093 |
-
|
22094 |
-
sprintf(
|
22095 |
-
'<a href="%s" target="_blank" rel="noopener">%s</a>',
|
22096 |
-
'https://freemius.com',
|
22097 |
-
'freemius.com'
|
22098 |
-
)
|
22099 |
)
|
22100 |
);
|
22101 |
}
|
@@ -22243,10 +23376,15 @@
|
|
22243 |
$state = fs_request_get( 'state', 'init' );
|
22244 |
switch ( $state ) {
|
22245 |
case 'init':
|
22246 |
-
$candidate_email = fs_request_get( 'candidate_email'
|
|
|
22247 |
|
22248 |
-
if ( $this->init_change_owner( $candidate_email ) ) {
|
22249 |
-
|
|
|
|
|
|
|
|
|
22250 |
}
|
22251 |
break;
|
22252 |
case 'owner_confirmed':
|
@@ -22269,37 +23407,6 @@
|
|
22269 |
|
22270 |
return;
|
22271 |
|
22272 |
-
case 'update_email':
|
22273 |
-
check_admin_referer( 'update_email' );
|
22274 |
-
|
22275 |
-
$new_email = fs_request_get( 'fs_email_' . $this->get_unique_affix(), '' );
|
22276 |
-
$result = $this->update_email( $new_email );
|
22277 |
-
|
22278 |
-
if ( isset( $result->error ) ) {
|
22279 |
-
switch ( $result->error->code ) {
|
22280 |
-
case 'user_exist':
|
22281 |
-
$this->_admin_notices->add(
|
22282 |
-
$this->get_text_inline( 'Sorry, we could not complete the email update. Another user with the same email is already registered.', 'user-exist-message' ) . ' ' .
|
22283 |
-
sprintf( $this->get_text_inline( 'If you would like to give up the ownership of the %s\'s account to %s click the Change Ownership button.', 'user-exist-message_ownership' ), $this->_module_type, '<b>' . $new_email . '</b>' ) .
|
22284 |
-
sprintf(
|
22285 |
-
'<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s ➜</button></a>',
|
22286 |
-
$this->get_account_url( 'change_owner', array(
|
22287 |
-
'state' => 'init',
|
22288 |
-
'candidate_email' => $new_email
|
22289 |
-
) ),
|
22290 |
-
$this->get_text_inline( 'Change Ownership', 'change-ownership' )
|
22291 |
-
),
|
22292 |
-
$oops_text,
|
22293 |
-
'error'
|
22294 |
-
);
|
22295 |
-
break;
|
22296 |
-
}
|
22297 |
-
} else {
|
22298 |
-
$this->_admin_notices->add( $this->get_text_inline( 'Your email was successfully updated. You should receive an email with confirmation instructions in few moments.', 'email-updated-message' ) );
|
22299 |
-
}
|
22300 |
-
|
22301 |
-
return;
|
22302 |
-
|
22303 |
case 'update_user_name':
|
22304 |
check_admin_referer( 'update_user_name' );
|
22305 |
|
@@ -22461,7 +23568,26 @@
|
|
22461 |
|
22462 |
fs_enqueue_local_style( 'fs_affiliation', '/admin/affiliation.css' );
|
22463 |
|
22464 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22465 |
echo $this->apply_filters( "/forms/affiliation.php", fs_get_template( '/forms/affiliation.php', $vars ) );
|
22466 |
}
|
22467 |
|
@@ -22562,7 +23688,7 @@
|
|
22562 |
}
|
22563 |
|
22564 |
/* Pricing & Upgrade
|
22565 |
-
|
22566 |
/**
|
22567 |
* Render pricing page.
|
22568 |
*
|
@@ -22704,7 +23830,17 @@
|
|
22704 |
}
|
22705 |
|
22706 |
static function _clean_admin_content_section_hook() {
|
22707 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22708 |
|
22709 |
// Hide footer.
|
22710 |
echo '<style>#wpfooter { display: none !important; }</style>';
|
@@ -22721,17 +23857,17 @@
|
|
22721 |
}
|
22722 |
|
22723 |
/* CSS & JavaScript
|
22724 |
-
|
22725 |
/* function _enqueue_script($handle, $src) {
|
22726 |
-
|
22727 |
|
22728 |
-
|
22729 |
|
22730 |
-
|
22731 |
-
|
22732 |
|
22733 |
/* SDK
|
22734 |
-
|
22735 |
private $_user_api;
|
22736 |
|
22737 |
/**
|
@@ -22743,7 +23879,7 @@
|
|
22743 |
*
|
22744 |
* @return FS_Api
|
22745 |
*/
|
22746 |
-
|
22747 |
if ( ! isset( $this->_user_api ) || $flush ) {
|
22748 |
$this->_user_api = $this->get_api_user_scope_by_user( $this->_user );
|
22749 |
}
|
@@ -22822,13 +23958,56 @@
|
|
22822 |
$this->_site->public_key,
|
22823 |
! $this->is_live(),
|
22824 |
$this->_site->secret_key,
|
22825 |
-
$this->get_sdk_version()
|
|
|
22826 |
);
|
22827 |
}
|
22828 |
|
22829 |
return $this->_site_api;
|
22830 |
}
|
22831 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22832 |
private $_plugin_api;
|
22833 |
|
22834 |
/**
|
@@ -23264,7 +24443,7 @@
|
|
23264 |
}
|
23265 |
|
23266 |
/* Action Links
|
23267 |
-
|
23268 |
private $_action_links_hooked = false;
|
23269 |
private $_action_links = array();
|
23270 |
|
@@ -23435,15 +24614,6 @@
|
|
23435 |
|
23436 |
$this->_logger->entrance();
|
23437 |
|
23438 |
-
/**
|
23439 |
-
* @author Vova Feldman (@svovaf)
|
23440 |
-
* @since 2.3.2 Allow opting out from usage-tracking for paid products too by giving the appropriate warning letting the user know the automatic updates mechanism cannot function without an ongoing connection to the licensing and updates engine.
|
23441 |
-
*/
|
23442 |
-
/*if ( $this->is_premium() ) {
|
23443 |
-
// Don't add opt-in/out for premium code base.
|
23444 |
-
return;
|
23445 |
-
}*/
|
23446 |
-
|
23447 |
if ( $this->is_only_premium() && $this->is_free_plan() ) {
|
23448 |
// Don't add tracking links for premium-only products that were opted-in by relation (add-on or a parent product) before activating any license.
|
23449 |
return;
|
@@ -23451,10 +24621,13 @@
|
|
23451 |
|
23452 |
if (
|
23453 |
$this->is_addon() &&
|
23454 |
-
! $this->is_only_premium()
|
23455 |
-
$this->_parent->is_anonymous()
|
23456 |
) {
|
23457 |
-
|
|
|
|
|
|
|
|
|
23458 |
}
|
23459 |
|
23460 |
if ( fs_is_network_admin() ) {
|
@@ -23503,23 +24676,15 @@
|
|
23503 |
}
|
23504 |
}
|
23505 |
|
23506 |
-
if ( $this->add_ajax_action( '
|
23507 |
-
return;
|
23508 |
-
}
|
23509 |
-
|
23510 |
-
if ( $this->add_ajax_action( 'allow_tracking', array( &$this, '_allow_tracking_callback' ) ) ) {
|
23511 |
-
return;
|
23512 |
-
}
|
23513 |
-
|
23514 |
-
if ( $this->add_ajax_action( 'update_tracking_permission', array( &$this, '_update_tracking_permission_callback' ) ) ) {
|
23515 |
return;
|
23516 |
}
|
23517 |
|
23518 |
$link_text_id = '';
|
23519 |
$url = '#';
|
23520 |
|
23521 |
-
if ( $this->is_registered() ) {
|
23522 |
-
if ( $this->is_tracking_allowed() ) {
|
23523 |
$link_text_id = $this->get_text_inline( 'Opt Out', 'opt-out' );
|
23524 |
} else {
|
23525 |
$link_text_id = $this->get_text_inline( 'Opt In', 'opt-in' );
|
@@ -23716,9 +24881,12 @@
|
|
23716 |
*/
|
23717 |
private function is_premium_version_installed() {
|
23718 |
$premium_plugin_basename = $this->premium_plugin_basename();
|
23719 |
-
$premium_plugin = get_plugins( '/' . dirname( $premium_plugin_basename ) );
|
23720 |
|
23721 |
-
|
|
|
|
|
|
|
|
|
23722 |
}
|
23723 |
|
23724 |
/**
|
@@ -23754,7 +24922,9 @@
|
|
23754 |
* @author Leo Fajardo (@leorw)
|
23755 |
* @since 2.2.1
|
23756 |
*/
|
23757 |
-
$
|
|
|
|
|
23758 |
|
23759 |
return sprintf(
|
23760 |
/* translators: %1$s: Product title; %2$s: Plan title */
|
@@ -23763,7 +24933,9 @@
|
|
23763 |
$plan_title,
|
23764 |
sprintf(
|
23765 |
'<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s</button></a>',
|
23766 |
-
|
|
|
|
|
23767 |
esc_html( sprintf(
|
23768 |
/* translators: %s: Plan title */
|
23769 |
$this->get_text_inline( 'Activate %s features', 'activate-x-features' ),
|
@@ -23788,7 +24960,7 @@
|
|
23788 |
) ),
|
23789 |
$deactivation_step,
|
23790 |
$this->get_text_inline( 'Upload and activate the downloaded version', 'upload-and-activate' ),
|
23791 |
-
$this->apply_filters( 'upload_and_install_video_url', '//bit.ly/
|
23792 |
$this->get_text_inline( 'How to upload and activate?', 'howto-upload-activate' )
|
23793 |
);
|
23794 |
}
|
@@ -24241,8 +25413,10 @@
|
|
24241 |
function _tabs_capture() {
|
24242 |
$this->_logger->entrance();
|
24243 |
|
24244 |
-
if (
|
24245 |
-
|
|
|
|
|
24246 |
) {
|
24247 |
return;
|
24248 |
}
|
@@ -24296,8 +25470,10 @@
|
|
24296 |
function _store_tabs_styles() {
|
24297 |
$this->_logger->entrance();
|
24298 |
|
24299 |
-
if (
|
24300 |
-
|
|
|
|
|
24301 |
) {
|
24302 |
return;
|
24303 |
}
|
377 |
const REASON_DIDNT_WORK_AS_EXPECTED = 14;
|
378 |
const REASON_TEMPORARY_DEACTIVATION = 15;
|
379 |
|
380 |
+
#endregion
|
381 |
+
|
382 |
/**
|
383 |
* @author Leo Fajardo (@leorw)
|
384 |
* @since 2.3.1
|
394 |
*/
|
395 |
private $_pricing_js_path = null;
|
396 |
|
397 |
+
const VERSION_MAX_CHARS = 16;
|
398 |
+
const LANGUAGE_MAX_CHARS = 8;
|
399 |
|
400 |
/* Ctor
|
401 |
------------------------------------------------------------------------------------------------------------------*/
|
411 |
* @param bool $is_init Since 1.2.1 Is initiation sequence.
|
412 |
*/
|
413 |
private function __construct( $module_id, $slug = false, $is_init = false ) {
|
414 |
+
$main_file = false;
|
415 |
+
|
416 |
if ( $is_init && is_numeric( $module_id ) && is_string( $slug ) ) {
|
417 |
+
$main_file = $this->store_id_slug_type_path_map( $module_id, $slug );
|
418 |
}
|
419 |
|
420 |
$this->_module_id = $module_id;
|
429 |
|
430 |
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->get_unique_affix(), WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
|
431 |
|
432 |
+
$this->_plugin_main_file_path = $this->_find_caller_plugin_file( $is_init, $main_file );
|
433 |
$this->_plugin_dir_path = plugin_dir_path( $this->_plugin_main_file_path );
|
434 |
$this->_plugin_basename = $this->get_plugin_basename();
|
435 |
$this->_free_plugin_basename = str_replace( '-premium/', '/', $this->_plugin_basename );
|
524 |
* @author Leo Fajardo (@leorw)
|
525 |
* @since 1.2.2
|
526 |
*/
|
527 |
+
( is_object( $this->_plugin ) && isset( $this->_plugin->title ) ?
|
528 |
+
$this->_plugin->title :
|
529 |
+
$this->get_plugin_name()
|
530 |
+
),
|
531 |
$this->get_unique_affix()
|
532 |
);
|
533 |
|
941 |
* @param string $sdk_version
|
942 |
*/
|
943 |
function _sdk_version_update( $sdk_prev_version, $sdk_version ) {
|
|
|
|
|
|
|
944 |
if ( empty( $sdk_prev_version ) ) {
|
945 |
return;
|
946 |
}
|
947 |
|
948 |
+
if (
|
949 |
+
version_compare( $sdk_prev_version, '2.5.1', '<' ) &&
|
950 |
+
version_compare( $sdk_version, '2.5.1', '>=' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
951 |
) {
|
952 |
+
if ( $this->is_registered( true ) ) {
|
953 |
+
/**
|
954 |
+
* Migrate to new permissions layer.
|
955 |
+
*/
|
956 |
+
require_once WP_FS__DIR_INCLUDES . '/supplements/fs-migration-2.5.1.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
957 |
|
958 |
+
$install_by_blog_id = is_multisite() ?
|
959 |
+
$this->get_blog_install_map() :
|
960 |
+
array( 0 => $this->_site );
|
961 |
|
962 |
+
fs_migrate_251( $this, $install_by_blog_id );
|
963 |
}
|
964 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
965 |
}
|
966 |
|
967 |
/**
|
1012 |
}
|
1013 |
}
|
1014 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1015 |
/**
|
1016 |
* @author Vova Feldman (@svovaf)
|
1017 |
* @since 1.2.2.7
|
1348 |
}
|
1349 |
}
|
1350 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1351 |
/**
|
1352 |
* Opens the support forum subemenu item in a new browser page.
|
1353 |
*
|
1458 |
}
|
1459 |
|
1460 |
if ( $this->is_plugin() ) {
|
1461 |
+
if ( version_compare( $GLOBALS['wp_version'], '5.1', '<' ) ) {
|
1462 |
add_action( 'wpmu_new_blog', array( $this, '_after_new_blog_callback' ), 10, 6 );
|
1463 |
+
} else {
|
1464 |
+
add_action( 'wp_initialize_site', array( $this, '_after_wp_initialize_site_callback' ), 11, 2 );
|
1465 |
}
|
1466 |
|
1467 |
register_deactivation_hook( $this->_plugin_main_file_path, array( &$this, '_deactivate_plugin_hook' ) );
|
1471 |
add_action( 'deactivate_blog', array( &$this, '_after_site_deactivated_callback' ) );
|
1472 |
add_action( 'archive_blog', array( &$this, '_after_site_deactivated_callback' ) );
|
1473 |
add_action( 'make_spam_blog', array( &$this, '_after_site_deactivated_callback' ) );
|
1474 |
+
|
1475 |
+
if ( version_compare( $GLOBALS['wp_version'], '5.1', '<' ) ) {
|
1476 |
+
add_action( 'deleted_blog', array( $this, '_after_site_deleted_callback' ), 10, 2 );
|
1477 |
+
} else {
|
1478 |
+
add_action( 'wp_delete_site', array( $this, '_after_wpsite_deleted_callback' ) );
|
1479 |
+
}
|
1480 |
|
1481 |
add_action( 'activate_blog', array( &$this, '_after_site_reactivated_callback' ) );
|
1482 |
add_action( 'unarchive_blog', array( &$this, '_after_site_reactivated_callback' ) );
|
1501 |
add_action( 'admin_init', array( &$this, '_add_premium_version_upgrade_selection' ) );
|
1502 |
add_action( 'admin_init', array( &$this, '_add_beta_mode_update_handler' ) );
|
1503 |
add_action( 'admin_init', array( &$this, '_add_user_change_option' ) );
|
1504 |
+
add_action( 'admin_init', array( &$this, '_add_email_address_update_option' ) );
|
1505 |
|
1506 |
$this->add_ajax_action( 'update_billing', array( &$this, '_update_billing_ajax_action' ) );
|
1507 |
$this->add_ajax_action( 'start_trial', array( &$this, '_start_trial_ajax_action' ) );
|
1873 |
return;
|
1874 |
}
|
1875 |
|
1876 |
+
if (
|
1877 |
+
( self::is_plugins_page() && $this->is_plugin() ) ||
|
1878 |
+
( self::is_themes_page() && $this->is_theme() ) ||
|
1879 |
+
fs_request_is_action_secure( $this->get_unique_affix() . '_reconnect' )
|
1880 |
+
) {
|
1881 |
+
$this->_add_tracking_links();
|
1882 |
+
}
|
1883 |
|
1884 |
if ( self::is_plugins_page() && $this->is_plugin() ) {
|
1885 |
$this->hook_plugin_action_links();
|
1925 |
/**
|
1926 |
* Leverage backtrace to find caller plugin file path.
|
1927 |
*
|
1928 |
+
* @param bool $is_init Is initiation sequence.
|
1929 |
+
* @param string $main_file Since 2.5.0 expects the module's main file path to potentially purge the cached path.
|
|
|
|
|
1930 |
*
|
1931 |
* @return string
|
1932 |
+
* @since 1.0.6
|
1933 |
+
*
|
1934 |
+
* @author Vova Feldman (@svovaf)
|
1935 |
*/
|
1936 |
+
private function _find_caller_plugin_file( $is_init = false, $main_file = '' ) {
|
1937 |
// Try to load the cached value of the file path.
|
1938 |
if ( isset( $this->_storage->plugin_main_file ) ) {
|
1939 |
$plugin_main_file = $this->_storage->plugin_main_file;
|
1940 |
if ( ! empty( $plugin_main_file->path ) ) {
|
1941 |
$absolute_path = $this->get_absolute_path( $plugin_main_file->path );
|
1942 |
if ( file_exists( $absolute_path ) ) {
|
1943 |
+
if ( $is_init && $absolute_path !== $this->get_absolute_path( $main_file ) ) {
|
1944 |
+
// Update cached path if not matching the actual path.
|
1945 |
+
$plugin_main_file->path = $main_file;
|
1946 |
+
$this->_storage->plugin_main_file = $plugin_main_file;
|
1947 |
+
}
|
1948 |
+
|
1949 |
return $absolute_path;
|
1950 |
}
|
1951 |
}
|
1986 |
* Only the original instantiator that calls dynamic_init can modify the module's path.
|
1987 |
*/
|
1988 |
// Find caller module.
|
|
|
1989 |
$this->_storage->plugin_main_file = (object) array(
|
1990 |
+
'path' => $main_file,
|
1991 |
);
|
1992 |
|
1993 |
+
return $this->get_absolute_path( $main_file );
|
1994 |
}
|
1995 |
|
1996 |
/**
|
2052 |
* @param number $module_id
|
2053 |
* @param string $slug
|
2054 |
*
|
2055 |
+
* @return string Since 2.5.0 return the module's main file path.
|
2056 |
+
*
|
2057 |
* @since 1.2.2
|
2058 |
*/
|
2059 |
private function store_id_slug_type_path_map( $module_id, $slug ) {
|
2075 |
$store_option = true;
|
2076 |
}
|
2077 |
|
2078 |
+
$find_caller = empty( $id_slug_type_path_map[ $module_id ]['path'] );
|
2079 |
+
|
2080 |
+
if ( ! $find_caller ) {
|
2081 |
+
/**
|
2082 |
+
* This verification is for cases when suddenly the same module
|
2083 |
+
* is installed but with a different folder name.
|
2084 |
+
*
|
2085 |
+
* @author Vova Feldman (@svovaf)
|
2086 |
+
* @since 1.2.3
|
2087 |
+
*/
|
2088 |
+
$find_caller = ! file_exists( $this->get_absolute_path(
|
2089 |
+
$id_slug_type_path_map[ $module_id ]['path'],
|
2090 |
+
$id_slug_type_path_map[ $module_id ]['type']
|
2091 |
+
) );
|
2092 |
+
}
|
2093 |
+
|
2094 |
+
foreach ( $id_slug_type_path_map as $id => $data ) {
|
2095 |
+
if ( empty( $id ) ) {
|
2096 |
+
// Remove maps with empty module ID.
|
2097 |
+
unset( $id_slug_type_path_map[ $id ] );
|
2098 |
+
$store_option = true;
|
2099 |
+
continue;
|
2100 |
+
}
|
2101 |
+
|
2102 |
+
/**
|
2103 |
+
* If the module's main file path is identical to the main file path of another module then it means that the cached path of the current module or the other one with the same path is wrong, and therefore, we need to recalculate those paths.
|
2104 |
+
*
|
2105 |
+
* @author Vova Feldman (@svovaf)
|
2106 |
+
* @since 2.5.0
|
2107 |
+
*/
|
2108 |
+
if ( ! $find_caller ) {
|
2109 |
+
if ( $id == $module_id ) {
|
2110 |
+
continue;
|
2111 |
+
}
|
2112 |
+
|
2113 |
+
if (
|
2114 |
+
isset( $data['path'] ) &&
|
2115 |
+
$data['path'] === $id_slug_type_path_map[ $module_id ]['path']
|
2116 |
+
) {
|
2117 |
+
$find_caller = true;
|
2118 |
+
}
|
2119 |
+
}
|
2120 |
+
}
|
2121 |
+
|
2122 |
+
if ( $find_caller ) {
|
2123 |
+
$caller_main_file_and_type = $this->get_caller_main_file_and_type( $module_id );
|
2124 |
|
2125 |
$id_slug_type_path_map[ $module_id ]['type'] = $caller_main_file_and_type->module_type;
|
2126 |
$id_slug_type_path_map[ $module_id ]['path'] = $caller_main_file_and_type->path;
|
2131 |
if ( $store_option ) {
|
2132 |
self::$_accounts->set_option( 'id_slug_type_path_map', $id_slug_type_path_map, true );
|
2133 |
}
|
2134 |
+
|
2135 |
+
return $id_slug_type_path_map[ $module_id ]['path'];
|
2136 |
}
|
2137 |
|
2138 |
/**
|
2146 |
* add-ons are relying on loading the SDK from the parent module, and also allows themes including the
|
2147 |
* SDK an internal file instead of directly from functions.php.
|
2148 |
* @since 1.2.1.7 Knows how to handle cases when an add-on includes the parent module logic.
|
2149 |
+
*
|
2150 |
+
* @param number $module_id @since 2.5.0
|
2151 |
*/
|
2152 |
+
private function get_caller_main_file_and_type( $module_id ) {
|
2153 |
self::require_plugin_essentials();
|
2154 |
|
2155 |
$all_plugins = fs_get_plugins( true );
|
2288 |
}
|
2289 |
}
|
2290 |
|
2291 |
+
$caller_main_file_and_type = (object) array(
|
2292 |
'module_type' => $module_type,
|
2293 |
'path' => $caller_file_candidate
|
2294 |
);
|
2295 |
+
|
2296 |
+
return apply_filters( "fs_{$module_id}_caller_main_file_and_type", $caller_main_file_and_type );
|
2297 |
}
|
2298 |
|
2299 |
#----------------------------------------------------------------------------------
|
2310 |
* @since 1.1.2
|
2311 |
*/
|
2312 |
function _add_deactivation_feedback_dialog_box() {
|
2313 |
+
if (
|
2314 |
+
$this->is_clone() ||
|
2315 |
+
( is_object( $this->_site ) && ! $this->is_registered() )
|
2316 |
+
) {
|
2317 |
+
return;
|
2318 |
+
}
|
2319 |
+
|
2320 |
$subscription_cancellation_dialog_box_template_params = $this->apply_filters( 'show_deactivation_subscription_cancellation', true ) ?
|
2321 |
$this->_get_subscription_cancellation_dialog_box_template_params() :
|
2322 |
array();
|
2324 |
/**
|
2325 |
* @since 2.3.0 Developers can optionally hide the deactivation feedback form using the 'show_deactivation_feedback_form' filter.
|
2326 |
*/
|
2327 |
+
$show_deactivation_feedback_form = ! self::is_deactivation_snoozed();
|
2328 |
if ( $this->has_filter( 'show_deactivation_feedback_form' ) ) {
|
2329 |
$show_deactivation_feedback_form = $this->apply_filters( 'show_deactivation_feedback_form', true );
|
2330 |
} else if ( $this->is_addon() ) {
|
2429 |
$reason_temporary_deactivation = array(
|
2430 |
'id' => self::REASON_TEMPORARY_DEACTIVATION,
|
2431 |
'text' => sprintf(
|
2432 |
+
$this->get_text_inline( "It's a temporary %s - I'm troubleshooting an issue", 'reason-temporary-x' ),
|
2433 |
strtolower( $this->is_plugin() ?
|
2434 |
$this->get_text_inline( 'Deactivation', 'deactivation' ) :
|
2435 |
$this->get_text_inline( 'Theme Switch', 'theme-switch' )
|
2594 |
|
2595 |
$this->_storage->store( 'uninstall_reason', $reason );
|
2596 |
|
2597 |
+
if ( self::REASON_TEMPORARY_DEACTIVATION == $reason->id ) {
|
2598 |
+
$snooze_period = fs_request_get( 'snooze_period' );
|
2599 |
+
|
2600 |
+
if ( is_numeric( $snooze_period ) && 0 < $snooze_period ) {
|
2601 |
+
self::snooze_deactivation_form( (int) $snooze_period );
|
2602 |
+
}
|
2603 |
+
}
|
2604 |
+
|
2605 |
/**
|
2606 |
* If the module type is "theme", trigger the uninstall event here (on theme deactivation) since themes do
|
2607 |
* not support uninstall hook.
|
2623 |
exit;
|
2624 |
}
|
2625 |
|
2626 |
+
#--------------------------------------------------------------------------------
|
2627 |
+
#region Deactivation Feedback Snoozing
|
2628 |
+
#--------------------------------------------------------------------------------
|
2629 |
+
|
2630 |
+
/**
|
2631 |
+
* @author Vova Feldman (@svovaf)
|
2632 |
+
* @since 2.4.3
|
2633 |
+
*
|
2634 |
+
* @param int $period
|
2635 |
+
*
|
2636 |
+
* @return bool True if the value was set, false otherwise.
|
2637 |
+
*/
|
2638 |
+
private static function snooze_deactivation_form( $period ) {
|
2639 |
+
return ( 0 < $period && self::reset_deactivation_snoozing( $period ) );
|
2640 |
+
}
|
2641 |
+
|
2642 |
+
/**
|
2643 |
+
* Check if deactivation feedback form is snoozed.
|
2644 |
+
*
|
2645 |
+
* @author Vova Feldman (@svovaf)
|
2646 |
+
* @since 2.4.3
|
2647 |
+
*
|
2648 |
+
* @return bool
|
2649 |
+
*/
|
2650 |
+
static function is_deactivation_snoozed() {
|
2651 |
+
$is_snoozed = ( ! is_multisite() || fs_is_network_admin() ) ?
|
2652 |
+
get_transient( 'fs_snooze_period' ) :
|
2653 |
+
get_site_transient( 'fs_snooze_period' );
|
2654 |
+
|
2655 |
+
|
2656 |
+
return ( 'true' === $is_snoozed );
|
2657 |
+
}
|
2658 |
+
|
2659 |
+
/**
|
2660 |
+
* Reset deactivation snoozing. When `$period` is `0` will stop deactivation snoozing by deleting the transients. Otherwise, will set the transients for the selected period.
|
2661 |
+
*
|
2662 |
+
* @param int $period Period in seconds.
|
2663 |
+
*
|
2664 |
+
* @author Vova Feldman (@svovaf)
|
2665 |
+
* @since 2.4.3
|
2666 |
+
*/
|
2667 |
+
private static function reset_deactivation_snoozing( $period = 0 ) {
|
2668 |
+
$value = ( 0 === $period ) ? null : 'true';
|
2669 |
+
|
2670 |
+
if ( ! is_multisite() || fs_is_network_admin() ) {
|
2671 |
+
return set_transient( 'fs_snooze_period', $value, $period );
|
2672 |
+
} else {
|
2673 |
+
return set_site_transient( 'fs_snooze_period', $value, $period );
|
2674 |
+
}
|
2675 |
+
}
|
2676 |
+
|
2677 |
+
/**
|
2678 |
+
* The deactivation snooze expiration UNIX timestamp (in sec).
|
2679 |
+
*
|
2680 |
+
* @author Vova Feldman (@svovaf)
|
2681 |
+
* @since 2.4.3
|
2682 |
+
*
|
2683 |
+
* @return int
|
2684 |
+
*/
|
2685 |
+
static function deactivation_snooze_expires_at() {
|
2686 |
+
return ( ! is_multisite() || fs_is_network_admin() ) ?
|
2687 |
+
(int) get_option( '_transient_timeout_fs_snooze_period' ) :
|
2688 |
+
(int) get_site_option( '_site_transient_timeout_fs_snooze_period' );
|
2689 |
+
}
|
2690 |
+
|
2691 |
+
#endregion
|
2692 |
+
|
2693 |
/**
|
2694 |
* @author Leo Fajardo (@leorw)
|
2695 |
* @since 2.1.4
|
2886 |
return self::instance( $addon_id );
|
2887 |
}
|
2888 |
|
2889 |
+
/**
|
2890 |
+
* @return Freemius[]
|
2891 |
+
*/
|
2892 |
+
static function _get_all_instances() {
|
2893 |
+
return self::$_instances;
|
2894 |
+
}
|
2895 |
+
|
2896 |
#endregion ------------------------------------------------------------------
|
2897 |
|
2898 |
/**
|
3403 |
add_action( 'plugins_loaded', array( 'Freemius', '_load_textdomain' ), 1 );
|
3404 |
}
|
3405 |
|
3406 |
+
$clone_manager = FS_Clone_Manager::instance();
|
3407 |
+
add_action( 'init', array( $clone_manager, '_init' ) );
|
3408 |
+
|
3409 |
add_action( 'admin_footer', array( 'Freemius', '_open_support_forum_in_new_page' ) );
|
3410 |
|
3411 |
if ( self::is_plugins_page() || self::is_themes_page() ) {
|
3424 |
self::$_statics_loaded = true;
|
3425 |
}
|
3426 |
|
3427 |
+
#--------------------------------------------------------------------------------
|
3428 |
+
#region Clone
|
3429 |
+
#--------------------------------------------------------------------------------
|
3430 |
+
|
3431 |
/**
|
3432 |
* @author Leo Fajardo (@leorw)
|
3433 |
+
* @since 2.5.0
|
3434 |
*
|
3435 |
+
* @param bool $only_if_manual_resolution_is_not_hidden
|
3436 |
+
*
|
3437 |
+
* @return bool
|
3438 |
*/
|
3439 |
+
private function is_unresolved_clone( $only_if_manual_resolution_is_not_hidden = false ) {
|
3440 |
+
if ( ! $this->is_clone( $only_if_manual_resolution_is_not_hidden ) ) {
|
3441 |
+
return false;
|
3442 |
+
}
|
|
|
|
|
|
|
|
|
|
|
3443 |
|
3444 |
+
return FS_Clone_Manager::instance()->has_temporary_duplicate_mode_expired();
|
3445 |
}
|
3446 |
|
|
|
|
|
|
|
|
|
3447 |
/**
|
3448 |
+
* @author Leo Fajardo (@leorw)
|
3449 |
+
* @since 2.5.0
|
3450 |
*
|
3451 |
+
* @param bool $only_if_manual_resolution_is_not_hidden
|
|
|
3452 |
*/
|
3453 |
+
function is_clone( $only_if_manual_resolution_is_not_hidden = false ) {
|
3454 |
+
if ( ! is_object( $this->_site ) ) {
|
3455 |
+
return false;
|
3456 |
}
|
3457 |
|
3458 |
+
$blog_id = null;
|
3459 |
|
3460 |
+
if (
|
3461 |
+
fs_is_network_admin() &&
|
3462 |
+
FS_Site::is_valid_id( $this->_storage->network_install_blog_id )
|
3463 |
+
) {
|
3464 |
+
// Ensure that we're comparing the network install's URL with the relevant subsite's URL.
|
3465 |
+
$blog_id = $this->_storage->network_install_blog_id;
|
3466 |
+
}
|
3467 |
+
|
3468 |
+
$site_url = Freemius::get_unfiltered_site_url( $blog_id, true, true );
|
3469 |
+
|
3470 |
+
if ( ! $this->_site->is_clone( $site_url ) ) {
|
3471 |
+
return false;
|
3472 |
+
}
|
3473 |
+
|
3474 |
+
return (
|
3475 |
+
! $only_if_manual_resolution_is_not_hidden ||
|
3476 |
+
! FS_Clone_Manager::instance()->should_hide_manual_resolution()
|
3477 |
+
);
|
3478 |
+
}
|
3479 |
+
|
3480 |
+
/**
|
3481 |
+
* @author Leo Fajardo (@leorw)
|
3482 |
+
* @since 2.5.0
|
3483 |
+
*
|
3484 |
+
* @param int|null $blog_id
|
3485 |
+
* @param bool $strip_protocol
|
3486 |
+
* @param bool $add_trailing_slash
|
3487 |
+
*
|
3488 |
+
* @return string
|
3489 |
+
*/
|
3490 |
+
static function get_unfiltered_site_url( $blog_id = null, $strip_protocol = false, $add_trailing_slash = false ) {
|
3491 |
+
global $wp_filter;
|
3492 |
+
|
3493 |
+
$site_url_filters = array(
|
3494 |
+
'site_url' => null,
|
3495 |
+
'pre_option_siteurl' => null,
|
3496 |
+
'default_option_siteurl' => null,
|
3497 |
+
'option_siteurl' => null,
|
3498 |
+
);
|
3499 |
+
|
3500 |
+
// Detach all URL-related filters to get the actual site's URL (stripped of potential manipulations by multilingual plugins).
|
3501 |
+
foreach ( $site_url_filters as $hook_name => $site_url_filter ) {
|
3502 |
+
if ( ! empty( $wp_filter[ $hook_name ] ) ) {
|
3503 |
+
$site_url_filters[ $hook_name ] = $wp_filter[ $hook_name ];
|
3504 |
+
unset( $wp_filter[ $hook_name ] );
|
3505 |
+
}
|
3506 |
+
}
|
3507 |
+
|
3508 |
+
$url = get_site_url( $blog_id );
|
3509 |
+
|
3510 |
+
// Re-attach the filters back.
|
3511 |
+
foreach ( $site_url_filters as $hook_name => $site_url_filter ) {
|
3512 |
+
if ( ! empty( $site_url_filter ) ) {
|
3513 |
+
$wp_filter[ $hook_name ] = $site_url_filter;
|
3514 |
+
}
|
3515 |
+
}
|
3516 |
+
|
3517 |
+
if ( $strip_protocol ) {
|
3518 |
+
$url = fs_strip_url_protocol( $url );
|
3519 |
+
}
|
3520 |
+
|
3521 |
+
if ( $add_trailing_slash ) {
|
3522 |
+
$url = trailingslashit( $url );
|
3523 |
+
}
|
3524 |
+
|
3525 |
+
return $url;
|
3526 |
+
}
|
3527 |
+
|
3528 |
+
/**
|
3529 |
+
* @author Leo Fajardo (@leorw)
|
3530 |
+
* @since 2.5.0
|
3531 |
+
*
|
3532 |
+
* @param number $site_id
|
3533 |
+
*/
|
3534 |
+
function fetch_install_by_id( $site_id ) {
|
3535 |
+
return $this->get_current_or_network_user_api_scope()->get( "/installs/{$site_id}.json" );
|
3536 |
+
}
|
3537 |
+
|
3538 |
+
/**
|
3539 |
+
* @author Leo Fajardo (@leorw)
|
3540 |
+
* @since 2.5.0
|
3541 |
+
*
|
3542 |
+
* @return string|object|bool
|
3543 |
+
*/
|
3544 |
+
function _handle_long_term_duplicate() {
|
3545 |
+
$this->_logger->entrance();
|
3546 |
+
|
3547 |
+
$this->delete_current_install( false );
|
3548 |
+
|
3549 |
+
$license_key = false;
|
3550 |
+
|
3551 |
+
if (
|
3552 |
+
is_object( $this->_license ) &&
|
3553 |
+
! $this->_license->is_utilized(
|
3554 |
+
( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( self::get_unfiltered_site_url() ) )
|
3555 |
+
)
|
3556 |
+
) {
|
3557 |
+
$license_key = $this->_license->secret_key;
|
3558 |
+
}
|
3559 |
+
|
3560 |
+
return $this->opt_in(
|
3561 |
+
false,
|
3562 |
+
false,
|
3563 |
+
false,
|
3564 |
+
$license_key,
|
3565 |
+
false,
|
3566 |
+
false,
|
3567 |
+
false,
|
3568 |
+
null,
|
3569 |
+
array(),
|
3570 |
+
false
|
3571 |
+
);
|
3572 |
+
}
|
3573 |
+
|
3574 |
+
#endregion
|
3575 |
+
|
3576 |
+
/**
|
3577 |
+
* @author Leo Fajardo (@leorw)
|
3578 |
+
*
|
3579 |
+
* @since 2.1.3
|
3580 |
+
*/
|
3581 |
+
private static function migrate_options_to_network() {
|
3582 |
+
self::migrate_accounts_to_network();
|
3583 |
+
|
3584 |
+
// Migrate API options from site level to network level.
|
3585 |
+
$api_network_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true, true );
|
3586 |
+
$api_network_options->migrate_to_network();
|
3587 |
+
|
3588 |
+
// Migrate API cache to network level storage.
|
3589 |
+
FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME )->migrate_to_network();
|
3590 |
+
|
3591 |
+
self::$_accounts->set_option( 'ms_migration_complete', true, true );
|
3592 |
+
}
|
3593 |
+
|
3594 |
+
#----------------------------------------------------------------------------------
|
3595 |
+
#region Localization
|
3596 |
+
#----------------------------------------------------------------------------------
|
3597 |
+
|
3598 |
+
/**
|
3599 |
+
* Load framework's text domain.
|
3600 |
+
*
|
3601 |
+
* @author Vova Feldman (@svovaf)
|
3602 |
+
* @since 1.2.1
|
3603 |
+
*/
|
3604 |
+
static function _load_textdomain() {
|
3605 |
+
if ( ! is_admin() ) {
|
3606 |
+
return;
|
3607 |
+
}
|
3608 |
+
|
3609 |
+
global $fs_active_plugins;
|
3610 |
+
|
3611 |
+
// Works both for plugins and themes.
|
3612 |
+
load_plugin_textdomain(
|
3613 |
+
'freemius',
|
3614 |
+
false,
|
3615 |
+
$fs_active_plugins->newest->sdk_path . '/languages/'
|
3616 |
+
);
|
3617 |
+
}
|
3618 |
|
3619 |
#endregion
|
3620 |
|
3809 |
|
3810 |
switch_to_blog( $current_blog_id );
|
3811 |
}
|
3812 |
+
} else if ( fs_request_is_action( 'reset_deactivation_snoozing' ) ) {
|
3813 |
+
check_admin_referer( 'reset_deactivation_snoozing' );
|
3814 |
+
|
3815 |
+
self::reset_deactivation_snoozing();
|
3816 |
} else if ( fs_request_is_action( 'simulate_trial' ) ) {
|
3817 |
check_admin_referer( 'simulate_trial' );
|
3818 |
|
3861 |
}
|
3862 |
|
3863 |
/**
|
3864 |
+
* @author Leo Fajardo (@leorw)
|
3865 |
+
* @since 2.5.0
|
3866 |
+
*
|
3867 |
+
* @return array
|
3868 |
*/
|
3869 |
+
static function get_all_modules_sites() {
|
3870 |
self::$_static_logger->entrance();
|
3871 |
|
3872 |
+
$sites_by_type = array(
|
3873 |
+
WP_FS__MODULE_TYPE_PLUGIN => array(),
|
3874 |
+
WP_FS__MODULE_TYPE_THEME => array(),
|
3875 |
+
);
|
3876 |
+
|
3877 |
+
$module_types = array_keys( $sites_by_type );
|
3878 |
+
|
3879 |
if ( ! is_multisite() ) {
|
3880 |
+
foreach ( $module_types as $type ) {
|
3881 |
+
$sites_by_type[ $type ] = self::get_all_sites( $type );
|
3882 |
+
|
3883 |
+
foreach ( $sites_by_type[ $type ] as $slug => $install ) {
|
3884 |
+
$sites_by_type[ $type ][ $slug ] = array( $install );
|
3885 |
+
}
|
3886 |
+
}
|
3887 |
} else {
|
3888 |
$sites = self::get_sites();
|
3889 |
|
|
|
|
|
|
|
3890 |
foreach ( $sites as $site ) {
|
3891 |
$blog_id = self::get_site_blog_id( $site );
|
3892 |
|
3893 |
+
foreach ( $module_types as $type ) {
|
3894 |
+
$installs = self::get_all_sites( $type, $blog_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
3895 |
|
3896 |
+
foreach ( $installs as $slug => $install ) {
|
3897 |
+
if ( ! isset( $sites_by_type[ $type ][ $slug ] ) ) {
|
3898 |
+
$sites_by_type[ $type ][ $slug ] = array();
|
3899 |
+
}
|
3900 |
|
3901 |
+
$install->blog_id = $blog_id;
|
3902 |
|
3903 |
+
$sites_by_type[ $type ][ $slug ][] = $install;
|
|
|
|
|
3904 |
}
|
3905 |
|
|
|
|
|
|
|
3906 |
}
|
3907 |
}
|
3908 |
}
|
3909 |
|
3910 |
+
return $sites_by_type;
|
3911 |
+
}
|
3912 |
+
|
3913 |
+
/**
|
3914 |
+
* @author Vova Feldman (@svovaf)
|
3915 |
+
* @since 1.0.8
|
3916 |
+
*/
|
3917 |
+
static function _debug_page_render() {
|
3918 |
+
self::$_static_logger->entrance();
|
3919 |
+
|
3920 |
+
$all_modules_sites = self::get_all_modules_sites();
|
3921 |
+
|
3922 |
$licenses_by_module_type = self::get_all_licenses_by_module_type();
|
3923 |
|
3924 |
$vars = array(
|
3925 |
+
'plugin_sites' => $all_modules_sites[ WP_FS__MODULE_TYPE_PLUGIN ],
|
3926 |
+
'theme_sites' => $all_modules_sites[ WP_FS__MODULE_TYPE_THEME ],
|
3927 |
'users' => self::get_all_users(),
|
3928 |
'addons' => self::get_all_addons(),
|
3929 |
'account_addons' => self::get_all_account_addons(),
|
3955 |
function is_on() {
|
3956 |
self::$_static_logger->entrance();
|
3957 |
|
3958 |
+
if ( is_object( $this->_site ) && ! $this->is_registered() ) {
|
3959 |
+
return false;
|
3960 |
+
}
|
3961 |
+
|
3962 |
if ( isset( $this->_is_on ) ) {
|
3963 |
return $this->_is_on;
|
3964 |
}
|
4047 |
|
4048 |
$is_update = $this->apply_filters( 'is_plugin_update', $this->is_plugin_update() );
|
4049 |
|
4050 |
+
$params = array(
|
4051 |
+
'is_update' => json_encode( $is_update ),
|
4052 |
+
'version' => $version,
|
4053 |
+
'sdk' => $this->version,
|
4054 |
+
'is_admin' => json_encode( is_admin() ),
|
4055 |
+
'is_ajax' => json_encode( self::is_ajax() ),
|
4056 |
+
'is_cron' => json_encode( self::is_cron() ),
|
4057 |
+
'is_gdpr_test' => $is_gdpr_test,
|
4058 |
+
'is_http' => json_encode( WP_FS__IS_HTTP_REQUEST ),
|
4059 |
+
);
|
4060 |
+
|
4061 |
+
if ( is_multisite() && function_exists( 'get_network' ) ) {
|
4062 |
+
$params['network_uid'] = $this->get_anonymous_network_id();
|
4063 |
+
}
|
4064 |
+
|
4065 |
return $this->get_api_plugin_scope()->ping(
|
4066 |
$this->get_anonymous_id( $blog_id ),
|
4067 |
+
$params
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4068 |
);
|
4069 |
}
|
4070 |
|
4201 |
$unique_id = self::$_accounts->get_option( 'unique_id', null, $blog_id );
|
4202 |
|
4203 |
if ( empty( $unique_id ) || ! is_string( $unique_id ) ) {
|
4204 |
+
$key = self::get_unfiltered_site_url( $blog_id, true );
|
4205 |
|
4206 |
$secure_auth = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
|
4207 |
if ( empty( $secure_auth ) ||
|
4230 |
return $unique_id;
|
4231 |
}
|
4232 |
|
4233 |
+
/**
|
4234 |
+
* Returns anonymous network ID.
|
4235 |
+
*
|
4236 |
+
* @since 2.4.3
|
4237 |
+
*
|
4238 |
+
* @return string
|
4239 |
+
*/
|
4240 |
+
function get_anonymous_network_id() {
|
4241 |
+
return $this->get_anonymous_id( get_network()->site_id );
|
4242 |
+
}
|
4243 |
+
|
4244 |
/**
|
4245 |
* @author Vova Feldman (@svovaf)
|
4246 |
* @since 1.1.7.4
|
4389 |
$install_previous_desc = $this->esc_html_inline( 'Uninstall this version and install the previous one.', 'install-previous-desc' );
|
4390 |
$fix_issue_title = $this->esc_html_inline( 'Yes - I\'m giving you a chance to fix it', 'fix-issue-title' );
|
4391 |
$fix_issue_desc = $this->esc_html_inline( 'We will do our best to whitelist your server and resolve this issue ASAP. You will get a follow-up email to %s once we have an update.', 'fix-issue-desc' );
|
4392 |
+
/* translators: %s: product title (e.g. "Awesome Plugin" requires access to...) */
|
4393 |
+
$x_requires_access_to_api = $this->esc_html_inline( '%s requires access to our API.', 'x-requires-access-to-api' );
|
4394 |
$sysadmin_title = $this->esc_html_inline( 'I\'m a system administrator', 'sysadmin-title' );
|
4395 |
$happy_to_resolve_issue_asap = $this->esc_html_inline( 'We are sure it\'s an issue on our side and more than happy to resolve it for you ASAP if you give us a chance.', 'happy-to-resolve-issue-asap' );
|
4396 |
|
4397 |
+
if ( $this->is_premium() ) {
|
4398 |
+
/* translators: This string is optionally prepended to 'plugin requires access to our API.' */
|
4399 |
+
$x_requires_access_to_api = $this->esc_html_inline( 'For automatic delivery of security & feature updates,', 'requires-api-for' ) . ' ' . $x_requires_access_to_api;
|
4400 |
+
}
|
4401 |
+
|
4402 |
$message = false;
|
4403 |
if ( is_object( $api_result ) &&
|
4404 |
isset( $api_result->error ) &&
|
5030 |
|
5031 |
/**
|
5032 |
* This should be executed even if Freemius is off for the core module,
|
5033 |
+
* otherwise, the add-ons dialog box won't work properly. This is especially
|
5034 |
* relevant when the developer decided to turn FS off for existing users.
|
5035 |
*
|
5036 |
* @author Vova Feldman (@svovaf)
|
5068 |
* @since 1.1.7.3
|
5069 |
*
|
5070 |
*/
|
5071 |
+
if ( $this->is_registered() && $this->is_tracking_allowed() ) {
|
5072 |
+
$this->maybe_schedule_sync_cron();
|
|
|
|
|
5073 |
}
|
5074 |
|
5075 |
/**
|
5076 |
* Check if requested for manual blocking background sync.
|
5077 |
*/
|
5078 |
if ( fs_request_has( 'background_sync' ) ) {
|
5079 |
+
self::require_pluggable_essentials();
|
5080 |
+
self::wp_cookie_constants();
|
5081 |
+
|
5082 |
$this->run_manual_sync();
|
5083 |
}
|
5084 |
}
|
5085 |
}
|
5086 |
|
5087 |
if ( $this->is_registered() ) {
|
5088 |
+
FS_Clone_Manager::instance()->maybe_resolve_new_subsite_install_automatically( $this );
|
5089 |
+
|
5090 |
$this->hook_callback_to_install_sync();
|
5091 |
}
|
5092 |
|
5101 |
}
|
5102 |
|
5103 |
if ( $this->is_user_in_admin() ) {
|
5104 |
+
if ( $this->is_registered() && fs_request_has( 'purchase_completed' ) ) {
|
5105 |
+
$this->_admin_notices->add_sticky(
|
5106 |
+
sprintf(
|
5107 |
+
/* translators: %s: License type (e.g. you have a professional license) */
|
5108 |
+
$this->get_text_inline( 'You have purchased a %s license.', 'you-have-x-license' ),
|
5109 |
+
fs_request_get( 'purchased_plan' )
|
5110 |
+
) .
|
5111 |
+
sprintf(
|
5112 |
+
$this->get_text_inline(" The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box.", 'post-purchase-email-sent-message' ),
|
5113 |
+
$this->get_module_label( true ),
|
5114 |
+
( FS_Plugin::is_valid_id( $this->get_bundle_id() ) ? "products' " : '' ),
|
5115 |
+
( FS_Plugin::is_valid_id( $this->get_bundle_id() ) ? 's' : '' ),
|
5116 |
+
sprintf(
|
5117 |
+
'<strong>%s</strong>',
|
5118 |
+
fs_request_get( 'purchase_email' )
|
5119 |
+
)
|
5120 |
+
),
|
5121 |
+
'plan_purchased',
|
5122 |
+
$this->get_text_x_inline( 'Yee-haw', 'interjection expressing joy or exuberance', 'yee-haw' ) . '!'
|
5123 |
+
);
|
5124 |
+
}
|
5125 |
+
|
5126 |
if ( $this->is_addon() ) {
|
5127 |
if ( ! $this->is_parent_plugin_installed() ) {
|
5128 |
$parent_name = $this->get_option( $plugin_info, 'parent_name', null );
|
5227 |
* because the updater has some logic that needs to be executed
|
5228 |
* during AJAX calls.
|
5229 |
*
|
5230 |
+
* Currently, we need to hook to the `http_request_host_is_external` filter.
|
5231 |
* In the future, there might be additional logic added.
|
5232 |
*
|
5233 |
* @author Vova Feldman
|
5246 |
*/
|
5247 |
( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this->premium_plugin_basename() ) ) )
|
5248 |
) &&
|
5249 |
+
$this->has_release_on_freemius() &&
|
5250 |
+
( ! $this->is_unresolved_clone( true ) )
|
5251 |
) {
|
5252 |
FS_Plugin_Updater::instance( $this );
|
5253 |
}
|
5316 |
}
|
5317 |
|
5318 |
/**
|
5319 |
+
* @param string[] $permissions
|
5320 |
+
* @param bool $is_enabled
|
5321 |
+
* @param int|null $blog_id
|
5322 |
*
|
5323 |
+
* @return true|object `true` on success, API error object on failure.
|
5324 |
*/
|
5325 |
+
private function update_site_permissions( array $permissions, $is_enabled, $blog_id = null ) {
|
5326 |
$this->_logger->entrance();
|
5327 |
|
5328 |
+
$params = array(
|
5329 |
+
'permissions' => implode( ',', $permissions ),
|
5330 |
+
'is_enabled' => $is_enabled,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5331 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5332 |
|
5333 |
+
$current_blog_id = get_current_blog_id();
|
5334 |
+
$is_blog_switched = false;
|
5335 |
+
if ( is_numeric( $blog_id ) && $current_blog_id != $blog_id ) {
|
5336 |
+
$is_blog_switched = $this->switch_to_blog( $blog_id );
|
5337 |
}
|
5338 |
|
5339 |
+
$result = $this->api_site_call( '/permissions.json', 'put', $params );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5340 |
|
5341 |
+
if ( $is_blog_switched ) {
|
5342 |
+
$this->switch_to_blog( $current_blog_id );
|
|
|
5343 |
}
|
5344 |
|
5345 |
+
if (
|
5346 |
+
! $this->is_api_result_object( $result ) ||
|
5347 |
+
! isset( $result->install_id )
|
|
|
|
|
|
|
|
|
|
|
5348 |
) {
|
5349 |
$this->_logger->api_error( $result );
|
5350 |
|
5351 |
return $result;
|
5352 |
}
|
5353 |
|
|
|
|
|
|
|
|
|
|
|
|
|
5354 |
return true;
|
5355 |
}
|
5356 |
|
5357 |
/**
|
5358 |
+
* @param string[] $permissions
|
5359 |
+
* @param bool $is_enabled
|
5360 |
+
* @param bool $has_site_delegated_connection
|
5361 |
*
|
5362 |
+
* @return true|object `true` on success, API error object on failure.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5363 |
*/
|
5364 |
+
private function update_network_permissions(
|
5365 |
+
array $permissions,
|
5366 |
+
$is_enabled,
|
5367 |
+
&$has_site_delegated_connection
|
5368 |
+
) {
|
5369 |
$this->_logger->entrance();
|
5370 |
|
|
|
|
|
|
|
|
|
|
|
5371 |
$install_id_2_blog_id = array();
|
5372 |
+
$install_by_blog_id = $this->get_blog_install_map();
|
|
|
|
|
5373 |
|
5374 |
+
$has_site_delegated_connection = false;
|
|
|
|
|
|
|
|
|
|
|
5375 |
|
5376 |
+
foreach ( $install_by_blog_id as $blog_id => $install ) {
|
5377 |
if ( $this->is_site_delegated_connection( $blog_id ) ) {
|
5378 |
+
// Only update permissions of non-delegated installs.
|
5379 |
+
$has_site_delegated_connection = true;
|
5380 |
continue;
|
5381 |
}
|
5382 |
|
|
|
|
|
5383 |
$install_id_2_blog_id[ $install->id ] = $blog_id;
|
5384 |
}
|
5385 |
|
5387 |
return true;
|
5388 |
}
|
5389 |
|
5390 |
+
$params = array(
|
5391 |
+
'permissions' => implode( ',', $permissions ),
|
5392 |
+
'is_enabled' => $is_enabled,
|
5393 |
+
'install_ids' => implode( ',', array_keys( $install_id_2_blog_id ) ),
|
5394 |
+
);
|
5395 |
|
5396 |
// Send update to FS.
|
5397 |
+
$result = $this->get_current_or_network_user_api_scope()->call(
|
5398 |
+
"/plugins/{$this->_module_id}/installs/permissions.json",
|
5399 |
+
'put',
|
5400 |
+
$params
|
5401 |
+
);
|
5402 |
|
5403 |
+
if ( ! $this->is_api_result_object( $result, 'installs_metadata' ) ) {
|
5404 |
$this->_logger->api_error( $result );
|
5405 |
|
5406 |
return $result;
|
5407 |
}
|
5408 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5409 |
return true;
|
5410 |
}
|
5411 |
|
5412 |
/**
|
5413 |
+
* @param mixed $result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5414 |
*
|
5415 |
+
* @return string
|
5416 |
*/
|
5417 |
+
private function get_api_error_message( $result ) {
|
5418 |
+
$error_message = sprintf( $this->get_text_inline( 'There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn\'t work, contact the %s\'s author with the following:',
|
5419 |
+
'unexpected-api-error' ), $this->_module_type ) . ' ';
|
5420 |
+
|
5421 |
+
if (
|
5422 |
+
$this->is_api_error( $result ) &&
|
5423 |
+
isset( $result->error )
|
5424 |
+
) {
|
5425 |
+
$code = empty( $result->error->code ) ? '' : " Code: {$result->error->code}";
|
5426 |
+
|
5427 |
+
$error_message .= "<b>{$result->error->message}{$code}</b>";
|
5428 |
+
} else {
|
5429 |
+
$error_message .= var_export( $result, true );
|
5430 |
+
}
|
5431 |
|
5432 |
+
return $error_message;
|
|
|
|
|
5433 |
}
|
5434 |
|
5435 |
/**
|
5436 |
+
* @author Vova Feldman (@svovaf)
|
5437 |
+
* @since 2.5.1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5438 |
*/
|
5439 |
+
function _toggle_permission_tracking_callback() {
|
5440 |
$this->_logger->entrance();
|
5441 |
|
5442 |
+
$this->check_ajax_referer( 'toggle_permission_tracking' );
|
|
|
|
|
|
|
5443 |
|
5444 |
+
if ( ! $this->is_registered( true ) ) {
|
5445 |
+
self::shoot_ajax_failure( 'User never opted-in.' );
|
|
|
5446 |
}
|
5447 |
|
5448 |
+
$is_enabled = fs_request_get_bool( 'is_enabled' );
|
5449 |
+
$permissions = fs_request_get( 'permissions' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5450 |
|
5451 |
+
if ( ! is_string( $permissions ) ) {
|
5452 |
+
self::shoot_ajax_failure( 'The permissions param must be a string.' );
|
5453 |
}
|
5454 |
|
5455 |
+
$permissions = explode( ',', $permissions );
|
|
|
5456 |
|
5457 |
+
$result = $this->toggle_permission_tracking( $permissions, $is_enabled );
|
5458 |
|
5459 |
+
if ( true !== $result ) {
|
5460 |
+
self::shoot_ajax_failure( $this->get_api_error_message( $result ) );
|
5461 |
+
}
|
5462 |
+
|
5463 |
+
self::shoot_ajax_success();
|
5464 |
}
|
5465 |
|
5466 |
/**
|
5467 |
+
* @param string[] $permissions
|
5468 |
+
* @param bool $is_enabled
|
5469 |
+
* @param int|null $blog_id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5470 |
*
|
5471 |
+
* @return bool|mixed `true` if updated successfully or no update is needed.
|
5472 |
*/
|
5473 |
+
private function toggle_permission_tracking( $permissions, $is_enabled, $blog_id = null ) {
|
5474 |
+
if ( ! $this->is_registered( true ) ) {
|
|
|
|
|
5475 |
// User never opted-in.
|
5476 |
return false;
|
5477 |
}
|
5478 |
|
5479 |
+
// Check if permissions are already set as needed.
|
5480 |
+
if ( FS_Permission_Manager::instance( $this )->are_permissions( $permissions, $is_enabled, $blog_id ) ) {
|
5481 |
+
/**
|
5482 |
+
* Note:
|
5483 |
+
* When running on the network admin, there's no need to iterate through all the installs individually since network opt-in permissions are managed for ALL non-delegated installs through a single option (per permission) on the network-level storage.
|
5484 |
+
*/
|
5485 |
+
return true;
|
|
|
|
|
|
|
|
|
|
|
5486 |
}
|
5487 |
|
5488 |
+
$api_managed_permissions = array_intersect(
|
5489 |
+
$permissions,
|
5490 |
+
FS_Permission_Manager::get_api_managed_permission_ids()
|
5491 |
+
);
|
5492 |
+
|
5493 |
+
if (
|
5494 |
+
in_array( FS_Permission_Manager::PERMISSION_ESSENTIALS, $permissions ) &&
|
5495 |
+
! in_array( FS_Permission_Manager::PERMISSION_SITE, $permissions )
|
5496 |
+
) {
|
5497 |
+
$api_managed_permissions[] = FS_Permission_Manager::PERMISSION_SITE;
|
5498 |
}
|
5499 |
|
5500 |
+
if ( ! empty( $api_managed_permissions ) ) {
|
5501 |
+
$has_site_delegated_connection = false;
|
5502 |
|
5503 |
+
if (
|
5504 |
+
! $is_enabled &&
|
5505 |
+
! in_array( FS_Permission_Manager::PERMISSION_EXTENSIONS, $api_managed_permissions ) &&
|
5506 |
+
false === FS_Permission_Manager::instance( $this )->is_extensions_tracking_allowed( $blog_id )
|
5507 |
+
) {
|
5508 |
+
/**
|
5509 |
+
* If we are turning off a permission and the extensions permission is off too, enrich the permissions update request to also turn off extensions tracking, as currently when opting in with extensions tracking disabled the extensions tracking is off but the API isn't aware of it.
|
5510 |
+
*
|
5511 |
+
* @todo Remove this entire `if` after implementing granular opt-in that also sends the permissions to the API when opting in.
|
5512 |
+
*/
|
5513 |
+
$api_managed_permissions[] = FS_Permission_Manager::PERMISSION_EXTENSIONS;
|
5514 |
+
}
|
5515 |
|
5516 |
+
if ( is_null( $blog_id ) && fs_is_network_admin() ) {
|
5517 |
+
$result = $this->update_network_permissions(
|
5518 |
+
$api_managed_permissions,
|
5519 |
+
$is_enabled,
|
5520 |
+
$has_site_delegated_connection
|
5521 |
+
);
|
5522 |
+
} else {
|
5523 |
+
$result = $this->update_site_permissions(
|
5524 |
+
$api_managed_permissions,
|
5525 |
+
$is_enabled,
|
5526 |
+
$blog_id
|
5527 |
+
);
|
5528 |
+
}
|
5529 |
|
5530 |
+
if ( true !== $result ) {
|
5531 |
+
return $result;
|
5532 |
+
}
|
5533 |
|
5534 |
+
if ( in_array( FS_Permission_Manager::PERMISSION_SITE, $api_managed_permissions ) ) {
|
5535 |
+
if ( $is_enabled ) {
|
5536 |
+
$this->schedule_sync_cron();
|
5537 |
+
} else {
|
5538 |
+
$this->clear_sync_cron( ! $has_site_delegated_connection );
|
5539 |
+
}
|
5540 |
+
}
|
5541 |
|
5542 |
+
if ( in_array( FS_Permission_Manager::PERMISSION_USER, $api_managed_permissions ) ) {
|
5543 |
+
$this->toggle_user_permission( $is_enabled, $blog_id );
|
5544 |
+
}
|
|
|
|
|
5545 |
}
|
5546 |
|
5547 |
+
$this->update_tracking_permissions(
|
5548 |
+
$permissions,
|
5549 |
+
$is_enabled,
|
5550 |
+
$blog_id
|
5551 |
+
);
|
5552 |
|
|
|
5553 |
return true;
|
5554 |
}
|
5555 |
|
5556 |
+
/**
|
5557 |
+
* @param bool $is_enabled
|
5558 |
+
* @param int|null $blog_id
|
5559 |
+
*/
|
5560 |
+
private function toggle_user_permission( $is_enabled, $blog_id = null ) {
|
5561 |
+
$network_or_blog_ids = is_numeric( $blog_id ) ?
|
5562 |
+
$blog_id :
|
5563 |
+
fs_is_network_admin();
|
5564 |
+
|
5565 |
+
if ( $is_enabled ) {
|
5566 |
+
$this->reset_anonymous_mode( $network_or_blog_ids );
|
5567 |
+
} else {
|
5568 |
+
$this->skip_connection( $network_or_blog_ids );
|
5569 |
+
}
|
5570 |
+
}
|
5571 |
+
|
5572 |
/**
|
5573 |
* Opt-in back into usage tracking.
|
5574 |
*
|
5582 |
* @author Leo Fajardo (@leorw)
|
5583 |
* @since 1.2.1.5
|
5584 |
*
|
5585 |
+
* @bool $is_enabled
|
5586 |
*
|
5587 |
* @return bool|object
|
5588 |
*/
|
5589 |
+
private function toggle_site_tracking( $is_enabled, $blog_id = null ) {
|
5590 |
$this->_logger->entrance();
|
5591 |
|
5592 |
+
return $this->toggle_permission_tracking(
|
5593 |
+
FS_Permission_Manager::instance( $this )->get_site_tracking_permission_names(),
|
5594 |
+
$is_enabled,
|
5595 |
+
$blog_id
|
5596 |
+
);
|
5597 |
}
|
5598 |
|
5599 |
/**
|
5614 |
|
5615 |
if ( ! fs_is_network_admin() || $is_context_single_site ) {
|
5616 |
if ( $this->is_tracking_prohibited() ) {
|
5617 |
+
FS_Permission_Manager::instance( $this )->update_site_tracking( true );
|
|
|
5618 |
}
|
5619 |
} else {
|
5620 |
$installs_map = $this->get_blog_install_map();
|
5622 |
/**
|
5623 |
* @var FS_Site $install
|
5624 |
*/
|
5625 |
+
if ( ! $this->is_tracking_allowed( $blog_id, $install ) ) {
|
5626 |
+
FS_Permission_Manager::instance( $this )->update_site_tracking( true, $blog_id );
|
|
|
5627 |
}
|
5628 |
}
|
5629 |
}
|
5630 |
}
|
5631 |
|
5632 |
/**
|
5633 |
+
* Update permission tracking flags. When updating in a network context, in addition to updating the network-level flags, also update the permissions on the site-level for all non-delegated sites.
|
|
|
5634 |
*
|
5635 |
+
* @param string[] $permissions
|
5636 |
+
* @param bool $is_enabled
|
5637 |
+
* @param int|null $blog_id
|
5638 |
+
*
|
5639 |
+
* @return array
|
5640 |
*/
|
5641 |
+
private function update_tracking_permissions( $permissions, $is_enabled, $blog_id = null ) {
|
5642 |
+
// Alias.
|
5643 |
+
$permission_manager = FS_Permission_Manager::instance( $this );
|
|
|
|
|
|
|
5644 |
|
5645 |
+
$network_or_blog_ids = is_numeric( $blog_id ) ?
|
5646 |
+
$blog_id :
|
5647 |
+
fs_is_network_admin();
|
|
|
|
|
|
|
5648 |
|
5649 |
+
if ( true === $network_or_blog_ids ) {
|
5650 |
+
// Update the permission for all non-delegated sub-sites.
|
5651 |
+
$blog_ids = $this->get_non_delegated_blog_ids();
|
5652 |
|
5653 |
+
// Add the network-level to the array, to update the permission on the network-level storage.
|
5654 |
+
array_unshift( $blog_ids, null );
|
5655 |
+
}
|
5656 |
+
else
|
5657 |
+
{
|
5658 |
+
if ( false === $network_or_blog_ids ) {
|
5659 |
+
$network_or_blog_ids = null;
|
5660 |
+
}
|
5661 |
|
5662 |
+
$blog_ids = is_array( $network_or_blog_ids ) ?
|
5663 |
+
$network_or_blog_ids :
|
5664 |
+
array( $network_or_blog_ids );
|
5665 |
}
|
5666 |
|
5667 |
+
$result = array();
|
5668 |
+
foreach ( $permissions as $permission ) {
|
5669 |
+
$permission = trim( $permission );
|
5670 |
+
$is_permission_supported = true;
|
5671 |
+
|
5672 |
+
foreach ( $blog_ids as $id ) {
|
5673 |
+
$is_permission_supported = $permission_manager->update_permission_tracking_flag(
|
5674 |
+
$permission,
|
5675 |
+
$is_enabled,
|
5676 |
+
$id
|
5677 |
+
);
|
5678 |
+
}
|
5679 |
|
5680 |
+
if ( ! $is_permission_supported ) {
|
|
|
|
|
|
|
|
|
5681 |
$permission = 'no_match';
|
5682 |
+
}
|
5683 |
|
5684 |
+
$result[ $permission ] = $is_enabled;
|
|
|
5685 |
}
|
5686 |
|
5687 |
+
return $result;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5688 |
}
|
5689 |
|
5690 |
/**
|
5890 |
if ( $this->is_activation_mode() ) {
|
5891 |
if ( ! is_admin() ) {
|
5892 |
/**
|
5893 |
+
* If in activation mode, don't execute Freemius outside the admin dashboard.
|
|
|
5894 |
*
|
5895 |
* @author Vova Feldman (@svovaf)
|
5896 |
* @since 1.1.7.3
|
6437 |
if ( ! isset( $this->_is_anonymous ) ) {
|
6438 |
if ( $this->is_network_anonymous() ) {
|
6439 |
$this->_is_anonymous = true;
|
6440 |
+
} else if ( fs_is_network_admin() ) {
|
6441 |
+
/**
|
6442 |
+
* When not-network-anonymous, yet, running in the network admin, consider as anonymous only when ALL non-delegated sites are set to anonymous.
|
6443 |
+
*/
|
6444 |
+
$non_delegated_sites = $this->get_non_delegated_blog_ids();
|
6445 |
+
|
6446 |
+
foreach ( $non_delegated_sites as $blog_id ) {
|
6447 |
+
$is_anonymous = $this->_storage->get( 'is_anonymous', false, $blog_id );
|
6448 |
+
|
6449 |
+
if ( empty( $is_anonymous ) || false === $is_anonymous[ 'is' ] ) {
|
6450 |
+
$this->_is_anonymous = false;
|
6451 |
+
break;
|
6452 |
+
}
|
6453 |
+
}
|
6454 |
+
|
6455 |
+
if ( false !== $this->_is_anonymous ) {
|
6456 |
+
$this->_is_anonymous = true;
|
6457 |
+
}
|
6458 |
+
} else {
|
6459 |
if ( ! isset( $this->_storage->is_anonymous ) ) {
|
6460 |
// Not skipped.
|
6461 |
$this->_is_anonymous = false;
|
6511 |
return $this->_storage->get( 'is_pending_activation', false );
|
6512 |
}
|
6513 |
|
6514 |
+
/**
|
6515 |
+
* @author Leo Fajardo (@leorw)
|
6516 |
+
* @since 2.5.0
|
6517 |
+
*/
|
6518 |
+
private function clear_pending_activation_mode() {
|
6519 |
+
// Remove the pending activation sticky notice (if it still exists).
|
6520 |
+
$this->_admin_notices->remove_sticky( 'activation_pending' );
|
6521 |
+
|
6522 |
+
// Clear the plugin's pending activation mode.
|
6523 |
+
unset( $this->_storage->is_pending_activation );
|
6524 |
+
}
|
6525 |
+
|
6526 |
/**
|
6527 |
* Check if plugin must be WordPress.org compliant.
|
6528 |
*
|
6599 |
private function get_cron_blog_id( $name ) {
|
6600 |
$this->_logger->entrance( $name );
|
6601 |
|
6602 |
+
if ( ! is_multisite() ) {
|
6603 |
+
// Not a multisite.
|
6604 |
+
return 0;
|
6605 |
+
}
|
6606 |
+
|
6607 |
$cron_data = $this->get_cron_data( $name );
|
6608 |
|
6609 |
return ( is_object( $cron_data ) && is_numeric( $cron_data->blog_id ) ) ?
|
6714 |
return 0;
|
6715 |
}
|
6716 |
|
6717 |
+
if ( $this->_is_network_active ) {
|
6718 |
+
$network_install_blog_id = $this->_storage->network_install_blog_id;
|
|
|
|
|
|
|
|
|
|
|
6719 |
|
6720 |
+
if (
|
6721 |
+
is_numeric( $network_install_blog_id ) &&
|
6722 |
+
$except_blog_id != $network_install_blog_id &&
|
6723 |
+
self::is_site_active( $network_install_blog_id )
|
6724 |
) {
|
6725 |
+
// Try to run cron from the main network blog.
|
6726 |
+
$install = $this->get_install_by_blog_id( $network_install_blog_id );
|
6727 |
+
|
6728 |
+
if (
|
6729 |
+
is_object( $install ) &&
|
6730 |
+
$this->is_tracking_allowed( $network_install_blog_id, $install )
|
6731 |
+
) {
|
6732 |
+
return $network_install_blog_id;
|
6733 |
+
}
|
6734 |
}
|
6735 |
}
|
6736 |
|
6739 |
foreach ( $installs as $blog_id => $install ) {
|
6740 |
if ( $except_blog_id != $blog_id &&
|
6741 |
self::is_site_active( $blog_id ) &&
|
6742 |
+
$this->is_tracking_allowed( $blog_id, $install )
|
6743 |
) {
|
6744 |
return $blog_id;
|
6745 |
}
|
6771 |
/**
|
6772 |
* @var FS_Site $install
|
6773 |
*/
|
6774 |
+
if ( $this->is_tracking_allowed( $blog_id, $install ) ) {
|
6775 |
$clear_cron = false;
|
6776 |
break;
|
6777 |
}
|
6782 |
return;
|
6783 |
}
|
6784 |
|
6785 |
+
$cron_blog_id = $this->get_cron_blog_id( $name );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6786 |
|
6787 |
$this->clear_cron_data( $name );
|
6788 |
|
6819 |
return false;
|
6820 |
}
|
6821 |
|
6822 |
+
$cron_blog_id = $this->get_cron_blog_id( $name );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6823 |
|
6824 |
if ( 0 < $cron_blog_id ) {
|
6825 |
switch_to_blog( $cron_blog_id );
|
6930 |
} else {
|
6931 |
$installs = $this->get_blog_install_map();
|
6932 |
foreach ( $installs as $blog_id => $install ) {
|
6933 |
+
if ( $this->is_tracking_allowed( $blog_id, $install ) ) {
|
6934 |
if ( ! isset( $users_2_blog_ids[ $install->user_id ] ) ) {
|
6935 |
$users_2_blog_ids[ $install->user_id ] = array();
|
6936 |
}
|
6995 |
* @since 1.1.7.3
|
6996 |
*/
|
6997 |
private function run_manual_sync() {
|
|
|
|
|
6998 |
if ( ! $this->is_user_admin() ) {
|
6999 |
return;
|
7000 |
}
|
7078 |
return $this->is_cron_on( 'sync' );
|
7079 |
}
|
7080 |
|
7081 |
+
/**
|
7082 |
+
* @author Leo Fajardo (@leorw)
|
7083 |
+
* @since 2.5.0
|
7084 |
+
*/
|
7085 |
+
private function maybe_schedule_sync_cron() {
|
7086 |
+
$next_schedule = $this->next_sync_cron();
|
7087 |
+
|
7088 |
+
// The event is properly scheduled, so no need to reschedule it.
|
7089 |
+
if (
|
7090 |
+
is_numeric( $next_schedule ) &&
|
7091 |
+
$next_schedule > time()
|
7092 |
+
) {
|
7093 |
+
return;
|
7094 |
+
}
|
7095 |
+
|
7096 |
+
$this->schedule_sync_cron();
|
7097 |
+
}
|
7098 |
+
|
7099 |
/**
|
7100 |
* @author Vova Feldman (@svovaf)
|
7101 |
* @since 1.1.7.3
|
7202 |
* @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
|
7203 |
*/
|
7204 |
private function schedule_install_sync( $except_blog_id = 0 ) {
|
7205 |
+
if ( $this->is_clone() ) {
|
7206 |
+
return;
|
7207 |
+
}
|
7208 |
+
|
7209 |
$this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
|
7210 |
}
|
7211 |
|
7294 |
/**
|
7295 |
* Show a notice that activation is currently pending.
|
7296 |
*
|
7297 |
+
* @todo Add some sort of mechanism to allow users to update the email address they would like to opt-in with when $is_suspicious_email is true.
|
7298 |
+
*
|
7299 |
* @author Vova Feldman (@svovaf)
|
7300 |
* @since 1.0.7
|
7301 |
*
|
7302 |
* @param bool|string $email
|
7303 |
* @param bool $is_pending_trial Since 1.2.1.5
|
7304 |
+
* @param bool $is_suspicious_email Since 2.5.0 Set to true when there's an indication that email address the user opted in with is fake/dummy/placeholder.
|
7305 |
*/
|
7306 |
+
function _add_pending_activation_notice(
|
7307 |
+
$email = false,
|
7308 |
+
$is_pending_trial = false,
|
7309 |
+
$is_suspicious_email = false
|
7310 |
+
) {
|
7311 |
if ( ! is_string( $email ) ) {
|
7312 |
$current_user = self::_get_current_wp_user();
|
7313 |
$email = $current_user->user_email;
|
7363 |
/**
|
7364 |
* Don't redirect if activating multiple plugins at once (bulk activation).
|
7365 |
*/
|
7366 |
+
} else if (
|
7367 |
+
self::is_deactivation_snoozed() &&
|
7368 |
+
(
|
7369 |
+
// Either running the free code base.
|
7370 |
+
! $this->is_premium() ||
|
7371 |
+
// Or if has a free version.
|
7372 |
+
! $this->is_only_premium() ||
|
7373 |
+
// If premium only, don't redirect if license is activated.
|
7374 |
+
( $this->is_registered() && ! $this->can_use_premium_code() )
|
7375 |
+
)
|
7376 |
+
) {
|
7377 |
+
/**
|
7378 |
+
* Don't redirect if activating during the deactivation snooze period (aka troubleshooting), unless activating a paid product version that the admin didn't enter its license key yet.
|
7379 |
+
*/
|
7380 |
} else if ( ! $is_migration ) {
|
7381 |
$this->_redirect_on_activation_hook();
|
7382 |
return;
|
7390 |
if ( fs_request_is_action( $this->get_unique_affix() . '_skip_activation' ) ) {
|
7391 |
check_admin_referer( $this->get_unique_affix() . '_skip_activation' );
|
7392 |
|
7393 |
+
$this->skip_connection( fs_is_network_admin() );
|
7394 |
|
7395 |
fs_redirect( $this->get_after_activation_url( 'after_skip_url' ) );
|
7396 |
}
|
7563 |
|
7564 |
fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' );
|
7565 |
fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' );
|
|
|
|
|
7566 |
}
|
7567 |
|
7568 |
/**
|
7598 |
<?php
|
7599 |
echo $this->apply_filters( 'optin_pointer_execute', "
|
7600 |
|
7601 |
+
optin.pointer('open');
|
7602 |
|
7603 |
+
// Tag the opt-in pointer with custom class.
|
7604 |
+
$('.wp-pointer #fs_connect')
|
7605 |
+
.parents('.wp-pointer.wp-pointer-top')
|
7606 |
+
.addClass('fs-opt-in-pointer');
|
7607 |
|
7608 |
+
", 'element', 'optin' ) ?>
|
7609 |
}
|
7610 |
}
|
7611 |
});
|
7621 |
*
|
7622 |
* @return string
|
7623 |
*/
|
7624 |
+
static function current_page_url() {
|
7625 |
$url = 'http';
|
7626 |
|
7627 |
if ( isset( $_SERVER["HTTPS"] ) ) {
|
7653 |
}
|
7654 |
|
7655 |
/* Events
|
7656 |
+
------------------------------------------------------------------------------------------------------------------*/
|
7657 |
/**
|
7658 |
* Delete site install from Database.
|
7659 |
*
|
7817 |
|
7818 |
/**
|
7819 |
* @author Leo Fajardo (@leorw)
|
7820 |
+
* @since 1.2.2
|
7821 |
+
*
|
7822 |
+
* @return bool
|
7823 |
+
*/
|
7824 |
+
private function can_activate_previous_theme() {
|
7825 |
+
return $this->can_activate_theme( $this->get_previous_theme_slug() );
|
7826 |
+
}
|
7827 |
+
|
7828 |
+
/**
|
7829 |
+
* @author Leo Fajardo (@leorw)
|
7830 |
+
* @since 2.5.0
|
7831 |
*
|
7832 |
+
* @return bool
|
7833 |
*/
|
7834 |
+
private function can_activate_theme( $slug ) {
|
|
|
7835 |
if ( false !== $slug && current_user_can( 'switch_themes' ) ) {
|
7836 |
$theme_instance = wp_get_theme( $slug );
|
7837 |
|
7928 |
( current_filter() !== ( 'activate_' . $this->_free_plugin_basename ) ) :
|
7929 |
$this->is_premium();
|
7930 |
|
7931 |
+
if ( $is_premium_version_activation && $this->is_pending_activation() ) {
|
7932 |
+
$this->clear_pending_activation_mode();
|
7933 |
+
}
|
7934 |
+
|
7935 |
$this->_logger->info( 'Activating ' . ( $is_premium_version_activation ? 'premium' : 'free' ) . ' plugin version.' );
|
7936 |
|
7937 |
if ( $this->is_plugin() ) {
|
7998 |
$plugin_version = $this->_storage->is_anonymous_ms['version'];
|
7999 |
$network = true;
|
8000 |
} else {
|
8001 |
+
$plugin_version = isset( $this->_storage->is_anonymous ) ?
|
8002 |
+
$this->_storage->is_anonymous['version'] :
|
8003 |
+
null;
|
8004 |
$network = false;
|
8005 |
}
|
8006 |
|
8148 |
);
|
8149 |
} else {
|
8150 |
// Activate the license.
|
8151 |
+
$install = $this->api_site_call(
|
8152 |
'/',
|
8153 |
'put',
|
8154 |
array( 'license_key' => $this->apply_filters( 'license_key', $license->secret_key ) )
|
8807 |
$this->_is_anonymous = $is_anonymous;
|
8808 |
}
|
8809 |
|
8810 |
+
/**
|
8811 |
+
* @author Vova Feldman (@svovaf)
|
8812 |
+
* @since 2.5.1
|
8813 |
+
*
|
8814 |
+
* @param bool|int $network_or_blog_id
|
8815 |
+
*/
|
8816 |
+
private function unset_anonymous_mode( $network_or_blog_id = 0 ) {
|
8817 |
+
if ( true === $network_or_blog_id ) {
|
8818 |
+
unset( $this->_storage->is_anonymous_ms );
|
8819 |
+
} else {
|
8820 |
+
$this->_storage->remove( 'is_anonymous', true, $network_or_blog_id );
|
8821 |
+
}
|
8822 |
+
}
|
8823 |
+
|
8824 |
/**
|
8825 |
* @author Vova Feldman (@svovaf)
|
8826 |
* @since 2.0.0
|
8837 |
* @uses Freemius::is_network_anonymous() to check if the super-admin network skipped.
|
8838 |
* @uses Freemius::is_network_delegated_connection() to check if the super-admin network delegated the connection to the site admins.
|
8839 |
*/
|
8840 |
+
public function _after_new_blog_callback( $blog_id, $user_id, $domain, $path, $network_id, $meta ) {
|
8841 |
$this->_logger->entrance();
|
8842 |
|
8843 |
+
if ( ! $this->_is_network_active ) {
|
8844 |
+
FS_Clone_Manager::instance()->store_blog_install_info( $blog_id );
|
8845 |
+
return;
|
8846 |
+
}
|
8847 |
+
|
8848 |
+
$site = null;
|
8849 |
+
$new_blog_id = $blog_id;
|
8850 |
+
|
8851 |
if ( $this->is_premium() &&
|
8852 |
$this->is_network_connected() &&
|
8853 |
is_object( $this->_license ) &&
|
8881 |
}
|
8882 |
}
|
8883 |
|
8884 |
+
$site = $this->_site;
|
8885 |
+
|
8886 |
$this->switch_to_blog( $current_blog_id );
|
8887 |
|
8888 |
+
if ( is_object( $site ) ) {
|
8889 |
+
FS_Clone_Manager::instance()->store_blog_install_info( $blog_id, $site );
|
8890 |
+
|
8891 |
// Already connected (with or without a license), so no need to continue.
|
8892 |
return;
|
8893 |
}
|
8920 |
false
|
8921 |
);
|
8922 |
|
8923 |
+
$site = $this->_site;
|
8924 |
+
|
8925 |
$this->switch_to_blog( $current_blog_id );
|
8926 |
} else {
|
8927 |
/**
|
8932 |
$has_delegated_site = false;
|
8933 |
|
8934 |
$sites = self::get_sites();
|
8935 |
+
foreach ( $sites as $wp_site ) {
|
8936 |
+
$blog_id = self::get_site_blog_id( $wp_site );
|
8937 |
|
8938 |
if ( $this->is_site_delegated_connection( $blog_id ) ) {
|
8939 |
$has_delegated_site = true;
|
8947 |
$this->skip_site_connection( $blog_id );
|
8948 |
}
|
8949 |
}
|
8950 |
+
|
8951 |
+
/**
|
8952 |
+
* Store the new blog's information even if there's no install so that when a clone install is stored in the new blog's storage, we can try to resolve it automatically.
|
8953 |
+
*
|
8954 |
+
* @author Leo Fajardo (@leorw)
|
8955 |
+
* @since 2.5.0
|
8956 |
+
*/
|
8957 |
+
FS_Clone_Manager::instance()->store_blog_install_info( $new_blog_id, $site );
|
8958 |
+
}
|
8959 |
+
|
8960 |
+
/**
|
8961 |
+
* @author Vova Feldman (@svovaf)
|
8962 |
+
* @since 2.5.0
|
8963 |
+
*
|
8964 |
+
* @param \WP_Site $new_site
|
8965 |
+
* @param array $args
|
8966 |
+
*/
|
8967 |
+
public function _after_wp_initialize_site_callback( WP_Site $new_site, $args ) {
|
8968 |
+
$this->_logger->entrance();
|
8969 |
+
|
8970 |
+
$this->_after_new_blog_callback(
|
8971 |
+
$new_site->id,
|
8972 |
+
// Dummy user ID (not in use).
|
8973 |
+
0,
|
8974 |
+
$new_site->domain,
|
8975 |
+
$new_site->path,
|
8976 |
+
$new_site->network_id,
|
8977 |
+
// Dummy meta, not in use.
|
8978 |
+
array()
|
8979 |
+
);
|
8980 |
}
|
8981 |
|
8982 |
/**
|
8983 |
* @author Vova Feldman (@svovaf)
|
8984 |
* @since 1.1.3
|
8985 |
*
|
8986 |
+
* @param bool|int|int[] $network_or_blog_ids Since 2.0.0.
|
8987 |
*/
|
8988 |
+
private function reset_anonymous_mode( $network_or_blog_ids = false ) {
|
8989 |
+
if ( true === $network_or_blog_ids ) {
|
8990 |
+
$this->unset_anonymous_mode( true );
|
8991 |
+
|
8992 |
+
if ( fs_is_network_admin() ) {
|
8993 |
+
$this->_is_anonymous = null;
|
8994 |
+
}
|
8995 |
+
|
8996 |
+
// Rest anonymous mode for all non-delegated sub-sites.
|
8997 |
+
$blog_ids = $this->get_non_delegated_blog_ids();
|
8998 |
+
}
|
8999 |
+
else
|
9000 |
+
{
|
9001 |
+
if ( false === $network_or_blog_ids ) {
|
9002 |
+
$network_or_blog_ids = 0;
|
9003 |
+
}
|
9004 |
+
|
9005 |
+
$blog_ids = is_array( $network_or_blog_ids ) ?
|
9006 |
+
$network_or_blog_ids :
|
9007 |
+
array( $network_or_blog_ids );
|
9008 |
+
|
9009 |
+
foreach ( $blog_ids as $blog_id ) {
|
9010 |
+
if ( 0 === $blog_id || get_current_blog_id() == $blog_id ) {
|
9011 |
+
$this->_is_anonymous = null;
|
9012 |
+
}
|
9013 |
+
}
|
9014 |
+
}
|
9015 |
+
|
9016 |
+
foreach ( $blog_ids as $blog_id ) {
|
9017 |
+
$this->unset_anonymous_mode( $blog_id );
|
9018 |
}
|
9019 |
|
9020 |
/**
|
9025 |
* @author Leo Fajardo (@leorw)
|
9026 |
* @since 1.2.2
|
9027 |
*/
|
9028 |
+
if ( ! $this->_is_network_active ) {
|
|
|
|
|
|
|
|
|
9029 |
$this->_is_anonymous = null;
|
9030 |
}
|
9031 |
}
|
9071 |
* @author Vova Feldman (@svovaf)
|
9072 |
* @since 1.1.1
|
9073 |
*
|
9074 |
+
* @param bool|int|int[] $network_or_blog_ids Since 2.5.1
|
|
|
9075 |
*/
|
9076 |
+
function skip_connection( $network_or_blog_ids = false ) {
|
9077 |
$this->_logger->entrance();
|
9078 |
|
9079 |
$this->_admin_notices->remove_sticky( 'connect_account' );
|
9080 |
|
9081 |
+
if ( true === $network_or_blog_ids ) {
|
9082 |
$this->set_anonymous_mode( true, true );
|
|
|
9083 |
|
9084 |
+
if ( fs_is_network_admin() ) {
|
9085 |
+
$this->_is_anonymous = null;
|
9086 |
+
}
|
9087 |
+
|
9088 |
+
// Rest anonymous mode for all non-delegated sub-sites.
|
9089 |
+
$blog_ids = $this->get_non_delegated_blog_ids();
|
9090 |
+
}
|
9091 |
+
else
|
9092 |
+
{
|
9093 |
+
if ( false === $network_or_blog_ids ) {
|
9094 |
+
$network_or_blog_ids = 0;
|
9095 |
+
}
|
9096 |
|
9097 |
+
$blog_ids = is_array( $network_or_blog_ids ) ?
|
9098 |
+
$network_or_blog_ids :
|
9099 |
+
array( $network_or_blog_ids );
|
9100 |
|
9101 |
+
foreach ( $blog_ids as $blog_id ) {
|
9102 |
+
if ( 0 === $blog_id || get_current_blog_id() == $blog_id ) {
|
9103 |
+
$this->_is_anonymous = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9104 |
}
|
9105 |
}
|
9106 |
+
}
|
9107 |
|
9108 |
+
foreach ( $blog_ids as $blog_id ) {
|
9109 |
+
$this->skip_site_connection( $blog_id );
|
|
|
|
|
|
|
9110 |
}
|
9111 |
|
9112 |
$this->network_upgrade_mode_completed();
|
9121 |
* @param int|null $blog_id
|
9122 |
* @param bool $send_skip
|
9123 |
*/
|
9124 |
+
private function skip_site_connection( $blog_id = null ) {
|
9125 |
$this->_logger->entrance();
|
9126 |
|
9127 |
$this->_admin_notices->remove_sticky( 'connect_account', $blog_id );
|
9128 |
|
9129 |
$this->set_anonymous_mode( true, $blog_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
9130 |
}
|
9131 |
|
9132 |
/**
|
9498 |
* @param string[] $override
|
9499 |
* @param bool $include_plugins Since 1.1.8 by default include plugin changes.
|
9500 |
* @param bool $include_themes Since 1.1.8 by default include plugin changes.
|
9501 |
+
* @param bool $include_blog_data Since 2.3.0 by default include the current blog's data (language, title, and URL).
|
9502 |
*
|
9503 |
* @return array
|
9504 |
*/
|
9508 |
$include_themes = true,
|
9509 |
$include_blog_data = true
|
9510 |
) {
|
9511 |
+
// Alias.
|
9512 |
+
$permissions = FS_Permission_Manager::instance( $this );
|
9513 |
+
|
9514 |
+
if ( $permissions->is_extensions_tracking_allowed() ) {
|
9515 |
if ( ! defined( 'WP_FS__TRACK_PLUGINS' ) || false !== WP_FS__TRACK_PLUGINS ) {
|
9516 |
/**
|
9517 |
* @since 1.1.8 Also send plugin updates.
|
9539 |
|
9540 |
$versions = $this->get_versions();
|
9541 |
|
9542 |
+
$blog_data = array();
|
9543 |
+
if ( $include_blog_data ) {
|
9544 |
+
$blog_data['url'] = self::get_unfiltered_site_url();
|
9545 |
+
|
9546 |
+
if ( $permissions->is_diagnostic_tracking_allowed() ) {
|
9547 |
+
$blog_data = array_merge( $blog_data, array(
|
9548 |
+
'language' => self::get_sanitized_language(),
|
9549 |
+
'title' => get_bloginfo( 'name' ),
|
9550 |
+
) );
|
9551 |
+
}
|
9552 |
+
}
|
9553 |
|
9554 |
return array_merge( $versions, $blog_data, array(
|
9555 |
'version' => $this->get_plugin_version(),
|
9556 |
'is_premium' => $this->is_premium(),
|
9557 |
// Special params.
|
9558 |
'is_active' => true,
|
|
|
9559 |
'is_uninstalled' => false,
|
9560 |
), $override );
|
9561 |
}
|
9570 |
*
|
9571 |
* @param string[] string $override
|
9572 |
* @param bool $only_diff
|
9573 |
+
* @param bool $is_keepalive
|
9574 |
* @param bool $include_plugins Since 1.1.8 by default include plugin changes.
|
9575 |
* @param bool $include_themes Since 1.1.8 by default include plugin changes.
|
9576 |
*
|
9579 |
private function get_installs_data_for_api(
|
9580 |
array $override,
|
9581 |
$only_diff = false,
|
9582 |
+
$is_keepalive = false,
|
9583 |
$include_plugins = true,
|
9584 |
$include_themes = true
|
9585 |
) {
|
9617 |
|
9618 |
$sites = self::get_sites();
|
9619 |
|
9620 |
+
$subsite_data_for_api_by_install_id = array();
|
9621 |
+
$install_url_by_install_id = array();
|
9622 |
+
$subsite_registration_date_by_install_id = array();
|
9623 |
+
|
9624 |
foreach ( $sites as $site ) {
|
9625 |
$blog_id = self::get_site_blog_id( $site );
|
9626 |
|
9632 |
continue;
|
9633 |
}
|
9634 |
|
9635 |
+
if ( ! $this->is_tracking_allowed( $blog_id, $install ) ) {
|
9636 |
// Don't send updates regarding opted-out installs.
|
9637 |
continue;
|
9638 |
}
|
9639 |
|
9640 |
+
$install_data = $this->get_site_info( $site, true );
|
9641 |
+
|
9642 |
+
if ( FS_Clone_Manager::instance()->is_temporary_duplicate_by_blog_id( $install_data['blog_id'] ) ) {
|
9643 |
+
continue;
|
9644 |
+
}
|
9645 |
+
|
9646 |
+
$uid = $install_data['uid'];
|
9647 |
+
$url = $install_data['url'];
|
9648 |
+
$registration_date = $install_data['registration_date'];
|
9649 |
+
|
9650 |
+
if ( isset( $subsite_data_for_api_by_install_id[ $install->id ] ) ) {
|
9651 |
+
$clone_subsite_data = $subsite_data_for_api_by_install_id[ $install->id ];
|
9652 |
+
$clone_install_url = $install_url_by_install_id[ $install->id ];
|
9653 |
+
$clone_subsite_registration_date = $subsite_registration_date_by_install_id[ $install->id ];
|
9654 |
+
|
9655 |
+
$skip = false;
|
9656 |
+
|
9657 |
+
if (
|
9658 |
+
! empty( $install_data['registration_date'] ) &&
|
9659 |
+
! empty( $clone_subsite_registration_date )
|
9660 |
+
) {
|
9661 |
+
/**
|
9662 |
+
* If the current subsite was created after the other subsite that is also linked to the same install ID, we assume that it's a clone (not the original), and therefore, would skip its processing.
|
9663 |
+
*
|
9664 |
+
* @author Leo Fajardo (@leorw)
|
9665 |
+
* @since 2.5.1
|
9666 |
+
*/
|
9667 |
+
$skip = ( strtotime( $install_data['registration_date'] ) > strtotime( $clone_subsite_registration_date ) );
|
9668 |
+
} else if (
|
9669 |
+
/**
|
9670 |
+
* If we already have an install with the same URL as the subsite it's stored in, skip the current subsite. Otherwise, replace the existing install's data with the current subsite's install's data if the URLs match.
|
9671 |
+
*
|
9672 |
+
* @author Leo Fajardo (@leorw)
|
9673 |
+
* @since 2.5.0
|
9674 |
+
*/
|
9675 |
+
fs_strip_url_protocol( untrailingslashit( $clone_install_url ) ) === fs_strip_url_protocol( untrailingslashit( $clone_subsite_data['url'] ) ) ||
|
9676 |
+
fs_strip_url_protocol( untrailingslashit( $install->url ) ) !== fs_strip_url_protocol( untrailingslashit( $url ) )
|
9677 |
+
) {
|
9678 |
+
$skip = true;
|
9679 |
+
}
|
9680 |
|
9681 |
+
if ( $skip ) {
|
9682 |
+
// Store the skipped subsite's ID so that the clone resolution manager can try to resolve the clone install that is stored in that subsite later on.
|
9683 |
+
FS_Clone_Manager::instance()->store_blog_install_info( $blog_id );
|
9684 |
+
continue;
|
9685 |
+
}
|
9686 |
+
}
|
9687 |
|
9688 |
unset( $install_data['blog_id'] );
|
9689 |
unset( $install_data['uid'] );
|
9690 |
+
unset( $install_data['url'] );
|
9691 |
+
unset( $install_data['registration_date'] );
|
9692 |
|
|
|
9693 |
$install_data['is_active'] = $this->is_active_for_site( $blog_id );
|
9694 |
$install_data['is_uninstalled'] = $install->is_uninstalled;
|
9695 |
|
9712 |
$is_common_diff_for_any_site = $is_common_diff_for_any_site || $is_common_diff;
|
9713 |
}
|
9714 |
|
9715 |
+
if ( ! empty( $install_data ) || $is_common_diff || $is_keepalive ) {
|
9716 |
// Add install ID and site unique ID.
|
9717 |
$install_data['id'] = $install->id;
|
9718 |
$install_data['uid'] = $uid;
|
9719 |
+
$install_data['url'] = $url;
|
9720 |
|
9721 |
+
$subsite_data_for_api_by_install_id[ $install->id ] = $install_data;
|
9722 |
+
$install_url_by_install_id[ $install->id ] = $install->url;
|
9723 |
+
$subsite_registration_date_by_install_id[ $install->id ] = $registration_date;
|
9724 |
}
|
9725 |
}
|
9726 |
}
|
9727 |
|
9728 |
restore_current_blog();
|
9729 |
|
9730 |
+
$installs_data = array_merge(
|
9731 |
+
$installs_data,
|
9732 |
+
array_values( $subsite_data_for_api_by_install_id )
|
9733 |
+
);
|
9734 |
+
|
9735 |
if ( 0 < count( $installs_data ) && ( $is_common_diff_for_any_site || ! $only_diff ) ) {
|
9736 |
if ( ! $only_diff ) {
|
9737 |
$installs_data[] = $common;
|
9769 |
if ( ( is_bool( $install->{$p} ) || ! empty( $install->{$p} ) ) &&
|
9770 |
$install->{$p} != $v
|
9771 |
) {
|
9772 |
+
$val = self::get_api_sanitized_property( $p, $v );
|
9773 |
+
|
9774 |
+
if ( $install->{$p} != $val ) {
|
9775 |
+
$install->{$p} = $val;
|
9776 |
+
$diff[ $p ] = $val;
|
9777 |
+
}
|
9778 |
}
|
9779 |
} else {
|
9780 |
$special[ $p ] = $v;
|
9799 |
return $diff;
|
9800 |
}
|
9801 |
|
9802 |
+
/**
|
9803 |
+
* @author Leo Fajardo (@leorw)
|
9804 |
+
* @since 2.5.1
|
9805 |
+
*/
|
9806 |
+
private function send_pending_clone_update_once() {
|
9807 |
+
$this->_logger->entrance();
|
9808 |
+
|
9809 |
+
if ( ! empty( $this->_storage->clone_id ) ) {
|
9810 |
+
return;
|
9811 |
+
}
|
9812 |
+
|
9813 |
+
$install_clone = $this->get_api_site_scope()->call(
|
9814 |
+
'/clones',
|
9815 |
+
'post',
|
9816 |
+
array( 'site_url' => self::get_unfiltered_site_url() )
|
9817 |
+
);
|
9818 |
+
|
9819 |
+
if ( $this->is_api_result_entity( $install_clone ) ) {
|
9820 |
+
$this->_storage->clone_id = $install_clone->id;
|
9821 |
+
}
|
9822 |
+
}
|
9823 |
+
|
9824 |
+
/**
|
9825 |
+
* @author Leo Fajardo (@leorw)
|
9826 |
+
* @since 2.5.1
|
9827 |
+
*
|
9828 |
+
* @param string $resolution_type
|
9829 |
+
* @param FS_Site $clone_context_install
|
9830 |
+
*/
|
9831 |
+
function send_clone_resolution_update( $resolution_type, $clone_context_install ) {
|
9832 |
+
$this->_logger->entrance();
|
9833 |
+
|
9834 |
+
if ( empty( $this->_storage->clone_id ) ) {
|
9835 |
+
return;
|
9836 |
+
}
|
9837 |
+
|
9838 |
+
$new_install_id = null;
|
9839 |
+
$current_site = null;
|
9840 |
+
|
9841 |
+
$flush = false;
|
9842 |
+
|
9843 |
+
/**
|
9844 |
+
* If the current site is now different from the context install before the clone resolution, we need to override `$this->_site` so that the API call below will be made with the right install scope entity.
|
9845 |
+
*/
|
9846 |
+
if ( $clone_context_install->id != $this->_site->id ) {
|
9847 |
+
$new_install_id = $this->_site->id;
|
9848 |
+
$current_site = $this->_site;
|
9849 |
+
$this->_site = $clone_context_install;
|
9850 |
+
|
9851 |
+
$flush = true;
|
9852 |
+
}
|
9853 |
+
|
9854 |
+
$this->get_api_site_scope( $flush )->call(
|
9855 |
+
"/clones/{$this->_storage->clone_id}",
|
9856 |
+
'put',
|
9857 |
+
array(
|
9858 |
+
'resolution' => $resolution_type,
|
9859 |
+
'new_install_id' => $new_install_id,
|
9860 |
+
)
|
9861 |
+
);
|
9862 |
+
|
9863 |
+
if ( is_object( $current_site ) ) {
|
9864 |
+
/**
|
9865 |
+
* Ensure that the install scope entity is updated back to the previous install entity.
|
9866 |
+
*/
|
9867 |
+
$this->_site = $current_site;
|
9868 |
+
|
9869 |
+
// Restore the previous install scope entity of the API.
|
9870 |
+
$this->get_api_site_scope( true );
|
9871 |
+
}
|
9872 |
+
}
|
9873 |
+
|
9874 |
/**
|
9875 |
* Update install only if changed.
|
9876 |
*
|
9879 |
*
|
9880 |
* @param string[] string $override
|
9881 |
* @param bool $flush
|
9882 |
+
* @param bool $is_two_way_sync @since 2.5.0 If true and there's a successful API request, the install sync cron will be cleared.
|
9883 |
*
|
9884 |
* @return false|object|string
|
9885 |
*/
|
9886 |
+
private function send_install_update( $override = array(), $flush = false, $is_two_way_sync = false ) {
|
9887 |
$this->_logger->entrance();
|
9888 |
|
9889 |
$check_properties = $this->get_install_data_for_api( $override );
|
9894 |
$params = $this->get_install_diff_for_api( $check_properties, $this->_site, $override );
|
9895 |
}
|
9896 |
|
|
|
9897 |
if ( empty( $params ) ) {
|
9898 |
$keepalive_only_update = $this->should_send_keepalive_update();
|
9899 |
|
9908 |
}
|
9909 |
}
|
9910 |
|
9911 |
+
if ( $is_two_way_sync ) {
|
9912 |
/**
|
9913 |
+
* Update last install sync timestamp during a two-way sync call as we expect that updates are sent during this call.
|
|
|
9914 |
*
|
9915 |
* @author Leo Fajardo (@leorw)
|
9916 |
* @since 2.2.3
|
9926 |
$this->set_keepalive_timestamp();
|
9927 |
|
9928 |
// Send updated values to FS.
|
9929 |
+
$site = $this->api_site_call( '/', 'put', $params, true );
|
9930 |
|
9931 |
+
if ( $is_two_way_sync && $this->is_api_result_entity( $site ) ) {
|
9932 |
/**
|
9933 |
+
* Clear scheduled install sync after a two-way sync call.
|
9934 |
*
|
9935 |
* @author Leo Fajardo (@leorw)
|
9936 |
* @since 2.2.3
|
9952 |
*
|
9953 |
* @param string[] string $override
|
9954 |
* @param bool $flush
|
9955 |
+
* @param bool $is_two_way_sync @since 2.5.0 If true and there's a successful API request, the install sync cron will be cleared.
|
9956 |
*
|
9957 |
* @return false|object|string
|
9958 |
*/
|
9959 |
+
private function send_installs_update( $override = array(), $flush = false, $is_two_way_sync = false ) {
|
9960 |
$this->_logger->entrance();
|
9961 |
|
9962 |
+
/**
|
9963 |
+
* Pass `true` to use the network level storage since the update is for many installs.
|
9964 |
+
*
|
9965 |
+
* @author Leo Fajardo (@leorw)
|
9966 |
+
* @since 2.2.3
|
9967 |
+
*/
|
9968 |
+
$should_send_keepalive = $this->should_send_keepalive_update( true );
|
9969 |
|
9970 |
+
$installs_data = $this->get_installs_data_for_api( $override, ! $flush, $should_send_keepalive );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9971 |
|
9972 |
+
if ( empty( $installs_data ) ) {
|
9973 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9974 |
}
|
9975 |
|
9976 |
+
if ( $is_two_way_sync ) {
|
9977 |
+
// Update last install sync timestamp during a two-way sync call as we expect that updates are sent during this call.
|
9978 |
$this->set_cron_execution_timestamp( 'install_sync' );
|
9979 |
}
|
9980 |
|
9989 |
// Send updated values to FS.
|
9990 |
$result = $this->get_api_user_scope()->call( "/plugins/{$this->_plugin->id}/installs.json", 'put', $installs_data );
|
9991 |
|
9992 |
+
if ( $is_two_way_sync && $this->is_api_result_object( $result, 'installs' ) ) {
|
9993 |
+
// I successfully sent a two-way installs update, clear the scheduled install sync if it exists.
|
9994 |
$this->clear_install_sync_cron();
|
9995 |
}
|
9996 |
|
10040 |
* @param string[] string $override
|
10041 |
* @param bool $flush
|
10042 |
*/
|
10043 |
+
function sync_install( $override = array(), $flush = false ) {
|
10044 |
$this->_logger->entrance();
|
10045 |
|
10046 |
+
$site = $this->send_install_update( $override, $flush, true );
|
10047 |
|
10048 |
if ( false === $site ) {
|
10049 |
// No sync required.
|
10072 |
private function sync_installs( $override = array(), $flush = false ) {
|
10073 |
$this->_logger->entrance();
|
10074 |
|
10075 |
+
$result = $this->send_installs_update( $override, $flush, true );
|
10076 |
|
10077 |
if ( false === $result ) {
|
10078 |
// No sync required.
|
10227 |
// Send uninstall event.
|
10228 |
$this->send_installs_update( $params );
|
10229 |
} else {
|
10230 |
+
// Send uninstall event and handle the result.
|
10231 |
+
$this->sync_install( $params );
|
10232 |
}
|
10233 |
}
|
10234 |
|
10325 |
return;
|
10326 |
}
|
10327 |
|
10328 |
+
if (
|
10329 |
+
! $fs->is_clone() &&
|
10330 |
+
/**
|
10331 |
+
* If there's a context install, run this method only when there's also a context user (e.g., when cloning a subsite of a multisite network into a single-site installation, it's possible for an install to be associated with a non-existing user entity; we want Freemius to be off in this case, while we are trying to recover the user).
|
10332 |
+
*
|
10333 |
+
* @author Leo Fajardo
|
10334 |
+
*/
|
10335 |
+
( ! is_object( $fs->_site ) || $fs->is_registered() )
|
10336 |
+
) {
|
10337 |
+
$fs->_uninstall_plugin_event();
|
10338 |
+
}
|
10339 |
|
10340 |
$fs->do_action( 'after_uninstall' );
|
10341 |
}
|
10446 |
* @return string
|
10447 |
*/
|
10448 |
function get_premium_slug() {
|
10449 |
+
return ( is_object( $this->_plugin ) && ! empty( $this->_plugin->premium_slug ) ) ?
|
10450 |
$this->_plugin->premium_slug :
|
10451 |
"{$this->_slug}-premium";
|
10452 |
}
|
10499 |
null;
|
10500 |
}
|
10501 |
|
10502 |
+
/**
|
10503 |
+
* Get whether the SDK has been initiated in the context of a Bundle.
|
10504 |
+
*
|
10505 |
+
* This will return true, if `bundle_id` is present in the SDK init parameters.
|
10506 |
+
*
|
10507 |
+
* ```php
|
10508 |
+
* $my_fs = fs_dynamic_init( array(
|
10509 |
+
* // ...
|
10510 |
+
* 'bundle_id' => 'XXXX', // Will return true since we have bundle id.
|
10511 |
+
* 'bundle_public_key' => 'pk_XXXX',
|
10512 |
+
* ) );
|
10513 |
+
* ```
|
10514 |
+
*
|
10515 |
+
* @author Swashata Ghosh (@swashata)
|
10516 |
+
* @since 2.5.0
|
10517 |
+
*
|
10518 |
+
* @return bool True if we are running in bundle context, false otherwise.
|
10519 |
+
*/
|
10520 |
+
private function has_bundle_context() {
|
10521 |
+
return ! is_null( $this->get_bundle_id() );
|
10522 |
+
}
|
10523 |
+
|
10524 |
/**
|
10525 |
* @author Vova Feldman (@svovaf)
|
10526 |
* @since 1.2.1.5
|
10565 |
function get_eula_url() {
|
10566 |
return $this->apply_filters(
|
10567 |
'eula_url',
|
10568 |
+
"https://freemius.com/product/{$this->_plugin->id}/{$this->_slug}/legal/eula/"
|
10569 |
);
|
10570 |
}
|
10571 |
|
10753 |
#endregion ------------------------------------------------------------------
|
10754 |
|
10755 |
/* Account
|
10756 |
+
------------------------------------------------------------------------------------------------------------------*/
|
10757 |
|
10758 |
/**
|
10759 |
* Find plugin's slug by plugin's basename.
|
10817 |
*/
|
10818 |
private static function get_all_sites(
|
10819 |
$module_type = WP_FS__MODULE_TYPE_PLUGIN,
|
10820 |
+
$blog_id = null,
|
10821 |
+
$is_backup = false
|
10822 |
) {
|
10823 |
+
$sites = self::get_account_option(
|
10824 |
+
( $is_backup ? 'prev_' : '' ) . 'sites',
|
10825 |
+
$module_type,
|
10826 |
+
$blog_id
|
10827 |
+
);
|
10828 |
|
10829 |
if ( ! is_array( $sites ) ) {
|
10830 |
$sites = array();
|
11184 |
*
|
11185 |
* @author Vova Feldman (@svovaf)
|
11186 |
* @since 1.0.1
|
11187 |
+
*
|
11188 |
+
* @param bool $ignore_anonymous_state Since 2.5.1
|
11189 |
+
*
|
11190 |
* @return bool
|
11191 |
*/
|
11192 |
+
function is_registered( $ignore_anonymous_state = false ) {
|
11193 |
+
return (
|
11194 |
+
is_object( $this->_user ) &&
|
11195 |
+
(
|
11196 |
+
$this->is_premium() ||
|
11197 |
+
$ignore_anonymous_state ||
|
11198 |
+
! $this->is_anonymous()
|
11199 |
+
)
|
11200 |
+
);
|
11201 |
}
|
11202 |
|
11203 |
/**
|
11208 |
*
|
11209 |
* @return bool
|
11210 |
*/
|
11211 |
+
function is_tracking_allowed( $blog_id = null, $install = null ) {
|
11212 |
+
if ( is_null( $install ) ) {
|
11213 |
+
$install = is_null( $blog_id ) ?
|
11214 |
+
$this->_site :
|
11215 |
+
$this->get_install_by_blog_id( $blog_id );
|
11216 |
+
}
|
11217 |
+
|
11218 |
+
return (
|
11219 |
+
is_object( $install ) &&
|
11220 |
+
FS_Permission_Manager::instance( $this )->is_homepage_url_tracking_allowed( $blog_id )
|
11221 |
+
);
|
11222 |
+
}
|
11223 |
+
|
11224 |
+
/**
|
11225 |
+
* Returns TRUE if the user never opted-in or manually opted-out.
|
11226 |
+
*
|
11227 |
+
* @author Vova Feldman (@svovaf)
|
11228 |
+
* @since 1.2.1.5
|
11229 |
+
*
|
11230 |
+
* @param int|null $blog_id
|
11231 |
+
*
|
11232 |
+
* @return bool
|
11233 |
+
*/
|
11234 |
+
function is_tracking_prohibited( $blog_id = null ) {
|
11235 |
+
return (
|
11236 |
+
! $this->is_registered( true ) ||
|
11237 |
+
! $this->is_tracking_allowed( $blog_id )
|
11238 |
+
);
|
11239 |
}
|
11240 |
|
11241 |
/**
|
11271 |
}
|
11272 |
|
11273 |
/**
|
11274 |
+
* @author Vova Feldman (@svovaf)
|
11275 |
+
* @since 1.0.3
|
11276 |
+
*
|
11277 |
+
* @return FS_Site
|
11278 |
+
*/
|
11279 |
+
function get_site() {
|
11280 |
+
return $this->_site;
|
11281 |
+
}
|
11282 |
+
|
11283 |
+
/**
|
11284 |
+
* @author Leo Fajardo (@leorw)
|
11285 |
+
* @since 2.5.0
|
11286 |
+
*/
|
11287 |
+
function store_site( $site ) {
|
11288 |
+
$this->_site = $site;
|
11289 |
+
$this->_store_site( true );
|
11290 |
+
}
|
11291 |
+
|
11292 |
+
/**
|
11293 |
+
* Deletes the current install with an option to back it up in case restoration will be needed (e.g., if the automatic clone resolution attempt fails).
|
11294 |
+
*
|
11295 |
+
* @author Leo Fajardo (@leorw)
|
11296 |
+
* @since 2.5.0
|
11297 |
+
*/
|
11298 |
+
function delete_current_install( $back_up ) {
|
11299 |
+
// Back up and delete the unique ID.
|
11300 |
+
if ( $back_up ) {
|
11301 |
+
self::$_accounts->set_option( 'prev_unique_id', $this->get_anonymous_id() );
|
11302 |
+
}
|
11303 |
+
|
11304 |
+
self::$_accounts->set_option( 'unique_id', null );
|
11305 |
+
|
11306 |
+
if ( $back_up ) {
|
11307 |
+
// Back up the install before deleting it so that it can be restored later on if necessary (e.g., if the automatic clone resolution attempt fails).
|
11308 |
+
$this->back_up_site();
|
11309 |
+
}
|
11310 |
+
|
11311 |
+
$this->_delete_site();
|
11312 |
+
$this->_site = null;
|
11313 |
+
}
|
11314 |
+
|
11315 |
+
/**
|
11316 |
+
* @author Leo Fajardo (@leorw)
|
11317 |
+
* @since 2.5.0
|
11318 |
*/
|
11319 |
+
function restore_backup_site() {
|
11320 |
+
self::$_accounts->set_option(
|
11321 |
+
'unique_id',
|
11322 |
+
self::$_accounts->get_option( 'prev_unique_id' )
|
11323 |
+
);
|
11324 |
+
|
11325 |
+
$sites = self::get_all_sites( $this->_module_type, null, true );
|
11326 |
+
$this->store_site( clone $sites[ $this->_slug ] );
|
11327 |
}
|
11328 |
|
11329 |
/**
|
12607 |
} else {
|
12608 |
$url = is_object( $site ) ?
|
12609 |
$site->siteurl :
|
12610 |
+
self::get_unfiltered_site_url( $blog_id );
|
12611 |
|
12612 |
$disconnected_site_ids[] = $blog_id;
|
12613 |
}
|
12980 |
} else if ( $is_whitelabeled_flag ) {
|
12981 |
$is_whitelabeled = true;
|
12982 |
} else {
|
12983 |
+
if ( $this->is_registered() || $this->is_premium() ) {
|
12984 |
+
$addon_ids = $this->get_updated_account_addons();
|
12985 |
+
} else {
|
12986 |
+
$addons = self::get_all_addons();
|
12987 |
+
|
12988 |
+
$plugin_addons = isset( $addons[ $this->_plugin->id ] ) ?
|
12989 |
+
$addons[ $this->_plugin->id ] :
|
12990 |
+
array();
|
12991 |
+
|
12992 |
+
$addon_ids = array();
|
12993 |
+
foreach ( $plugin_addons as $addon ) {
|
12994 |
+
$addon_ids[] = $addon->id;
|
12995 |
+
}
|
12996 |
+
}
|
12997 |
+
|
12998 |
$installed_addons = $this->get_installed_addons();
|
12999 |
foreach ( $installed_addons as $fs_addon ) {
|
13000 |
$addon_ids[] = $fs_addon->get_id();
|
13423 |
fs_require_template( 'forms/resend-key.php', $vars );
|
13424 |
}
|
13425 |
|
13426 |
+
/**
|
13427 |
+
* Displays an email address update dialog box when the user clicks on the email address "Edit" button on the "Account" page.
|
13428 |
+
*
|
13429 |
+
* @author Leo Fajardo (@leorw)
|
13430 |
+
* @since 2.5.0
|
13431 |
+
*/
|
13432 |
+
function _add_email_address_update_dialog_box() {
|
13433 |
+
$vars = array( 'id' => $this->_module_id );
|
13434 |
+
|
13435 |
+
fs_require_template( 'forms/email-address-update.php', $vars );
|
13436 |
+
}
|
13437 |
+
|
13438 |
+
/**
|
13439 |
+
* @author Leo Fajardo (@leorw)
|
13440 |
+
* @since 2.5.0
|
13441 |
+
*/
|
13442 |
+
function _add_email_address_update_option() {
|
13443 |
+
if ( ! $this->should_handle_user_change() ) {
|
13444 |
+
return;
|
13445 |
+
}
|
13446 |
+
|
13447 |
+
// Add email address update AJAX handler.
|
13448 |
+
$this->add_ajax_action( 'update_email_address', array( &$this, '_email_address_update_ajax_handler' ) );
|
13449 |
+
}
|
13450 |
+
|
13451 |
+
/**
|
13452 |
+
* @author Leo Fajardo (@leorw)
|
13453 |
+
* @since 2.5.0
|
13454 |
+
*/
|
13455 |
+
function _email_address_update_ajax_handler() {
|
13456 |
+
$this->check_ajax_referer( 'update_email_address' );
|
13457 |
+
|
13458 |
+
$new_email_address = fs_request_get( 'email_address' );
|
13459 |
+
$transfer_type = fs_request_get( 'transfer_type' );
|
13460 |
+
|
13461 |
+
$result = $this->update_email( $new_email_address );
|
13462 |
+
|
13463 |
+
if ( ! FS_Api::is_api_error( $result ) ) {
|
13464 |
+
self::shoot_ajax_success();
|
13465 |
+
}
|
13466 |
+
|
13467 |
+
$error = '';
|
13468 |
+
|
13469 |
+
if ( FS_Api::is_api_error_object( $result ) ) {
|
13470 |
+
switch ( $result->error->code ) {
|
13471 |
+
case 'user_exist':
|
13472 |
+
case 'account_verification_required':
|
13473 |
+
$error = array(
|
13474 |
+
'code' => 'change_ownership',
|
13475 |
+
'url' => $this->get_account_url( 'change_owner', array(
|
13476 |
+
'state' => 'init',
|
13477 |
+
'candidate_email' => $new_email_address,
|
13478 |
+
'transfer_type' => $transfer_type,
|
13479 |
+
) ),
|
13480 |
+
);
|
13481 |
+
|
13482 |
+
break;
|
13483 |
+
}
|
13484 |
+
}
|
13485 |
+
|
13486 |
+
if ( empty( $error ) ) {
|
13487 |
+
$error = is_object( $result ) ?
|
13488 |
+
var_export( $result->error, true ) :
|
13489 |
+
$result;
|
13490 |
+
}
|
13491 |
+
|
13492 |
+
self::shoot_ajax_failure( $error );
|
13493 |
+
}
|
13494 |
+
|
13495 |
/**
|
13496 |
* Returns a collection of IDs of installs that are associated with the context product and its add-ons, and activated with foreign licenses.
|
13497 |
*
|
13699 |
( $is_network_admin && $this->is_network_active() && ! $this->is_network_delegated_connection() ) ||
|
13700 |
( ! $is_network_admin && ( ! $this->is_network_active() || $this->is_delegated_connection() ) )
|
13701 |
) {
|
13702 |
+
if (
|
13703 |
+
$this->is_premium() ||
|
13704 |
+
( $this->has_paid_plan() && ! $this->has_premium_version() )
|
13705 |
+
) {
|
13706 |
+
/**
|
13707 |
+
* @since 1.2.0 Add license action link only on plugins page.
|
13708 |
+
*/
|
13709 |
+
$this->_add_license_action_link();
|
13710 |
+
}
|
13711 |
}
|
13712 |
}
|
13713 |
|
13879 |
self::shoot_ajax_failure();
|
13880 |
}
|
13881 |
|
13882 |
+
$site = $this->api_site_call(
|
13883 |
'',
|
13884 |
'put',
|
13885 |
array(
|
13932 |
fs_request_get( 'blog_id', null ),
|
13933 |
fs_request_get( 'module_id', null, 'post' ),
|
13934 |
fs_request_get( 'user_id', null ),
|
13935 |
+
fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
|
13936 |
+
fs_request_get_bool( 'is_diagnostic_tracking_allowed', null )
|
13937 |
);
|
13938 |
|
13939 |
if (
|
14178 |
* @param null|int $blog_id
|
14179 |
* @param null|number $plugin_id
|
14180 |
* @param null|number $license_owner_id
|
14181 |
+
* @param bool|null $is_extensions_tracking_allowed
|
14182 |
+
* @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2 to allow license activation with minimal data footprint.
|
14183 |
+
*
|
14184 |
*
|
14185 |
* @return array {
|
14186 |
* @var bool $success
|
14195 |
$blog_id = null,
|
14196 |
$plugin_id = null,
|
14197 |
$license_owner_id = null,
|
14198 |
+
$is_extensions_tracking_allowed = null,
|
14199 |
+
$is_diagnostic_tracking_allowed = null
|
14200 |
) {
|
14201 |
$this->_logger->entrance();
|
14202 |
|
14216 |
$this :
|
14217 |
$this->get_addon_instance( $plugin_id );
|
14218 |
|
14219 |
+
FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array(
|
14220 |
+
FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed,
|
14221 |
+
FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed,
|
14222 |
+
) );
|
14223 |
|
14224 |
$error = false;
|
14225 |
$next_page = false;
|
14384 |
}
|
14385 |
}
|
14386 |
|
14387 |
+
$all_sites = self::get_sites();
|
14388 |
+
$pending_blog_ids = array();
|
14389 |
|
14390 |
/**
|
14391 |
* Check if there are any sites that are not connected, skipped, nor delegated. For every site that falls into that category, if the product is freemium, skip the connection. If the product is premium only, delegate the connection to the site administrator.
|
14415 |
continue;
|
14416 |
}
|
14417 |
|
14418 |
+
$pending_blog_ids[] = $blog_id;
|
14419 |
}
|
14420 |
|
14421 |
+
if ( ! empty( $pending_blog_ids ) ) {
|
14422 |
if ( $fs->is_freemium() && $fs->is_enable_anonymous() ) {
|
14423 |
+
$fs->skip_connection( $pending_blog_ids );
|
14424 |
} else {
|
14425 |
+
$fs->delegate_connection( $pending_blog_ids );
|
14426 |
}
|
14427 |
}
|
14428 |
}
|
14500 |
|
14501 |
$addon_info = $fs->_get_addon_info( $addon_id, $is_installed );
|
14502 |
|
14503 |
+
if ( ! isset( $addon_info['is_connected'] ) || ! $addon_info['is_connected'] ) {
|
14504 |
// Add-on is not associated with an install entity.
|
14505 |
continue;
|
14506 |
}
|
14558 |
$this->delegate_connection();
|
14559 |
} else {
|
14560 |
if ( ! empty( $sites_by_action['delegate'] ) ) {
|
14561 |
+
$this->delegate_connection( self::get_sites_blog_ids( $sites_by_action['delegate'] ) );
|
14562 |
}
|
14563 |
|
14564 |
if ( ! empty( $sites_by_action['skip'] ) ) {
|
14565 |
+
$this->skip_connection( self::get_sites_blog_ids( $sites_by_action['skip'] ) );
|
14566 |
}
|
14567 |
|
14568 |
if ( empty( $sites_by_action['allow'] ) ) {
|
14880 |
return $this->_plugin->has_affiliate_program();
|
14881 |
}
|
14882 |
|
14883 |
+
/**
|
14884 |
+
* Get Plugin ID under which we will track affiliate application.
|
14885 |
+
*
|
14886 |
+
* This could either be the Bundle ID or the main plugin ID.
|
14887 |
+
*
|
14888 |
+
* @return number Bundle ID if developer has provided one, else the main plugin ID.
|
14889 |
+
*/
|
14890 |
+
private function get_plugin_id_for_affiliate_terms() {
|
14891 |
+
return $this->has_bundle_context() ?
|
14892 |
+
$this->get_bundle_id() :
|
14893 |
+
$this->_plugin_id;
|
14894 |
+
}
|
14895 |
+
|
14896 |
/**
|
14897 |
* @author Leo Fajardo (@leorw)
|
14898 |
* @since 1.2.4
|
14899 |
*/
|
14900 |
private function fetch_affiliate_terms() {
|
14901 |
if ( ! is_object( $this->plugin_affiliate_terms ) ) {
|
14902 |
+
/**
|
14903 |
+
* In case we have a bundle set in SDK configuration, we would like to use that for affiliates, not the main plugin.
|
14904 |
+
*/
|
14905 |
+
$plugins_api = $this->has_bundle_context() ?
|
14906 |
+
$this->get_api_bundle_scope() :
|
14907 |
+
$this->get_api_plugin_scope();
|
14908 |
+
|
14909 |
$affiliate_terms = $plugins_api->get( '/aff.json?type=affiliation', false );
|
14910 |
|
14911 |
+
/**
|
14912 |
+
* At this point, we intentionally don't fallback to the main plugin, because the developer has chosen to use bundle. So it makes sense the affiliate program should be in context to the bundle too.
|
14913 |
+
*/
|
14914 |
if ( ! $this->is_api_result_entity( $affiliate_terms ) ) {
|
14915 |
return;
|
14916 |
}
|
14928 |
$application_data = $this->_storage->affiliate_application_data;
|
14929 |
$flush = ( ! isset( $application_data['status'] ) || 'pending' === $application_data['status'] );
|
14930 |
|
14931 |
+
$plugin_id_for_affiliate = $this->get_plugin_id_for_affiliate_terms();
|
14932 |
+
|
14933 |
$users_api = $this->get_api_user_scope();
|
14934 |
+
$result = $users_api->get( "/plugins/{$plugin_id_for_affiliate}/aff/{$this->plugin_affiliate_terms->id}/affiliates.json", $flush );
|
14935 |
if ( $this->is_api_result_object( $result, 'affiliates' ) ) {
|
14936 |
if ( ! empty( $result->affiliates ) ) {
|
14937 |
$affiliate = new FS_Affiliate( $result->affiliates[0] );
|
15031 |
var_export( $next_page, true )
|
15032 |
);
|
15033 |
} else if ( $this->is_pending_activation() ) {
|
15034 |
+
self::shoot_ajax_failure( $this->get_text_inline( 'Account is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.', 'account-is-pending-activation' ) );
|
15035 |
}
|
15036 |
}
|
15037 |
|
15038 |
$this->fetch_affiliate_terms();
|
15039 |
|
15040 |
+
$plugin_id_for_affiliate = $this->get_plugin_id_for_affiliate_terms();
|
15041 |
+
|
15042 |
$api = $this->get_api_user_scope();
|
15043 |
$result = $api->call(
|
15044 |
+
( "/plugins/{$plugin_id_for_affiliate}/aff/{$this->plugin_affiliate_terms->id}/affiliates.json" ),
|
15045 |
'post',
|
15046 |
$affiliate
|
15047 |
);
|
15503 |
return ( defined( 'DOING_CRON' ) && DOING_CRON );
|
15504 |
}
|
15505 |
|
15506 |
+
/**
|
15507 |
+
* @author Leo Fajardo (@leorw)
|
15508 |
+
* @since 2.5.0
|
15509 |
+
*
|
15510 |
+
* @return bool
|
15511 |
+
*/
|
15512 |
+
static function is_admin_post() {
|
15513 |
+
return ( 'admin-post.php' === self::get_current_page() );
|
15514 |
+
}
|
15515 |
+
|
15516 |
/**
|
15517 |
* Check if a real user is visiting the admin dashboard.
|
15518 |
*
|
15526 |
is_admin() &&
|
15527 |
! self::is_ajax() &&
|
15528 |
! self::is_cron() &&
|
15529 |
+
! self::is_admin_post()
|
15530 |
);
|
15531 |
}
|
15532 |
|
15678 |
* @author Leo Fajardo (@leorw)
|
15679 |
* @since 2.0.0
|
15680 |
*
|
15681 |
+
* @param bool|int[] $all_or_blog_ids
|
15682 |
*/
|
15683 |
+
private function delegate_connection( $all_or_blog_ids = true ) {
|
15684 |
$this->_logger->entrance();
|
15685 |
|
15686 |
$this->_admin_notices->remove_sticky( 'connect_account' );
|
15687 |
|
15688 |
+
if ( true === $all_or_blog_ids ) {
|
15689 |
// All sites delegation.
|
15690 |
+
$this->_storage->store( 'is_delegated_connection', true, true );
|
15691 |
} else {
|
15692 |
// Specified sites delegation.
|
15693 |
+
foreach ( $all_or_blog_ids as $blog_id ) {
|
15694 |
+
$this->delegate_site_connection( $blog_id );
|
15695 |
}
|
15696 |
}
|
15697 |
|
15707 |
* @param int $blog_id
|
15708 |
*/
|
15709 |
private function delegate_site_connection( $blog_id ) {
|
15710 |
+
$this->_storage->store( 'is_delegated_connection', true, $blog_id );
|
15711 |
}
|
15712 |
|
15713 |
/**
|
15747 |
}
|
15748 |
|
15749 |
/**
|
15750 |
+
* Check if delegated the connection. When running within the network admin,
|
15751 |
* and haven't specified the blog ID, checks if network level delegated. If running
|
15752 |
* within a site admin or specified a blog ID, check if delegated the connection for
|
15753 |
* the current context site.
|
15807 |
}
|
15808 |
|
15809 |
/**
|
15810 |
+
* @todo Implement pagination when accessing the subsites collection.
|
15811 |
+
*
|
15812 |
* @author Leo Fajardo (@leorw)
|
15813 |
* @since 2.0.0
|
15814 |
*
|
15815 |
+
* @param int $limit Default to 1,000
|
15816 |
+
* @param int $offset Default to 0
|
15817 |
+
*
|
15818 |
* @return array Active & public sites collection.
|
15819 |
*/
|
15820 |
+
static function get_sites( $limit = 1000, $offset = 0 ) {
|
15821 |
if ( ! is_multisite() ) {
|
15822 |
return array();
|
15823 |
}
|
15839 |
'mature' => 0,
|
15840 |
'spam' => 0,
|
15841 |
'deleted' => 0,
|
15842 |
+
'number' => $limit,
|
15843 |
+
'offset' => $offset,
|
15844 |
);
|
15845 |
|
15846 |
+
return get_sites( $args );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15847 |
}
|
15848 |
|
15849 |
/**
|
15892 |
$address_to_blog_map = array();
|
15893 |
foreach ( $sites as $site ) {
|
15894 |
$blog_id = self::get_site_blog_id( $site );
|
15895 |
+
$address = self::get_unfiltered_site_url( $blog_id, true, true );
|
15896 |
$address_to_blog_map[ $address ] = $blog_id;
|
15897 |
}
|
15898 |
|
15928 |
return $install_map;
|
15929 |
}
|
15930 |
|
15931 |
+
/**
|
15932 |
+
* @author Vova Feldman (@svovaf)
|
15933 |
+
* @since 2.5.1
|
15934 |
+
*
|
15935 |
+
* @param bool|null $is_delegated When `true`, returns only connection delegated blog IDs. When `false`, only non-delegated blog IDs.
|
15936 |
+
*
|
15937 |
+
* @return int[]
|
15938 |
+
*/
|
15939 |
+
private function get_blog_ids( $is_delegated = null ) {
|
15940 |
+
$blog_ids = array();
|
15941 |
+
|
15942 |
+
$sites = self::get_sites();
|
15943 |
+
foreach ( $sites as $site ) {
|
15944 |
+
$blog_id = self::get_site_blog_id( $site );
|
15945 |
+
|
15946 |
+
if (
|
15947 |
+
is_null( $is_delegated ) ||
|
15948 |
+
$is_delegated === $this->is_site_delegated_connection( $blog_id )
|
15949 |
+
) {
|
15950 |
+
$blog_ids[] = $blog_id;
|
15951 |
+
}
|
15952 |
+
}
|
15953 |
+
|
15954 |
+
return $blog_ids;
|
15955 |
+
}
|
15956 |
+
|
15957 |
+
/**
|
15958 |
+
* @author Vova Feldman (@svovaf)
|
15959 |
+
* @since 2.5.1
|
15960 |
+
*
|
15961 |
+
* @return int[]
|
15962 |
+
*/
|
15963 |
+
private function get_non_delegated_blog_ids() {
|
15964 |
+
return $this->get_blog_ids( false );
|
15965 |
+
}
|
15966 |
+
|
15967 |
/**
|
15968 |
* Gets a map of module IDs that the given user has opted-in to.
|
15969 |
*
|
16048 |
*
|
16049 |
* @param int $blog_id
|
16050 |
* @param FS_Site $install
|
16051 |
+
* @param bool $flush
|
16052 |
*
|
16053 |
* @return bool Since 2.3.1 returns if a switch was made.
|
16054 |
*/
|
16055 |
+
function switch_to_blog( $blog_id, FS_Site $install = null, $flush = false ) {
|
16056 |
+
if ( ! is_numeric( $blog_id ) ) {
|
16057 |
+
return false;
|
16058 |
+
}
|
16059 |
+
|
16060 |
+
if ( ! $flush && $blog_id == $this->_context_is_network_or_blog_id ) {
|
16061 |
return false;
|
16062 |
}
|
16063 |
|
16121 |
unset( $this->_site_api );
|
16122 |
unset( $this->_user_api );
|
16123 |
|
16124 |
+
return true;
|
16125 |
}
|
16126 |
|
16127 |
/**
|
16150 |
$site['blog_id'] );
|
16151 |
}
|
16152 |
|
16153 |
+
/**
|
16154 |
+
* @author Vova Feldman (@svovaf)
|
16155 |
+
* @since 2.5.1
|
16156 |
+
*
|
16157 |
+
* @param WP_Site[]|array[] $sites
|
16158 |
+
*
|
16159 |
+
* @return int[]
|
16160 |
+
*/
|
16161 |
+
static function get_sites_blog_ids( $sites ) {
|
16162 |
+
$blog_ids = array();
|
16163 |
+
foreach ( $sites as $site ) {
|
16164 |
+
$blog_ids[] = self::get_site_blog_id( $site );
|
16165 |
+
}
|
16166 |
+
|
16167 |
+
return $blog_ids;
|
16168 |
+
}
|
16169 |
+
|
16170 |
/**
|
16171 |
* @author Leo Fajardo (@leorw)
|
16172 |
* @since 2.0.0
|
16173 |
*
|
16174 |
* @param array|WP_Site|null $site
|
16175 |
+
* @param bool $load_registration Since 2.5.1 When set to `true` the method will attempt to return the subsite's registration date, regardless of the `$site` type and value. In most calls, the registration date will be returned anyway, even when the value is `false`. This param is purely for performance optimization.
|
16176 |
*
|
16177 |
* @return array
|
16178 |
*/
|
16179 |
+
function get_site_info( $site = null, $load_registration = false ) {
|
16180 |
$this->_logger->entrance();
|
16181 |
|
16182 |
$switched = false;
|
16183 |
|
16184 |
+
$registration_date = null;
|
16185 |
+
|
16186 |
if ( is_null( $site ) ) {
|
16187 |
+
$url = self::get_unfiltered_site_url();
|
16188 |
$name = get_bloginfo( 'name' );
|
16189 |
$blog_id = null;
|
16190 |
} else {
|
16196 |
}
|
16197 |
|
16198 |
if ( $site instanceof WP_Site ) {
|
16199 |
+
$url = $site->siteurl;
|
16200 |
+
$name = $site->blogname;
|
16201 |
+
$registration_date = $site->registered;
|
16202 |
} else {
|
16203 |
+
$url = self::get_unfiltered_site_url( $blog_id );
|
16204 |
$name = get_bloginfo( 'name' );
|
16205 |
}
|
16206 |
}
|
16207 |
|
16208 |
+
if ( empty( $registration_date ) && $load_registration ) {
|
16209 |
+
$blog_details = get_blog_details( $blog_id, false );
|
16210 |
+
|
16211 |
+
if ( is_object( $blog_details ) && isset( $blog_details->registered ) ) {
|
16212 |
+
$registration_date = $blog_details->registered;
|
16213 |
+
}
|
16214 |
+
}
|
16215 |
+
|
16216 |
$info = array(
|
16217 |
+
'uid' => $this->get_anonymous_id( $blog_id ),
|
16218 |
+
'url' => $url,
|
|
|
|
|
|
|
16219 |
);
|
16220 |
|
16221 |
+
// Add these diagnostic information only if user allowed to track.
|
16222 |
+
if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) {
|
16223 |
+
$info = array_merge( $info, array(
|
16224 |
+
'title' => $name,
|
16225 |
+
'language' => self::get_sanitized_language(),
|
16226 |
+
) );
|
16227 |
+
}
|
16228 |
+
|
16229 |
if ( is_numeric( $blog_id ) ) {
|
16230 |
$info['blog_id'] = $blog_id;
|
16231 |
}
|
16232 |
|
16233 |
+
if ( ! empty( $registration_date ) ) {
|
16234 |
+
$info[ 'registration_date' ] = $registration_date;
|
16235 |
+
}
|
16236 |
+
|
16237 |
if ( $switched ) {
|
16238 |
restore_current_blog();
|
16239 |
}
|
16456 |
}
|
16457 |
}
|
16458 |
|
16459 |
+
if ( ! $this->is_registered() ) {
|
16460 |
+
return;
|
16461 |
+
}
|
16462 |
+
|
16463 |
if ( $this->is_sync_cron_scheduled() &&
|
16464 |
$context_blog_id == $this->get_sync_cron_blog_id()
|
16465 |
) {
|
16493 |
|
16494 |
$this->update_multisite_data_after_site_deactivation( $context_blog_id );
|
16495 |
|
16496 |
+
if ( ! $this->is_registered() ) {
|
16497 |
+
return;
|
16498 |
+
}
|
16499 |
+
|
16500 |
$current_blog_id = get_current_blog_id();
|
16501 |
|
16502 |
$this->switch_to_blog( $context_blog_id );
|
16530 |
|
16531 |
$this->update_multisite_data_after_site_deactivation( $context_blog_id );
|
16532 |
|
16533 |
+
if ( ! $this->is_registered() ) {
|
16534 |
+
return;
|
16535 |
+
}
|
16536 |
+
|
16537 |
$current_blog_id = get_current_blog_id();
|
16538 |
|
16539 |
$this->switch_to_blog( $context_blog_id );
|
16551 |
$this->switch_to_blog( $current_blog_id );
|
16552 |
}
|
16553 |
|
16554 |
+
/**
|
16555 |
+
* Executed after site deletion, called from wp_delete_site
|
16556 |
+
*
|
16557 |
+
* @author Dario Curvino (@dudo)
|
16558 |
+
* @since 2.5.0
|
16559 |
+
*
|
16560 |
+
* @param WP_Site $old_site
|
16561 |
+
*/
|
16562 |
+
public function _after_wpsite_deleted_callback( WP_Site $old_site ) {
|
16563 |
+
$this->_logger->entrance();
|
16564 |
+
|
16565 |
+
$this->_after_site_deleted_callback( $old_site->blog_id, true );
|
16566 |
+
}
|
16567 |
+
|
16568 |
/**
|
16569 |
* Executed after site re-activation.
|
16570 |
*
|
16679 |
* @return bool
|
16680 |
*/
|
16681 |
function is_product_settings_page() {
|
16682 |
+
$page = fs_request_get( 'page', '', 'get' );
|
16683 |
+
$menu_slug = $this->_menu->get_slug();
|
16684 |
+
|
16685 |
+
if ( $page === $menu_slug ) {
|
16686 |
+
return true;
|
16687 |
+
}
|
16688 |
+
|
16689 |
return fs_starts_with(
|
16690 |
+
// e.g., {$menu_slug}-account, {$menu_slug}-affiliation, etc.
|
16691 |
+
$page,
|
16692 |
+
( $menu_slug . '-' )
|
16693 |
);
|
16694 |
}
|
16695 |
|
16769 |
*
|
16770 |
* @param bool|string $topic
|
16771 |
* @param bool|string $message
|
16772 |
+
* @param bool|string $summary Since 2.5.1.
|
16773 |
*
|
16774 |
* @return string
|
16775 |
*/
|
16776 |
+
function contact_url( $topic = false, $message = false, $summary = false ) {
|
16777 |
$params = array();
|
16778 |
if ( is_string( $topic ) ) {
|
16779 |
$params['topic'] = $topic;
|
16782 |
$params['message'] = $message;
|
16783 |
}
|
16784 |
|
16785 |
+
if ( is_string( $summary ) ) {
|
16786 |
+
$params['summary'] = $summary;
|
16787 |
+
}
|
16788 |
+
|
16789 |
if ( $this->is_addon() ) {
|
16790 |
$params['addon_id'] = $this->get_id();
|
16791 |
|
16824 |
}
|
16825 |
|
16826 |
/* Logger
|
16827 |
+
------------------------------------------------------------------------------------------------------------------*/
|
16828 |
/**
|
16829 |
* @param string $id
|
16830 |
* @param bool $prefix_slug
|
16849 |
}
|
16850 |
|
16851 |
/* Security
|
16852 |
+
------------------------------------------------------------------------------------------------------------------*/
|
16853 |
private static function _encrypt( $str ) {
|
16854 |
if ( is_null( $str ) ) {
|
16855 |
return null;
|
17069 |
) {
|
17070 |
// Load site.
|
17071 |
$this->_site = $site;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17072 |
}
|
17073 |
|
17074 |
$user = null;
|
17097 |
/**
|
17098 |
* This is a special fault tolerance mechanism to handle a scenario that the user data is missing.
|
17099 |
*/
|
17100 |
+
if (
|
17101 |
+
! isset( $this->_storage->user_recovery_from_install_last_attempt_timestamp ) ||
|
17102 |
+
time() > ( $this->_storage->user_recovery_from_install_last_attempt_timestamp + FS_Clone_Manager::CLONE_RESOLUTION_MAX_EXECUTION_TIME )
|
17103 |
+
) {
|
17104 |
+
$user = $this->sync_user_by_current_install();
|
17105 |
+
} else {
|
17106 |
+
return;
|
17107 |
+
}
|
17108 |
+
|
17109 |
+
if ( is_object( $user ) ) {
|
17110 |
+
$this->_storage->user_was_recovered_from_install = true;
|
17111 |
+
} else {
|
17112 |
+
$this->_storage->user_recovery_from_install_attempts = isset( $this->_storage->user_recovery_from_install_attempts ) ?
|
17113 |
+
( $this->_storage->user_recovery_from_install_attempts + 1 ) :
|
17114 |
+
1;
|
17115 |
+
|
17116 |
+
if ( $this->_storage->user_recovery_from_install_attempts >= 3 ) {
|
17117 |
+
$this->delete_current_install( false );
|
17118 |
+
} else {
|
17119 |
+
$this->_storage->user_recovery_from_install_last_attempt_timestamp = time();
|
17120 |
+
|
17121 |
+
return;
|
17122 |
+
}
|
17123 |
+
}
|
17124 |
}
|
17125 |
|
17126 |
$this->_user = ( $user instanceof FS_User ) ?
|
17134 |
}
|
17135 |
|
17136 |
if ( is_object( $this->_site ) ) {
|
17137 |
+
// Load plans.
|
17138 |
+
$this->_plans = isset( $plans[ $this->_slug ] ) ?
|
17139 |
+
$plans[ $this->_slug ] :
|
17140 |
+
array();
|
17141 |
+
|
17142 |
+
if ( ! is_array( $this->_plans ) || empty( $this->_plans ) ) {
|
17143 |
+
$this->_sync_plans();
|
17144 |
+
} else {
|
17145 |
+
for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) {
|
17146 |
+
if ( $this->_plans[ $i ] instanceof FS_Plugin_Plan ) {
|
17147 |
+
$this->_plans[ $i ] = self::decrypt_entity( $this->_plans[ $i ] );
|
17148 |
+
} else {
|
17149 |
+
unset( $this->_plans[ $i ] );
|
17150 |
+
}
|
17151 |
+
}
|
17152 |
+
}
|
17153 |
+
|
17154 |
$this->_license = $this->_get_license_by_id( $this->_site->license_id );
|
17155 |
|
17156 |
if ( $this->_site->version != $this->get_plugin_version() ) {
|
17169 |
if ( $this->is_theme() ) {
|
17170 |
$this->_register_account_hooks();
|
17171 |
}
|
17172 |
+
|
17173 |
+
if ( $this->is_user_in_admin() && $this->is_clone() ) {
|
17174 |
+
if ( empty( FS_Clone_Manager::instance()->get_clone_identification_timestamp() ) ) {
|
17175 |
+
FS_Clone_Manager::instance()->store_clone_identification_timestamp();
|
17176 |
+
}
|
17177 |
+
|
17178 |
+
FS_Clone_Manager::instance()->maybe_update_clone_resolution_support_flag( $this->_storage->sdk_last_version );
|
17179 |
+
$this->send_pending_clone_update_once();
|
17180 |
+
}
|
17181 |
}
|
17182 |
|
17183 |
/**
|
17257 |
*/
|
17258 |
private function get_versions() {
|
17259 |
$versions = array();
|
17260 |
+
$versions['sdk_version'] = $this->version;
|
17261 |
+
|
17262 |
+
// Collect these diagnostic information only if it's allowed.
|
17263 |
+
if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) {
|
17264 |
+
$versions['platform_version'] = get_bloginfo( 'version' );
|
17265 |
+
$versions['programming_language_version'] = phpversion();
|
17266 |
+
}
|
17267 |
+
|
17268 |
+
foreach ( $versions as $k => $version ) {
|
17269 |
+
$versions[ $k ] = self::get_api_sanitized_property( $k, $version );
|
17270 |
+
}
|
17271 |
+
|
17272 |
+
return $versions;
|
17273 |
+
}
|
17274 |
+
|
17275 |
+
/**
|
17276 |
+
* Get sanitized site language.
|
17277 |
+
*
|
17278 |
+
* @param string $language
|
17279 |
+
* @param int $max_len
|
17280 |
+
*
|
17281 |
+
* @since 2.5.1
|
17282 |
+
* @author Vova Feldman (@svovaf)
|
17283 |
+
*
|
17284 |
+
* @return string
|
17285 |
+
*/
|
17286 |
+
private static function get_sanitized_language( $language = '', $max_len = self::LANGUAGE_MAX_CHARS ) {
|
17287 |
+
if ( empty( $language ) ) {
|
17288 |
+
$language = get_bloginfo( 'language' );
|
17289 |
+
}
|
17290 |
+
|
17291 |
+
return substr( $language, 0, $max_len );
|
17292 |
+
}
|
17293 |
+
|
17294 |
+
/**
|
17295 |
+
* Get core version stripped from pre-release and build.
|
17296 |
+
*
|
17297 |
+
* @since 2.5.1
|
17298 |
+
* @author Vova Feldman (@svovaf)
|
17299 |
+
*
|
17300 |
+
* @param string $version
|
17301 |
+
* @param int $parts
|
17302 |
+
* @param int $max_len
|
17303 |
+
* @param bool $include_pre_release
|
17304 |
+
*
|
17305 |
+
* @return string
|
17306 |
+
*/
|
17307 |
+
private static function get_core_version(
|
17308 |
+
$version,
|
17309 |
+
$parts = 3,
|
17310 |
+
$max_len = self::VERSION_MAX_CHARS,
|
17311 |
+
$include_pre_release = false
|
17312 |
+
) {
|
17313 |
+
if ( empty( $version ) ) {
|
17314 |
+
// Version is empty.
|
17315 |
+
return '';
|
17316 |
+
}
|
17317 |
+
|
17318 |
+
if ( is_numeric( $version ) ) {
|
17319 |
+
$is_float_version = is_float( $version );
|
17320 |
+
|
17321 |
+
$version = (string) $version;
|
17322 |
+
|
17323 |
+
/**
|
17324 |
+
* Casting a whole float number to a string cuts the decimal point. This part make sure to add the missing decimal part to the version.
|
17325 |
+
*/
|
17326 |
+
if ( $is_float_version && false === strpos( $version, '.' ) ) {
|
17327 |
+
$version .= '.0';
|
17328 |
+
}
|
17329 |
+
}
|
17330 |
+
|
17331 |
+
if ( ! is_string( $version ) ) {
|
17332 |
+
return '';
|
17333 |
+
}
|
17334 |
+
|
17335 |
+
if ( $parts < 1 ) {
|
17336 |
+
return '';
|
17337 |
+
}
|
17338 |
|
17339 |
+
$pre_release_regex = $include_pre_release ?
|
17340 |
+
'(\-(alpha|beta|RC)([0-9]+)?)?' :
|
17341 |
+
'';
|
17342 |
+
|
17343 |
+
if ( 0 === preg_match( '/^([0-9]+(\.[0-9]+){0,' . ( $parts - 1 ) . '}' . $pre_release_regex . ')/i', $version, $matches ) ) {
|
17344 |
+
// Version is not starting with a digit.
|
17345 |
+
return '';
|
17346 |
}
|
17347 |
|
17348 |
+
return substr( $matches[1], 0, $max_len );
|
17349 |
+
}
|
17350 |
+
|
17351 |
+
/**
|
17352 |
+
* @param string $prop
|
17353 |
+
* @param mixed $val
|
17354 |
+
*
|
17355 |
+
* @return mixed
|
17356 |
+
*@author Vova Feldman (@svovaf)
|
17357 |
+
*
|
17358 |
+
* @since 2.5.1
|
17359 |
+
*/
|
17360 |
+
private static function get_api_sanitized_property( $prop, $val ) {
|
17361 |
+
if ( ! is_string( $val ) || empty( $val ) ) {
|
17362 |
+
return $val;
|
17363 |
+
}
|
17364 |
+
|
17365 |
+
switch ( $prop ) {
|
17366 |
+
case 'programming_language_version':
|
17367 |
+
// Get core PHP version, which can have up to 3 parts (ignore pre-releases).
|
17368 |
+
return self::get_core_version( $val );
|
17369 |
+
case 'platform_version':
|
17370 |
+
// Get the exact WordPress version, which can have up to 3 parts (including pre-releases).
|
17371 |
+
return self::get_core_version( $val, 3, self::VERSION_MAX_CHARS, true );
|
17372 |
+
case 'sdk_version':
|
17373 |
+
// Get the exact SDK version, which can have up to 4 parts.
|
17374 |
+
return self::get_core_version( $val, 4 );
|
17375 |
+
case 'version':
|
17376 |
+
// Get the entire version but just limited in length.
|
17377 |
+
return substr( $val, 0, self::VERSION_MAX_CHARS );
|
17378 |
+
case 'language':
|
17379 |
+
return self::get_sanitized_language( $val );
|
17380 |
+
default:
|
17381 |
+
return $val;
|
17382 |
+
}
|
17383 |
}
|
17384 |
|
17385 |
/**
|
17434 |
$versions = $this->get_versions();
|
17435 |
|
17436 |
$params = array_merge( $versions, array(
|
17437 |
+
'user_firstname' => $current_user->user_firstname,
|
17438 |
+
'user_lastname' => $current_user->user_lastname,
|
17439 |
+
'user_email' => $current_user->user_email,
|
17440 |
+
'plugin_slug' => $this->_slug,
|
17441 |
+
'plugin_id' => $this->get_id(),
|
17442 |
+
'plugin_public_key' => $this->get_public_key(),
|
17443 |
+
'plugin_version' => $this->get_plugin_version(),
|
17444 |
+
'return_url' => fs_nonce_url( $return_url, $activation_action ),
|
17445 |
+
'account_url' => fs_nonce_url( $this->_get_admin_page_url(
|
|
|
|
|
17446 |
'account',
|
17447 |
array( 'fs_action' => 'sync_user' )
|
17448 |
), 'sync_user' ),
|
17449 |
+
'is_premium' => $this->is_premium(),
|
17450 |
+
'is_active' => true,
|
17451 |
+
'is_uninstalled' => false,
|
17452 |
+
'is_localhost' => WP_FS__IS_LOCALHOST,
|
17453 |
) );
|
17454 |
|
17455 |
if ( $this->is_addon() ) {
|
17470 |
|
17471 |
$site = $this->get_site_info( $site );
|
17472 |
|
17473 |
+
$diagnostic_info = array();
|
17474 |
+
if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) {
|
17475 |
+
$diagnostic_info = array(
|
17476 |
+
'site_name' => $site['title'],
|
17477 |
+
'language' => self::get_sanitized_language( $site['language'] ),
|
17478 |
+
);
|
17479 |
+
}
|
17480 |
+
|
17481 |
+
$params = array_merge( $params, $diagnostic_info, array(
|
17482 |
'site_uid' => $site['uid'],
|
17483 |
'site_url' => $site['url'],
|
|
|
|
|
|
|
17484 |
) );
|
17485 |
}
|
17486 |
|
17505 |
);
|
17506 |
}
|
17507 |
|
17508 |
+
if ( is_multisite() && function_exists( 'get_network' ) ) {
|
17509 |
+
$params['network_uid'] = $this->get_anonymous_network_id();
|
17510 |
+
}
|
17511 |
+
|
17512 |
return array_merge( $params, $override_with );
|
17513 |
}
|
17514 |
|
17527 |
* In this case, the user and site info will be sent to the server but no
|
17528 |
* data will be saved to the WP installation's database.
|
17529 |
* @param number|bool $trial_plan_id
|
17530 |
+
* @param bool $is_disconnected Whether to opt in without tracking.
|
17531 |
* @param null|bool $is_marketing_allowed
|
17532 |
* @param array $sites If network-level opt-in, an array of containing details of sites.
|
17533 |
+
* @param bool $redirect
|
17534 |
*
|
17535 |
* @return string|object
|
17536 |
* @use WP_Error
|
17544 |
$trial_plan_id = false,
|
17545 |
$is_disconnected = false,
|
17546 |
$is_marketing_allowed = null,
|
17547 |
+
$sites = array(),
|
17548 |
+
$redirect = true
|
17549 |
) {
|
17550 |
$this->_logger->entrance();
|
17551 |
|
17569 |
$fs_user,
|
17570 |
false,
|
17571 |
$trial_plan_id,
|
17572 |
+
$redirect,
|
17573 |
true,
|
17574 |
$sites
|
17575 |
);
|
17637 |
$params['is_marketing_allowed'] = $is_marketing_allowed;
|
17638 |
}
|
17639 |
|
17640 |
+
$params['is_disconnected'] = $is_disconnected;
|
17641 |
+
$params['format'] = 'json';
|
17642 |
+
$params['is_extensions_tracking_allowed'] = FS_Permission_Manager::instance( $this )->is_extensions_tracking_allowed();
|
17643 |
+
$params['is_diagnostic_tracking_allowed'] = FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed();
|
17644 |
|
17645 |
$request = array(
|
17646 |
'method' => 'POST',
|
17647 |
'body' => $params,
|
17648 |
+
'timeout' => 60,
|
17649 |
);
|
17650 |
|
17651 |
$url = $this->add_show_pending( WP_FS__ADDRESS . '/action/service/user/install/' );
|
17731 |
true ),
|
17732 |
false,
|
17733 |
$filtered_license_key,
|
17734 |
+
! empty( $params['trial_plan_id'] ),
|
17735 |
+
isset( $decoded->is_suspicious_email ) && $decoded->is_suspicious_email
|
17736 |
);
|
17737 |
} else if ( isset( $decoded->install_secret_key ) ) {
|
17738 |
return $this->install_with_new_user(
|
17745 |
( isset( $decoded->is_extensions_tracking_allowed ) && ! is_null( $decoded->is_extensions_tracking_allowed ) ?
|
17746 |
$decoded->is_extensions_tracking_allowed :
|
17747 |
null ),
|
17748 |
+
( isset( $decoded->is_diagnostic_tracking_allowed ) && ! is_null( $decoded->is_diagnostic_tracking_allowed ) ?
|
17749 |
+
$decoded->is_diagnostic_tracking_allowed :
|
17750 |
+
null ),
|
17751 |
$decoded->install_id,
|
17752 |
$decoded->install_public_key,
|
17753 |
$decoded->install_secret_key,
|
17764 |
( isset( $decoded->is_extensions_tracking_allowed ) && ! is_null( $decoded->is_extensions_tracking_allowed ) ?
|
17765 |
$decoded->is_extensions_tracking_allowed :
|
17766 |
null ),
|
17767 |
+
( isset( $decoded->is_diagnostic_tracking_allowed ) && ! is_null( $decoded->is_diagnostic_tracking_allowed ) ?
|
17768 |
+
$decoded->is_diagnostic_tracking_allowed :
|
17769 |
+
null ),
|
17770 |
$decoded->installs,
|
17771 |
false
|
17772 |
);
|
17864 |
$this->_admin_notices->remove_sticky( 'connect_account' );
|
17865 |
|
17866 |
if ( $this->is_pending_activation() || ! $this->has_settings_menu() ) {
|
17867 |
+
$this->clear_pending_activation_mode();
|
|
|
|
|
|
|
|
|
17868 |
|
17869 |
if ( ! $this->is_paying_or_trial() ) {
|
17870 |
$this->_admin_notices->add_sticky(
|
17871 |
+
sprintf( $this->get_text_inline( '%s opt-in was successfully completed.', 'plugin-x-activation-message' ), '<b>' . $this->get_plugin_name() . '</b>' ),
|
17872 |
'activation_complete'
|
17873 |
);
|
17874 |
}
|
17990 |
fs_request_get( 'user_secret_key' ),
|
17991 |
fs_request_get_bool( 'is_marketing_allowed', null ),
|
17992 |
fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
|
17993 |
+
fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ),
|
17994 |
$pending_sites_info['blog_ids'],
|
17995 |
$pending_sites_info['license_key'],
|
17996 |
$pending_sites_info['trial_plan_id']
|
18002 |
fs_request_get( 'user_secret_key' ),
|
18003 |
fs_request_get_bool( 'is_marketing_allowed', null ),
|
18004 |
fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
|
18005 |
+
fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ),
|
18006 |
fs_request_get( 'install_id' ),
|
18007 |
fs_request_get( 'install_public_key' ),
|
18008 |
fs_request_get( 'install_secret_key' ),
|
18011 |
);
|
18012 |
}
|
18013 |
} else if ( fs_request_has( 'pending_activation' ) ) {
|
18014 |
+
$this->set_pending_confirmation(
|
18015 |
+
fs_request_get( 'user_email' ),
|
18016 |
+
true,
|
18017 |
+
false,
|
18018 |
+
false,
|
18019 |
+
fs_request_get_bool( 'is_suspicious_email' )
|
18020 |
+
);
|
18021 |
}
|
18022 |
}
|
18023 |
}
|
18065 |
* @param string $user_secret_key
|
18066 |
* @param bool|null $is_marketing_allowed
|
18067 |
* @param bool|null $is_extensions_tracking_allowed Since 2.3.2
|
18068 |
+
* @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2
|
18069 |
* @param number $install_id
|
18070 |
* @param string $install_public_key
|
18071 |
* @param string $install_secret_key
|
18080 |
$user_secret_key,
|
18081 |
$is_marketing_allowed,
|
18082 |
$is_extensions_tracking_allowed,
|
18083 |
+
$is_diagnostic_tracking_allowed,
|
18084 |
$install_id,
|
18085 |
$install_public_key,
|
18086 |
$install_secret_key,
|
18114 |
$site->secret_key = $install_secret_key;
|
18115 |
|
18116 |
$this->_site = $site;
|
18117 |
+
$site_result = $this->get_api_site_scope( true )->get();
|
18118 |
$site = new FS_Site( $site_result );
|
18119 |
$this->_site = $site;
|
18120 |
|
18122 |
$this->disable_opt_in_notice_and_lock_user();
|
18123 |
}
|
18124 |
|
18125 |
+
FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array(
|
18126 |
+
FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed,
|
18127 |
+
FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed,
|
18128 |
+
) );
|
18129 |
|
18130 |
return $this->setup_account(
|
18131 |
$this->_user,
|
18146 |
* @param string $user_secret_key
|
18147 |
* @param bool|null $is_marketing_allowed
|
18148 |
* @param bool|null $is_extensions_tracking_allowed Since 2.3.2
|
18149 |
+
* @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2
|
18150 |
* @param array $site_ids
|
18151 |
* @param bool $license_key
|
18152 |
* @param bool $trial_plan_id
|
18160 |
$user_secret_key,
|
18161 |
$is_marketing_allowed,
|
18162 |
$is_extensions_tracking_allowed,
|
18163 |
+
$is_diagnostic_tracking_allowed,
|
18164 |
$site_ids,
|
18165 |
$license_key = false,
|
18166 |
$trial_plan_id = false,
|
18172 |
$this->disable_opt_in_notice_and_lock_user();
|
18173 |
}
|
18174 |
|
18175 |
+
FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array(
|
18176 |
+
FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed,
|
18177 |
+
FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed,
|
18178 |
+
) );
|
18179 |
|
18180 |
$sites = array();
|
18181 |
foreach ( $site_ids as $site_id ) {
|
18196 |
* @param string $user_secret_key
|
18197 |
* @param bool|null $is_marketing_allowed
|
18198 |
* @param bool|null $is_extensions_tracking_allowed Since 2.3.2
|
18199 |
+
* @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2
|
18200 |
* @param object[] $installs
|
18201 |
* @param bool $redirect
|
18202 |
* @param bool $auto_install Since 1.2.1.7 If `true` and setting up an account with a valid license, will redirect (or return a URL) to the account page with a special parameter to trigger the auto installation processes.
|
18209 |
$user_secret_key,
|
18210 |
$is_marketing_allowed,
|
18211 |
$is_extensions_tracking_allowed,
|
18212 |
+
$is_diagnostic_tracking_allowed,
|
18213 |
array $installs,
|
18214 |
$redirect = true,
|
18215 |
$auto_install = false
|
18220 |
$this->disable_opt_in_notice_and_lock_user();
|
18221 |
}
|
18222 |
|
18223 |
+
FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array(
|
18224 |
+
FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed,
|
18225 |
+
FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed,
|
18226 |
+
) );
|
18227 |
|
18228 |
$install_ids = array();
|
18229 |
|
18231 |
$install_ids[] = $install->id;
|
18232 |
}
|
18233 |
|
18234 |
+
$items_per_request = 25;
|
18235 |
+
$left = count( $install_ids );
|
18236 |
+
$offset = 0;
|
18237 |
|
18238 |
$installs = array();
|
18239 |
while ( $left > 0 ) {
|
18240 |
+
$result = $this->get_api_user_scope()->get( "/plugins/{$this->_module_id}/installs.json?ids=" . implode( ',', array_slice( $install_ids, $offset, $items_per_request ) ) );
|
18241 |
|
18242 |
if ( ! $this->is_api_result_object( $result, 'installs' ) ) {
|
18243 |
// @todo Handle API error.
|
18245 |
|
18246 |
$installs = array_merge( $installs, $result->installs );
|
18247 |
|
18248 |
+
$left -= $items_per_request;
|
18249 |
+
$offset += $items_per_request;
|
18250 |
}
|
18251 |
|
18252 |
foreach ( $installs as &$install ) {
|
18276 |
$email = false,
|
18277 |
$redirect = true,
|
18278 |
$license_key = false,
|
18279 |
+
$is_pending_trial = false,
|
18280 |
+
$is_suspicious_email = false
|
18281 |
) {
|
18282 |
if ( $this->_ignore_pending_mode ) {
|
18283 |
/**
|
18287 |
* @author Vova Feldman
|
18288 |
* @since 1.2.1.6
|
18289 |
*/
|
18290 |
+
$this->skip_connection( fs_is_network_admin() );
|
18291 |
} else {
|
18292 |
// Install must be activated via email since
|
18293 |
// user with the same email already exist.
|
18294 |
$this->_storage->is_pending_activation = true;
|
18295 |
+
$this->_add_pending_activation_notice( $email, $is_pending_trial, $is_suspicious_email );
|
18296 |
}
|
18297 |
|
18298 |
if ( ! empty( $license_key ) ) {
|
18307 |
|
18308 |
$next_page = $this->get_after_activation_url( 'after_pending_connect_url' );
|
18309 |
|
|
|
18310 |
if ( $redirect ) {
|
18311 |
+
// Reload the page with a pending activation message.
|
18312 |
fs_redirect( $next_page );
|
18313 |
}
|
18314 |
|
18337 |
*/
|
18338 |
$license_key = fs_request_get( 'license_secret_key' );
|
18339 |
|
18340 |
+
FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array(
|
18341 |
+
FS_Permission_Manager::PERMISSION_DIAGNOSTIC => fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ),
|
18342 |
+
FS_Permission_Manager::PERMISSION_EXTENSIONS => fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
|
18343 |
+
) );
|
18344 |
|
18345 |
$this->install_with_current_user( $license_key );
|
18346 |
}
|
18358 |
*
|
18359 |
* @return object|string If redirect is `false`, returns the next page the user should be redirected to, or the API error object if failed to install.
|
18360 |
*/
|
18361 |
+
function install_with_current_user(
|
18362 |
$license_key = false,
|
18363 |
$trial_plan_id = false,
|
18364 |
$sites = array(),
|
18741 |
$this->send_installs_update();
|
18742 |
}
|
18743 |
|
|
|
|
|
|
|
18744 |
$current_blog = get_current_blog_id();
|
18745 |
|
18746 |
foreach ( $blog_2_install_map as $blog_id => $install ) {
|
18749 |
$this->do_action( 'after_account_connection', $this->_user, $install );
|
18750 |
}
|
18751 |
|
18752 |
+
// Switch install context back to the first install.
|
18753 |
+
$this->switch_to_blog(
|
18754 |
+
$current_blog,
|
18755 |
+
$first_install,
|
18756 |
+
( $this->_site->id != $first_install->id )
|
18757 |
+
);
|
18758 |
|
18759 |
$this->do_action( 'after_network_account_connection', $this->_user, $blog_2_install_map );
|
18760 |
}
|
18802 |
$parent_fs->_admin_notices->remove_sticky( 'connect_account' );
|
18803 |
|
18804 |
if ( $parent_fs->is_pending_activation() ) {
|
18805 |
+
$parent_fs->clear_pending_activation_mode();
|
|
|
|
|
18806 |
}
|
18807 |
|
18808 |
// Get user information based on parent's plugin.
|
18856 |
// return;
|
18857 |
// }
|
18858 |
|
18859 |
+
if ( is_object( $this->_site ) && ! $this->is_registered() ) {
|
18860 |
+
return;
|
18861 |
+
}
|
18862 |
+
|
18863 |
/**
|
18864 |
* When running from a site admin with a network activated module and the connection
|
18865 |
* was NOT delegated and the user still haven't skipped or opted-in, then hide the
|
19814 |
*
|
19815 |
* @return string
|
19816 |
*/
|
19817 |
+
static function get_ajax_action_static( $tag, $module_id = null ) {
|
19818 |
$action = "fs_{$tag}";
|
19819 |
|
19820 |
if ( ! empty( $module_id ) ) {
|
19837 |
* @uses do_action()
|
19838 |
*/
|
19839 |
function do_action( $tag, $arg = '' ) {
|
|
|
|
|
19840 |
$args = func_get_args();
|
19841 |
|
19842 |
+
$this->_logger->entrance( $tag );
|
19843 |
+
|
19844 |
call_user_func_array( 'do_action', array_merge(
|
19845 |
array( $this->get_action_tag( $tag ) ),
|
19846 |
array_slice( $args, 1 ) )
|
19980 |
wp_send_json( $result );
|
19981 |
}
|
19982 |
|
19983 |
+
/**
|
19984 |
+
* Returns an AJAX URL with a special extra param to indicate whether the request was triggered from the network admin or blog admin.
|
19985 |
+
*
|
19986 |
+
* @author Vova Feldman (@svovaf)
|
19987 |
+
* @since 2.5.1
|
19988 |
+
*
|
19989 |
+
* @param string $wrap_with By default, returns the AJAX URL wrapped with single quotes.
|
19990 |
+
*
|
19991 |
+
* @return string
|
19992 |
+
*/
|
19993 |
+
static function ajax_url( $wrap_with = "'") {
|
19994 |
+
if ( fs_is_network_admin() ) {
|
19995 |
+
$param_name = '_fs_network_admin';
|
19996 |
+
} else {
|
19997 |
+
$param_name = '_fs_blog_admin';
|
19998 |
+
}
|
19999 |
+
|
20000 |
+
$url = admin_url( 'admin-ajax.php', 'relative' );
|
20001 |
+
$url .= ( false === strpos( $url, '?' ) ) ? '?' : '&';
|
20002 |
+
$url .= "{$param_name}=true";
|
20003 |
+
|
20004 |
+
return "{$wrap_with}{$url}{$wrap_with}";
|
20005 |
+
}
|
20006 |
+
|
20007 |
/**
|
20008 |
* Apply filter, specific for the current context plugin.
|
20009 |
*
|
20018 |
* @uses apply_filters()
|
20019 |
*/
|
20020 |
function apply_filters( $tag, $value ) {
|
20021 |
+
$args = func_get_args();
|
20022 |
+
|
20023 |
$this->_logger->entrance( $tag );
|
20024 |
|
|
|
20025 |
array_unshift( $args, $this->get_unique_affix() );
|
20026 |
|
20027 |
return call_user_func_array( 'fs_apply_filter', $args );
|
20082 |
}
|
20083 |
|
20084 |
/* Account Page
|
20085 |
+
------------------------------------------------------------------------------------------------------------------*/
|
20086 |
/**
|
20087 |
* Update site information.
|
20088 |
*
|
20093 |
* @param null|int $network_level_or_blog_id Since 2.0.0
|
20094 |
* @param \FS_Site $site Since 2.0.0
|
20095 |
*/
|
20096 |
+
private function _store_site( $store = true, $network_level_or_blog_id = null, FS_Site $site = null, $is_backup = false ) {
|
20097 |
$this->_logger->entrance();
|
20098 |
|
20099 |
if ( is_null( $site ) ) {
|
20108 |
|
20109 |
$site_clone = clone $site;
|
20110 |
|
20111 |
+
$sites = self::get_all_sites( $this->_module_type, $network_level_or_blog_id, $is_backup );
|
20112 |
|
20113 |
+
if (
|
20114 |
+
! $is_backup &&
|
20115 |
+
is_object( $this->_user ) && $this->_user->id != $site->user_id
|
20116 |
+
) {
|
20117 |
$this->sync_user_by_current_install( $site->user_id );
|
20118 |
|
20119 |
$prev_stored_user_id = $this->_storage->get( 'prev_user_id', false, $network_level_or_blog_id );
|
20138 |
|
20139 |
$sites[ $this->_slug ] = $site_clone;
|
20140 |
|
20141 |
+
$this->set_account_option(
|
20142 |
+
( $is_backup ? 'prev_' : '' ) . 'sites',
|
20143 |
+
$sites,
|
20144 |
+
$store,
|
20145 |
+
$network_level_or_blog_id
|
20146 |
+
);
|
20147 |
+
}
|
20148 |
+
|
20149 |
+
/**
|
20150 |
+
* Stores the context site in the sites backup storage. This logic is used before deleting the site info so that it can be restored later on if necessary (e.g., if the automatic clone resolution attempt fails).
|
20151 |
+
*
|
20152 |
+
* @author Leo Fajardo (@leorw)
|
20153 |
+
* @since 2.5.0
|
20154 |
+
*/
|
20155 |
+
private function back_up_site() {
|
20156 |
+
$this->_logger->entrance();
|
20157 |
+
|
20158 |
+
$site_clone = clone $this->_site;
|
20159 |
+
|
20160 |
+
$this->_store_site( true, null, $site_clone, true );
|
20161 |
}
|
20162 |
|
20163 |
/**
|
21398 |
$this->switch_to_blog( $current_blog_id );
|
21399 |
}
|
21400 |
|
21401 |
+
$result = $this->send_install_update( array(), true, true );
|
21402 |
$is_valid = $this->is_api_result_entity( $result );
|
21403 |
} else {
|
21404 |
+
$result = $this->send_installs_update( array(), true, true );
|
21405 |
$is_valid = $this->is_api_result_object( $result, 'installs' );
|
21406 |
}
|
21407 |
|
21411 |
$this->switch_to_blog( $this->_storage->network_install_blog_id );
|
21412 |
}
|
21413 |
|
21414 |
+
// Show API message only if not background sync or if paying customer.
|
21415 |
if ( ! $background || $this->is_paying() ) {
|
21416 |
// Try to ping API to see if not blocked.
|
21417 |
if ( ! FS_Api::test() ) {
|
21421 |
* @author Vova Feldman (@svovaf)
|
21422 |
* @since 1.1.6 Only show message related to one of the Freemius powered plugins. Once it will be resolved it will fix the issue for all plugins anyways. There's no point to scare users with multiple error messages.
|
21423 |
*/
|
|
|
21424 |
|
21425 |
if ( ! self::$_global_admin_notices->has_sticky( 'api_blocked' ) ) {
|
21426 |
+
// Add notice immediately if not a background sync.
|
21427 |
+
$add_notice = ( ! $background );
|
21428 |
+
|
21429 |
+
if ( ! $add_notice ) {
|
21430 |
+
$counter = (int) get_transient( '_fs_api_connection_retry_counter' );
|
21431 |
+
|
21432 |
+
// We only want to add the notice after 3 consecutive failures.
|
21433 |
+
$add_notice = ( 3 <= $counter );
|
21434 |
+
|
21435 |
+
if ( ! $add_notice ) {
|
21436 |
+
/**
|
21437 |
+
* Update counter transient only if notice shouldn't be added. If it is added the transient will be reset anyway, because the retries mechanism should only start counting if the admin isn't aware of the connectivity issue.
|
21438 |
+
*
|
21439 |
+
* Also, since the background sync happens once a day, setting the transient expiration for a week should be enough to count 3 failures, if there's an actual connectivity issue.
|
21440 |
+
*/
|
21441 |
+
set_transient( '_fs_api_connection_retry_counter', $counter + 1, WP_FS__TIME_WEEK_IN_SEC );
|
21442 |
+
}
|
21443 |
+
}
|
21444 |
+
|
21445 |
+
// Add notice instantly for not-background sync and only after 3 failed attempts for background sync.
|
21446 |
+
if ( $add_notice ) {
|
21447 |
+
self::$_global_admin_notices->add(
|
21448 |
+
sprintf(
|
21449 |
+
$this->get_text_inline( 'Your server is blocking the access to Freemius\' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$s', 'server-blocking-access' ),
|
21450 |
+
$this->get_plugin_name(),
|
21451 |
+
'<b>' . implode( ', ', $this->apply_filters( 'api_domains', array(
|
21452 |
+
'api.freemius.com',
|
21453 |
+
'wp.freemius.com'
|
21454 |
+
) ) ) . '</b>'
|
21455 |
+
) . '<br> ' . $this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . var_export( $result->error, true ),
|
21456 |
+
$this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...',
|
21457 |
+
'error',
|
21458 |
+
$background,
|
21459 |
+
'api_blocked'
|
21460 |
+
);
|
21461 |
+
|
21462 |
+
// Notice was just shown, reset connectivity counter.
|
21463 |
+
delete_transient( '_fs_api_connection_retry_counter' );
|
21464 |
+
}
|
21465 |
}
|
21466 |
+
} else if ( is_object( $result ) ) {
|
21467 |
// Authentication params are broken.
|
21468 |
$this->_admin_notices->add(
|
21469 |
$this->get_text_inline( 'It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.', 'wrong-authentication-param-message' ) . '<br> ' . $this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . var_export( $result->error, true ),
|
21477 |
return;
|
21478 |
}
|
21479 |
|
21480 |
+
// API is working now. Delete the transient and start afresh.
|
21481 |
+
delete_transient('_fs_api_connection_retry_counter');
|
21482 |
+
|
21483 |
if ( $is_site_level_sync ) {
|
21484 |
$site = new FS_Site( $result );
|
21485 |
} else {
|
21671 |
}
|
21672 |
|
21673 |
if ( ! $this->is_addon() &&
|
21674 |
+
$this->_site->is_beta() !== $site->is_beta()
|
21675 |
) {
|
21676 |
// Beta flag updated.
|
21677 |
$this->_site = $site;
|
22226 |
if ( ! $this->is_api_result_entity( $plan ) ) {
|
22227 |
// Some API error while trying to start the trial.
|
22228 |
$this->_admin_notices->add(
|
22229 |
+
$this->get_api_error_message( $plan ),
|
|
|
22230 |
$oops_text,
|
22231 |
'error'
|
22232 |
);
|
22404 |
) {
|
22405 |
$this->_logger->entrance();
|
22406 |
|
22407 |
+
if ( $this->is_unresolved_clone( true ) ) {
|
22408 |
+
return false;
|
22409 |
+
}
|
22410 |
+
|
22411 |
$switch_to_blog_id = null;
|
22412 |
|
22413 |
/**
|
22414 |
* @since 1.1.7.3 Check for plugin updates from Freemius only if opted-in.
|
22415 |
* @since 1.1.7.4 Also check updates for add-ons.
|
22416 |
*/
|
22417 |
+
if (
|
22418 |
+
( ! $this->is_registered() || ! FS_Permission_Manager::instance( $this )->is_essentials_tracking_allowed() ) &&
|
22419 |
! $this->_is_addon_id( $addon_id )
|
22420 |
) {
|
22421 |
if ( ! is_multisite() ) {
|
22425 |
$installs_map = $this->get_blog_install_map();
|
22426 |
|
22427 |
foreach ( $installs_map as $blog_id => $install ) {
|
22428 |
+
if ( ! FS_Permission_Manager::instance( $this )->is_essentials_tracking_allowed( $blog_id ) ) {
|
22429 |
+
continue;
|
22430 |
+
}
|
22431 |
+
|
22432 |
/**
|
22433 |
* @var FS_Site $install
|
22434 |
*/
|
22525 |
private function get_latest_download_api_url( $plugin_id = false ) {
|
22526 |
$this->_logger->entrance();
|
22527 |
|
22528 |
+
$download_api_url = $this->get_api_site_scope()->get_signed_url(
|
22529 |
$this->_get_latest_version_endpoint( $plugin_id, 'zip' )
|
22530 |
);
|
22531 |
+
|
22532 |
+
return str_replace( 'http:', 'https:', $download_api_url );
|
22533 |
}
|
22534 |
|
22535 |
/**
|
22724 |
private function update_email( $new_email ) {
|
22725 |
$this->_logger->entrance();
|
22726 |
|
|
|
22727 |
$api = $this->get_api_user_scope();
|
22728 |
$user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,email,is_verified", 'put', array(
|
22729 |
'email' => $new_email,
|
22739 |
$this->_store_user();
|
22740 |
} else {
|
22741 |
// handle different error cases.
|
|
|
22742 |
}
|
22743 |
|
22744 |
return $user;
|
22814 |
* @uses FS_Api
|
22815 |
*
|
22816 |
* @param string $candidate_email
|
22817 |
+
* @param string $transfer_type
|
22818 |
*
|
22819 |
* @return bool Is ownership change successfully initiated.
|
22820 |
*/
|
22821 |
+
private function init_change_owner( $candidate_email, $transfer_type ) {
|
22822 |
$this->_logger->entrance();
|
22823 |
|
22824 |
+
$installs_info_by_slug_map = $this->get_parent_and_addons_installs_info();
|
22825 |
+
$install_ids = array();
|
22826 |
+
|
22827 |
+
foreach ( $installs_info_by_slug_map as $slug => $install_info ) {
|
22828 |
+
$install = $install_info['install'];
|
22829 |
+
|
22830 |
+
if ( $this->_user->id != $install->user_id ) {
|
22831 |
+
// Skip add-on installs that are not owned by the parent product's install's owner.
|
22832 |
+
continue;
|
22833 |
+
}
|
22834 |
+
|
22835 |
+
$install_ids[ $slug ] = $install->id;
|
22836 |
+
}
|
22837 |
+
|
22838 |
$api = $this->get_api_site_scope();
|
22839 |
$result = $api->call( "/users/{$this->_user->id}.json", 'put', array(
|
22840 |
'email' => $candidate_email,
|
22841 |
+
'transfer_type' => $transfer_type,
|
22842 |
+
'install_ids' => implode( ',', array_values( $install_ids ) ),
|
22843 |
'after_confirm_url' => $this->_get_admin_page_url(
|
22844 |
'account',
|
22845 |
array( 'fs_action' => 'change_owner' )
|
22861 |
private function complete_change_owner() {
|
22862 |
$this->_logger->entrance();
|
22863 |
|
22864 |
+
$install_ids = fs_request_get( 'install_ids' );
|
22865 |
+
|
22866 |
+
if ( ! empty( $install_ids ) ) {
|
22867 |
+
$install_ids = explode( ',', $install_ids );
|
22868 |
+
|
22869 |
+
foreach ( $install_ids as $key => $install_id ) {
|
22870 |
+
if ( ! FS_Site::is_valid_id( $install_id ) ) {
|
22871 |
+
unset( $install_ids[ $key ] );
|
22872 |
+
}
|
22873 |
+
}
|
22874 |
+
}
|
22875 |
+
|
22876 |
+
if ( ! is_array( $install_ids ) ) {
|
22877 |
+
$install_ids = array();
|
22878 |
+
}
|
22879 |
+
|
22880 |
+
$user = new FS_User();
|
22881 |
+
$user->id = fs_request_get( 'user_id' );
|
22882 |
+
$user->public_key = fs_request_get( 'user_public_key' );
|
22883 |
+
$user->secret_key = fs_request_get( 'user_secret_key' );
|
22884 |
|
22885 |
+
$prev_user = $this->_user;
|
22886 |
+
$this->_user = $user;
|
22887 |
+
|
22888 |
+
$result = $this->get_api_user_scope( true )->get(
|
22889 |
+
"/installs.json?install_ids=" . implode( ',', $install_ids )
|
22890 |
+
);
|
22891 |
+
|
22892 |
+
$current_blog_sites = self::get_all_sites( $this->get_module_type() );
|
22893 |
+
|
22894 |
+
if ( $this->is_api_result_object( $result, 'installs' ) ) {
|
22895 |
+
$site_id_slug_map = array();
|
22896 |
+
|
22897 |
+
foreach ( $current_blog_sites as $slug => $site ) {
|
22898 |
+
$site_id_slug_map[ $site->id ] = $slug;
|
22899 |
+
}
|
22900 |
+
|
22901 |
+
foreach ( $result->installs as $install ) {
|
22902 |
+
$site = new FS_Site( $install );
|
22903 |
+
|
22904 |
+
if ( ! isset( $site_id_slug_map[ $install->id ] ) ) {
|
22905 |
+
continue;
|
22906 |
+
}
|
22907 |
+
|
22908 |
+
$current_blog_sites[ $site_id_slug_map[ $install->id ] ] = clone $site;
|
22909 |
+
|
22910 |
+
if ( $this->_site->id == $site->id ) {
|
22911 |
+
$this->_site = $site;
|
22912 |
+
}
|
22913 |
+
}
|
22914 |
+
}
|
22915 |
|
22916 |
// Validate install's user and given user.
|
22917 |
if ( $user->id != $this->_site->user_id ) {
|
22918 |
+
$this->_user = $prev_user;
|
22919 |
+
|
22920 |
return false;
|
22921 |
}
|
22922 |
|
22923 |
+
$this->set_account_option( 'sites', $current_blog_sites, true );
|
|
|
22924 |
|
22925 |
// Fetch new user information.
|
|
|
22926 |
$user_result = $this->get_api_user_scope( true )->get();
|
22927 |
$user = new FS_User( $user_result );
|
22928 |
$this->_user = $user;
|
22929 |
|
22930 |
+
$this->_set_account( $user, $this->_site );
|
22931 |
+
|
22932 |
+
$remove_user = true;
|
22933 |
+
$all_modules_sites = self::get_all_modules_sites();
|
22934 |
+
|
22935 |
+
foreach ( $all_modules_sites as $sites_by_module_type ) {
|
22936 |
+
foreach ( $sites_by_module_type as $sites_by_slug ) {
|
22937 |
+
foreach ( $sites_by_slug as $site ) {
|
22938 |
+
if ( $prev_user->id == $site->user_id ) {
|
22939 |
+
$remove_user = false;
|
22940 |
+
break;
|
22941 |
+
}
|
22942 |
+
}
|
22943 |
+
|
22944 |
+
if ( ! $remove_user ) {
|
22945 |
+
break;
|
22946 |
+
}
|
22947 |
+
}
|
22948 |
+
|
22949 |
+
if ( ! $remove_user ) {
|
22950 |
+
break;
|
22951 |
+
}
|
22952 |
+
}
|
22953 |
+
|
22954 |
+
if ( $remove_user ) {
|
22955 |
+
$users = self::get_all_users();
|
22956 |
+
|
22957 |
+
if ( isset( $users[ $prev_user->id ] ) ) {
|
22958 |
+
unset( $users[ $prev_user->id ] );
|
22959 |
+
} else {
|
22960 |
+
// If the prev user wasn't found by the key, iterate over the users collection.
|
22961 |
+
foreach ( $users as $key => $user ) {
|
22962 |
+
if ( $user->id == $prev_user->id ) {
|
22963 |
+
unset( $users[ $key ] );
|
22964 |
+
break;
|
22965 |
+
}
|
22966 |
+
}
|
22967 |
+
}
|
22968 |
+
|
22969 |
+
$this->set_account_option( 'users', $users, true );
|
22970 |
+
}
|
22971 |
|
22972 |
return true;
|
22973 |
}
|
23212 |
|
23213 |
if ( $is_parent_plugin_action ) {
|
23214 |
if ( $is_network_action && ! empty( $blog_id ) ) {
|
23215 |
+
if ( $this->is_registered( true ) ) {
|
23216 |
+
if ( $this->is_tracking_prohibited( $blog_id ) ) {
|
23217 |
+
if ( $this->toggle_site_tracking( true, $blog_id ) ) {
|
23218 |
$this->_admin_notices->add(
|
23219 |
+
sprintf( $this->get_text_inline( 'Sharing diagnostic data with %s helps to provide functionality that\'s more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.', 'opt-out-message-appreciation' ), "<b>{$this->get_plugin_title()}</b>" ),
|
23220 |
$this->get_text_inline( 'Thank you!', 'thank-you' )
|
23221 |
);
|
23222 |
}
|
23223 |
} else {
|
23224 |
+
if ( $this->toggle_site_tracking( false, $blog_id ) ) {
|
23225 |
+
$install = $this->get_install_by_blog_id( $blog_id );
|
23226 |
+
|
23227 |
$this->_admin_notices->add(
|
23228 |
sprintf(
|
23229 |
+
$this->get_text_inline( 'Diagnostic data will no longer be sent from %s to %s.', 'opted-out-successfully' ),
|
23230 |
+
self::get_unfiltered_site_url( $blog_id, true ),
|
23231 |
+
"<b>{$this->get_plugin_title()}</b>"
|
|
|
|
|
|
|
|
|
|
|
23232 |
)
|
23233 |
);
|
23234 |
}
|
23376 |
$state = fs_request_get( 'state', 'init' );
|
23377 |
switch ( $state ) {
|
23378 |
case 'init':
|
23379 |
+
$candidate_email = fs_request_get( 'candidate_email' );
|
23380 |
+
$transfer_type = fs_request_get( 'transfer_type' );
|
23381 |
|
23382 |
+
if ( $this->init_change_owner( $candidate_email, $transfer_type ) ) {
|
23383 |
+
if ( 'transfer' === $transfer_type ) {
|
23384 |
+
$this->_admin_notices->add( sprintf( $this->get_text_inline( 'A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.', 'change-owner-request-sent-x-transfer' ), '<b>' . $this->_user->email . '</b>' ) );
|
23385 |
+
} else {
|
23386 |
+
$this->_admin_notices->add( sprintf( $this->get_text_inline( 'A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.', 'change-owner-request-sent-x' ), '<b>' . $this->_user->email . '</b>' ) );
|
23387 |
+
}
|
23388 |
}
|
23389 |
break;
|
23390 |
case 'owner_confirmed':
|
23407 |
|
23408 |
return;
|
23409 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23410 |
case 'update_user_name':
|
23411 |
check_admin_referer( 'update_user_name' );
|
23412 |
|
23568 |
|
23569 |
fs_enqueue_local_style( 'fs_affiliation', '/admin/affiliation.css' );
|
23570 |
|
23571 |
+
$is_bundle_context = $this->has_bundle_context();
|
23572 |
+
|
23573 |
+
$plugin_title = $this->get_plugin_title();
|
23574 |
+
|
23575 |
+
if ( $is_bundle_context ) {
|
23576 |
+
$plugin_title = $this->plugin_affiliate_terms->plugin_title;
|
23577 |
+
|
23578 |
+
// Add the suffix "Bundle" only if the word is not present in the title itself.
|
23579 |
+
if ( false === mb_stripos( $plugin_title, fs_text_inline( 'Bundle', 'bundle' ) ) ) {
|
23580 |
+
$plugin_title = $this->apply_filters(
|
23581 |
+
'formatted_bundle_title',
|
23582 |
+
$plugin_title . ' ' . fs_text_inline( 'Bundle', 'bundle' )
|
23583 |
+
);
|
23584 |
+
}
|
23585 |
+
}
|
23586 |
+
|
23587 |
+
$vars = array(
|
23588 |
+
'id' => $this->_module_id,
|
23589 |
+
'plugin_title' => $plugin_title,
|
23590 |
+
);
|
23591 |
echo $this->apply_filters( "/forms/affiliation.php", fs_get_template( '/forms/affiliation.php', $vars ) );
|
23592 |
}
|
23593 |
|
23688 |
}
|
23689 |
|
23690 |
/* Pricing & Upgrade
|
23691 |
+
------------------------------------------------------------------------------------------------------------------*/
|
23692 |
/**
|
23693 |
* Render pricing page.
|
23694 |
*
|
23830 |
}
|
23831 |
|
23832 |
static function _clean_admin_content_section_hook() {
|
23833 |
+
$hide_admin_notices = true;
|
23834 |
+
|
23835 |
+
if ( fs_request_is_action( 'allow_clone_resolution_notice' ) ) {
|
23836 |
+
check_admin_referer( 'fs_allow_clone_resolution_notice' );
|
23837 |
+
|
23838 |
+
$hide_admin_notices = false;
|
23839 |
+
}
|
23840 |
+
|
23841 |
+
if ( $hide_admin_notices ) {
|
23842 |
+
self::_hide_admin_notices();
|
23843 |
+
}
|
23844 |
|
23845 |
// Hide footer.
|
23846 |
echo '<style>#wpfooter { display: none !important; }</style>';
|
23857 |
}
|
23858 |
|
23859 |
/* CSS & JavaScript
|
23860 |
+
------------------------------------------------------------------------------------------------------------------*/
|
23861 |
/* function _enqueue_script($handle, $src) {
|
23862 |
+
$url = plugins_url( substr( WP_FS__DIR_JS, strlen( $this->_plugin_dir_path ) ) . '/assets/js/' . $src );
|
23863 |
|
23864 |
+
$this->_logger->entrance( 'script = ' . $url );
|
23865 |
|
23866 |
+
wp_enqueue_script( $handle, $url );
|
23867 |
+
}*/
|
23868 |
|
23869 |
/* SDK
|
23870 |
+
------------------------------------------------------------------------------------------------------------------*/
|
23871 |
private $_user_api;
|
23872 |
|
23873 |
/**
|
23879 |
*
|
23880 |
* @return FS_Api
|
23881 |
*/
|
23882 |
+
function get_api_user_scope( $flush = false ) {
|
23883 |
if ( ! isset( $this->_user_api ) || $flush ) {
|
23884 |
$this->_user_api = $this->get_api_user_scope_by_user( $this->_user );
|
23885 |
}
|
23958 |
$this->_site->public_key,
|
23959 |
! $this->is_live(),
|
23960 |
$this->_site->secret_key,
|
23961 |
+
$this->get_sdk_version(),
|
23962 |
+
self::get_unfiltered_site_url()
|
23963 |
);
|
23964 |
}
|
23965 |
|
23966 |
return $this->_site_api;
|
23967 |
}
|
23968 |
|
23969 |
+
/**
|
23970 |
+
* @author Leo Fajardo (@leorw)
|
23971 |
+
* @since 2.5.0
|
23972 |
+
*
|
23973 |
+
* @param string $path
|
23974 |
+
* @param string $method
|
23975 |
+
* @param array $params
|
23976 |
+
* @param bool $flush_instance
|
23977 |
+
*
|
23978 |
+
* @return array|mixed|string|void
|
23979 |
+
* @throws Freemius_Exception
|
23980 |
+
*/
|
23981 |
+
private function api_site_call( $path, $method = 'GET', $params = array(), $flush_instance = false ) {
|
23982 |
+
$result = $this->get_api_site_scope( $flush_instance )->call( $path, $method, $params );
|
23983 |
+
|
23984 |
+
/**
|
23985 |
+
* Checks if the local install's URL is different from the remote install's URL, update the local install if necessary, and then run the clone handler if the install's URL is different from the URL of the site.
|
23986 |
+
*
|
23987 |
+
* @author Leo Fajardo (@leorw)
|
23988 |
+
* @since 2.5.0
|
23989 |
+
*/
|
23990 |
+
if (
|
23991 |
+
$this->is_registered() &&
|
23992 |
+
FS_Api::is_api_result_entity( $result ) &&
|
23993 |
+
isset( $result->url )
|
23994 |
+
) {
|
23995 |
+
$stored_local_url = trailingslashit( $this->_site->url );
|
23996 |
+
$stored_remote_url = trailingslashit( $result->url );
|
23997 |
+
|
23998 |
+
if ( $stored_local_url !== $stored_remote_url ) {
|
23999 |
+
$this->_site->url = $result->url;
|
24000 |
+
$this->_store_site();
|
24001 |
+
}
|
24002 |
+
|
24003 |
+
if ( fs_strip_url_protocol( $stored_remote_url ) !== self::get_unfiltered_site_url( null, true, true ) ) {
|
24004 |
+
FS_Clone_Manager::instance()->maybe_run_clone_resolution();
|
24005 |
+
}
|
24006 |
+
}
|
24007 |
+
|
24008 |
+
return $result;
|
24009 |
+
}
|
24010 |
+
|
24011 |
private $_plugin_api;
|
24012 |
|
24013 |
/**
|
24443 |
}
|
24444 |
|
24445 |
/* Action Links
|
24446 |
+
------------------------------------------------------------------------------------------------------------------*/
|
24447 |
private $_action_links_hooked = false;
|
24448 |
private $_action_links = array();
|
24449 |
|
24614 |
|
24615 |
$this->_logger->entrance();
|
24616 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24617 |
if ( $this->is_only_premium() && $this->is_free_plan() ) {
|
24618 |
// Don't add tracking links for premium-only products that were opted-in by relation (add-on or a parent product) before activating any license.
|
24619 |
return;
|
24621 |
|
24622 |
if (
|
24623 |
$this->is_addon() &&
|
24624 |
+
! $this->is_only_premium()
|
|
|
24625 |
) {
|
24626 |
+
$parent = $this->get_parent_instance();
|
24627 |
+
|
24628 |
+
if ( is_object( $parent ) && $parent->is_anonymous() ) {
|
24629 |
+
return;
|
24630 |
+
}
|
24631 |
}
|
24632 |
|
24633 |
if ( fs_is_network_admin() ) {
|
24676 |
}
|
24677 |
}
|
24678 |
|
24679 |
+
if ( $this->add_ajax_action( 'toggle_permission_tracking', array( &$this, '_toggle_permission_tracking_callback' ) ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24680 |
return;
|
24681 |
}
|
24682 |
|
24683 |
$link_text_id = '';
|
24684 |
$url = '#';
|
24685 |
|
24686 |
+
if ( $this->is_registered( true ) ) {
|
24687 |
+
if ( $this->is_registered() && $this->is_tracking_allowed() ) {
|
24688 |
$link_text_id = $this->get_text_inline( 'Opt Out', 'opt-out' );
|
24689 |
} else {
|
24690 |
$link_text_id = $this->get_text_inline( 'Opt In', 'opt-in' );
|
24881 |
*/
|
24882 |
private function is_premium_version_installed() {
|
24883 |
$premium_plugin_basename = $this->premium_plugin_basename();
|
|
|
24884 |
|
24885 |
+
if ( $this->is_theme() ) {
|
24886 |
+
return $this->can_activate_theme( $this->get_premium_slug() );
|
24887 |
+
}
|
24888 |
+
|
24889 |
+
return file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_plugin_basename ) );
|
24890 |
}
|
24891 |
|
24892 |
/**
|
24922 |
* @author Leo Fajardo (@leorw)
|
24923 |
* @since 2.2.1
|
24924 |
*/
|
24925 |
+
$premium_theme_slug_or_plugin_basename = $this->is_theme() ?
|
24926 |
+
$this->get_premium_slug() :
|
24927 |
+
$this->premium_plugin_basename();
|
24928 |
|
24929 |
return sprintf(
|
24930 |
/* translators: %1$s: Product title; %2$s: Plan title */
|
24933 |
$plan_title,
|
24934 |
sprintf(
|
24935 |
'<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s</button></a>',
|
24936 |
+
( $this->is_theme() ?
|
24937 |
+
wp_nonce_url( 'themes.php?action=activate&stylesheet=' . $premium_theme_slug_or_plugin_basename, 'switch-theme_' . $premium_theme_slug_or_plugin_basename ) :
|
24938 |
+
wp_nonce_url( 'plugins.php?action=activate&plugin=' . $premium_theme_slug_or_plugin_basename, 'activate-plugin_' . $premium_theme_slug_or_plugin_basename ) ),
|
24939 |
esc_html( sprintf(
|
24940 |
/* translators: %s: Plan title */
|
24941 |
$this->get_text_inline( 'Activate %s features', 'activate-x-features' ),
|
24960 |
) ),
|
24961 |
$deactivation_step,
|
24962 |
$this->get_text_inline( 'Upload and activate the downloaded version', 'upload-and-activate' ),
|
24963 |
+
$this->apply_filters( 'upload_and_install_video_url', '//bit.ly/wp-' . $this->_module_type . '-upload' ),
|
24964 |
$this->get_text_inline( 'How to upload and activate?', 'howto-upload-activate' )
|
24965 |
);
|
24966 |
}
|
25413 |
function _tabs_capture() {
|
25414 |
$this->_logger->entrance();
|
25415 |
|
25416 |
+
if (
|
25417 |
+
! $this->is_product_settings_page() ||
|
25418 |
+
! $this->should_page_include_tabs() ||
|
25419 |
+
! $this->is_matching_url( $this->main_menu_url() )
|
25420 |
) {
|
25421 |
return;
|
25422 |
}
|
25470 |
function _store_tabs_styles() {
|
25471 |
$this->_logger->entrance();
|
25472 |
|
25473 |
+
if (
|
25474 |
+
! $this->is_product_settings_page() ||
|
25475 |
+
! $this->should_page_include_tabs() ||
|
25476 |
+
! $this->is_matching_url( $this->main_menu_url() )
|
25477 |
) {
|
25478 |
return;
|
25479 |
}
|
freemius/includes/class-fs-admin-notices.php
CHANGED
@@ -125,13 +125,10 @@
|
|
125 |
$is_sticky = false,
|
126 |
$id = '',
|
127 |
$store_if_sticky = true,
|
128 |
-
$network_level_or_blog_id = null
|
|
|
129 |
) {
|
130 |
-
|
131 |
-
$notices = $this->_network_notices;
|
132 |
-
} else {
|
133 |
-
$notices = $this->get_site_notices( $network_level_or_blog_id );
|
134 |
-
}
|
135 |
|
136 |
$notices->add(
|
137 |
$message,
|
@@ -139,7 +136,11 @@
|
|
139 |
$type,
|
140 |
$is_sticky,
|
141 |
$id,
|
142 |
-
$store_if_sticky
|
|
|
|
|
|
|
|
|
143 |
);
|
144 |
}
|
145 |
|
@@ -149,8 +150,9 @@
|
|
149 |
*
|
150 |
* @param string|string[] $ids
|
151 |
* @param int|null $network_level_or_blog_id
|
|
|
152 |
*/
|
153 |
-
function remove_sticky( $ids, $network_level_or_blog_id = null ) {
|
154 |
if ( ! is_array( $ids ) ) {
|
155 |
$ids = array( $ids );
|
156 |
}
|
@@ -161,7 +163,7 @@
|
|
161 |
$notices = $this->get_site_notices( $network_level_or_blog_id );
|
162 |
}
|
163 |
|
164 |
-
return $notices->remove_sticky( $ids );
|
165 |
}
|
166 |
|
167 |
/**
|
@@ -176,11 +178,7 @@
|
|
176 |
* @return bool
|
177 |
*/
|
178 |
function has_sticky( $id, $network_level_or_blog_id = null ) {
|
179 |
-
|
180 |
-
$notices = $this->_network_notices;
|
181 |
-
} else {
|
182 |
-
$notices = $this->get_site_notices( $network_level_or_blog_id );
|
183 |
-
}
|
184 |
|
185 |
return $notices->has_sticky( $id );
|
186 |
}
|
@@ -200,6 +198,7 @@
|
|
200 |
* @param string|null $plugin_title
|
201 |
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and
|
202 |
* blog admin pages.
|
|
|
203 |
*/
|
204 |
function add_sticky(
|
205 |
$message,
|
@@ -209,15 +208,30 @@
|
|
209 |
$network_level_or_blog_id = null,
|
210 |
$wp_user_id = null,
|
211 |
$plugin_title = null,
|
212 |
-
$is_network_and_blog_admins = false
|
|
|
|
|
213 |
) {
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
-
$notices->
|
221 |
}
|
222 |
|
223 |
/**
|
@@ -227,21 +241,22 @@
|
|
227 |
* @since 2.0.0
|
228 |
*
|
229 |
* @param int|null $network_level_or_blog_id
|
|
|
230 |
*/
|
231 |
-
function clear_all_sticky( $network_level_or_blog_id = null ) {
|
232 |
if ( ! $this->_is_multisite ||
|
233 |
false === $network_level_or_blog_id ||
|
234 |
0 == $network_level_or_blog_id ||
|
235 |
is_null( $network_level_or_blog_id )
|
236 |
) {
|
237 |
$notices = $this->get_site_notices( $network_level_or_blog_id );
|
238 |
-
$notices->clear_all_sticky();
|
239 |
}
|
240 |
|
241 |
if ( $this->_is_multisite &&
|
242 |
( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
|
243 |
) {
|
244 |
-
$this->_network_notices->clear_all_sticky();
|
245 |
}
|
246 |
}
|
247 |
|
@@ -317,5 +332,22 @@
|
|
317 |
return fs_is_network_admin();
|
318 |
}
|
319 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
320 |
#endregion
|
321 |
}
|
125 |
$is_sticky = false,
|
126 |
$id = '',
|
127 |
$store_if_sticky = true,
|
128 |
+
$network_level_or_blog_id = null,
|
129 |
+
$is_dimissible = null
|
130 |
) {
|
131 |
+
$notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id );
|
|
|
|
|
|
|
|
|
132 |
|
133 |
$notices->add(
|
134 |
$message,
|
136 |
$type,
|
137 |
$is_sticky,
|
138 |
$id,
|
139 |
+
$store_if_sticky,
|
140 |
+
null,
|
141 |
+
null,
|
142 |
+
false,
|
143 |
+
$is_dimissible
|
144 |
);
|
145 |
}
|
146 |
|
150 |
*
|
151 |
* @param string|string[] $ids
|
152 |
* @param int|null $network_level_or_blog_id
|
153 |
+
* @param bool $store
|
154 |
*/
|
155 |
+
function remove_sticky( $ids, $network_level_or_blog_id = null, $store = true ) {
|
156 |
if ( ! is_array( $ids ) ) {
|
157 |
$ids = array( $ids );
|
158 |
}
|
163 |
$notices = $this->get_site_notices( $network_level_or_blog_id );
|
164 |
}
|
165 |
|
166 |
+
return $notices->remove_sticky( $ids, $store );
|
167 |
}
|
168 |
|
169 |
/**
|
178 |
* @return bool
|
179 |
*/
|
180 |
function has_sticky( $id, $network_level_or_blog_id = null ) {
|
181 |
+
$notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id );
|
|
|
|
|
|
|
|
|
182 |
|
183 |
return $notices->has_sticky( $id );
|
184 |
}
|
198 |
* @param string|null $plugin_title
|
199 |
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and
|
200 |
* blog admin pages.
|
201 |
+
* @param bool $is_dismissible
|
202 |
*/
|
203 |
function add_sticky(
|
204 |
$message,
|
208 |
$network_level_or_blog_id = null,
|
209 |
$wp_user_id = null,
|
210 |
$plugin_title = null,
|
211 |
+
$is_network_and_blog_admins = false,
|
212 |
+
$is_dismissible = true,
|
213 |
+
$data = array()
|
214 |
) {
|
215 |
+
$notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id );
|
216 |
+
|
217 |
+
$notices->add_sticky( $message, $id, $title, $type, $wp_user_id, $plugin_title, $is_network_and_blog_admins, $is_dismissible, $data );
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Retrieves the data of a sticky notice.
|
222 |
+
*
|
223 |
+
* @author Leo Fajardo (@leorw)
|
224 |
+
* @since 2.4.3
|
225 |
+
*
|
226 |
+
* @param string $id
|
227 |
+
* @param int|null $network_level_or_blog_id
|
228 |
+
*
|
229 |
+
* @return array|null
|
230 |
+
*/
|
231 |
+
function get_sticky( $id, $network_level_or_blog_id ) {
|
232 |
+
$notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id );
|
233 |
|
234 |
+
return $notices->get_sticky( $id );
|
235 |
}
|
236 |
|
237 |
/**
|
241 |
* @since 2.0.0
|
242 |
*
|
243 |
* @param int|null $network_level_or_blog_id
|
244 |
+
* @param bool $is_temporary
|
245 |
*/
|
246 |
+
function clear_all_sticky( $network_level_or_blog_id = null, $is_temporary = false ) {
|
247 |
if ( ! $this->_is_multisite ||
|
248 |
false === $network_level_or_blog_id ||
|
249 |
0 == $network_level_or_blog_id ||
|
250 |
is_null( $network_level_or_blog_id )
|
251 |
) {
|
252 |
$notices = $this->get_site_notices( $network_level_or_blog_id );
|
253 |
+
$notices->clear_all_sticky( $is_temporary );
|
254 |
}
|
255 |
|
256 |
if ( $this->_is_multisite &&
|
257 |
( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
|
258 |
) {
|
259 |
+
$this->_network_notices->clear_all_sticky( $is_temporary );
|
260 |
}
|
261 |
}
|
262 |
|
332 |
return fs_is_network_admin();
|
333 |
}
|
334 |
|
335 |
+
/**
|
336 |
+
* Retrieves an instance of FS_Admin_Notice_Manager.
|
337 |
+
*
|
338 |
+
* @author Leo Fajardo (@leorw)
|
339 |
+
* @since 2.5.0
|
340 |
+
*
|
341 |
+
* @param string $id
|
342 |
+
* @param int|null $network_level_or_blog_id
|
343 |
+
*
|
344 |
+
* @return FS_Admin_Notice_Manager
|
345 |
+
*/
|
346 |
+
private function get_site_or_network_notices( $id, $network_level_or_blog_id ) {
|
347 |
+
return $this->should_use_network_notices( $id, $network_level_or_blog_id ) ?
|
348 |
+
$this->_network_notices :
|
349 |
+
$this->get_site_notices( $network_level_or_blog_id );
|
350 |
+
}
|
351 |
+
|
352 |
#endregion
|
353 |
}
|
freemius/includes/class-fs-api.php
CHANGED
@@ -64,6 +64,14 @@
|
|
64 |
*/
|
65 |
private $_sdk_version;
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
/**
|
68 |
* @param string $slug
|
69 |
* @param string $scope 'app', 'developer', 'user' or 'install'.
|
@@ -72,6 +80,7 @@
|
|
72 |
* @param bool $is_sandbox
|
73 |
* @param bool|string $secret_key Element's secret key.
|
74 |
* @param null|string $sdk_version
|
|
|
75 |
*
|
76 |
* @return FS_Api
|
77 |
*/
|
@@ -82,14 +91,15 @@
|
|
82 |
$public_key,
|
83 |
$is_sandbox,
|
84 |
$secret_key = false,
|
85 |
-
$sdk_version = null
|
|
|
86 |
) {
|
87 |
$identifier = md5( $slug . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) );
|
88 |
|
89 |
if ( ! isset( self::$_instances[ $identifier ] ) ) {
|
90 |
self::_init();
|
91 |
|
92 |
-
self::$_instances[ $identifier ] = new FS_Api( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox, $sdk_version );
|
93 |
}
|
94 |
|
95 |
return self::$_instances[ $identifier ];
|
@@ -123,6 +133,7 @@
|
|
123 |
* @param bool|string $secret_key Element's secret key.
|
124 |
* @param bool $is_sandbox
|
125 |
* @param null|string $sdk_version
|
|
|
126 |
*/
|
127 |
private function __construct(
|
128 |
$slug,
|
@@ -131,12 +142,14 @@
|
|
131 |
$public_key,
|
132 |
$secret_key,
|
133 |
$is_sandbox,
|
134 |
-
$sdk_version
|
|
|
135 |
) {
|
136 |
$this->_api = new Freemius_Api_WordPress( $scope, $id, $public_key, $secret_key, $is_sandbox );
|
137 |
|
138 |
$this->_slug = $slug;
|
139 |
$this->_sdk_version = $sdk_version;
|
|
|
140 |
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_api', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
|
141 |
}
|
142 |
|
@@ -198,6 +211,17 @@
|
|
198 |
}
|
199 |
}
|
200 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
$result = $this->_api->Api( $path, $method, $params );
|
202 |
|
203 |
if ( null !== $result &&
|
64 |
*/
|
65 |
private $_sdk_version;
|
66 |
|
67 |
+
/**
|
68 |
+
* @author Leo Fajardo (@leorw)
|
69 |
+
* @since 2.5.0
|
70 |
+
*
|
71 |
+
* @var string
|
72 |
+
*/
|
73 |
+
private $_url;
|
74 |
+
|
75 |
/**
|
76 |
* @param string $slug
|
77 |
* @param string $scope 'app', 'developer', 'user' or 'install'.
|
80 |
* @param bool $is_sandbox
|
81 |
* @param bool|string $secret_key Element's secret key.
|
82 |
* @param null|string $sdk_version
|
83 |
+
* @param null|string $url
|
84 |
*
|
85 |
* @return FS_Api
|
86 |
*/
|
91 |
$public_key,
|
92 |
$is_sandbox,
|
93 |
$secret_key = false,
|
94 |
+
$sdk_version = null,
|
95 |
+
$url = null
|
96 |
) {
|
97 |
$identifier = md5( $slug . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) );
|
98 |
|
99 |
if ( ! isset( self::$_instances[ $identifier ] ) ) {
|
100 |
self::_init();
|
101 |
|
102 |
+
self::$_instances[ $identifier ] = new FS_Api( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox, $sdk_version, $url );
|
103 |
}
|
104 |
|
105 |
return self::$_instances[ $identifier ];
|
133 |
* @param bool|string $secret_key Element's secret key.
|
134 |
* @param bool $is_sandbox
|
135 |
* @param null|string $sdk_version
|
136 |
+
* @param null|string $url
|
137 |
*/
|
138 |
private function __construct(
|
139 |
$slug,
|
142 |
$public_key,
|
143 |
$secret_key,
|
144 |
$is_sandbox,
|
145 |
+
$sdk_version,
|
146 |
+
$url
|
147 |
) {
|
148 |
$this->_api = new Freemius_Api_WordPress( $scope, $id, $public_key, $secret_key, $is_sandbox );
|
149 |
|
150 |
$this->_slug = $slug;
|
151 |
$this->_sdk_version = $sdk_version;
|
152 |
+
$this->_url = $url;
|
153 |
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_api', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
|
154 |
}
|
155 |
|
211 |
}
|
212 |
}
|
213 |
|
214 |
+
/**
|
215 |
+
* @since 2.5.0 Include the site's URL, if available, in all API requests that are going through the API manager.
|
216 |
+
*/
|
217 |
+
if ( ! empty( $this->_url ) ) {
|
218 |
+
if ( false === strpos( $path, 'url=' ) &&
|
219 |
+
! isset( $params['url'] )
|
220 |
+
) {
|
221 |
+
$path = add_query_arg( 'url', $this->_url, $path );
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
$result = $this->_api->Api( $path, $method, $params );
|
226 |
|
227 |
if ( null !== $result &&
|
freemius/includes/class-fs-lock.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 2.5.1
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Class FS_Lock
|
15 |
+
*
|
16 |
+
* @author Vova Feldman (@svovaf)
|
17 |
+
* @since 2.5.1
|
18 |
+
*/
|
19 |
+
class FS_Lock {
|
20 |
+
/**
|
21 |
+
* @var int Random ID representing the current PHP thread.
|
22 |
+
*/
|
23 |
+
private static $_thread_id;
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
private $_lock_id;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param string $lock_id
|
31 |
+
*/
|
32 |
+
function __construct( $lock_id ) {
|
33 |
+
if ( ! fs_starts_with( $lock_id, WP_FS___OPTION_PREFIX ) ) {
|
34 |
+
$lock_id = WP_FS___OPTION_PREFIX . $lock_id;
|
35 |
+
}
|
36 |
+
|
37 |
+
$this->_lock_id = $lock_id;
|
38 |
+
|
39 |
+
if ( ! isset( self::$_thread_id ) ) {
|
40 |
+
self::$_thread_id = mt_rand( 0, 32000 );
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Try to acquire lock. If the lock is already set or is being acquired by another locker, don't do anything.
|
46 |
+
*
|
47 |
+
* @param int $expiration
|
48 |
+
*
|
49 |
+
* @return bool TRUE if successfully acquired lock.
|
50 |
+
*/
|
51 |
+
function try_lock( $expiration = 0 ) {
|
52 |
+
if ( $this->is_locked() ) {
|
53 |
+
// Already locked.
|
54 |
+
return false;
|
55 |
+
}
|
56 |
+
|
57 |
+
set_site_transient( $this->_lock_id, self::$_thread_id, $expiration );
|
58 |
+
|
59 |
+
if ( $this->has_lock() ) {
|
60 |
+
$this->lock($expiration);
|
61 |
+
|
62 |
+
return true;
|
63 |
+
}
|
64 |
+
|
65 |
+
return false;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Acquire lock regardless if it's already acquired by another locker or not.
|
70 |
+
*
|
71 |
+
* @author Vova Feldman (@svovaf)
|
72 |
+
* @since 2.1.0
|
73 |
+
*
|
74 |
+
* @param int $expiration
|
75 |
+
*/
|
76 |
+
function lock( $expiration = 0 ) {
|
77 |
+
set_site_transient( $this->_lock_id, true, $expiration );
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Checks if lock is currently acquired.
|
82 |
+
*
|
83 |
+
* @author Vova Feldman (@svovaf)
|
84 |
+
* @since 2.1.0
|
85 |
+
*
|
86 |
+
* @return bool
|
87 |
+
*/
|
88 |
+
function is_locked() {
|
89 |
+
return ( false !== get_site_transient( $this->_lock_id ) );
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Unlock the lock.
|
94 |
+
*
|
95 |
+
* @author Vova Feldman (@svovaf)
|
96 |
+
* @since 2.1.0
|
97 |
+
*/
|
98 |
+
function unlock() {
|
99 |
+
delete_site_transient( $this->_lock_id );
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Checks if lock is currently acquired by the current locker.
|
104 |
+
*
|
105 |
+
* @return bool
|
106 |
+
*/
|
107 |
+
protected function has_lock() {
|
108 |
+
return ( self::$_thread_id == get_site_transient( $this->_lock_id ) );
|
109 |
+
}
|
110 |
+
}
|
freemius/includes/class-fs-logger.php
CHANGED
@@ -38,9 +38,10 @@
|
|
38 |
private static $_HOOKED_FOOTER = false;
|
39 |
|
40 |
private function __construct( $id, $on = false, $echo = false ) {
|
|
|
|
|
41 |
$this->_id = $id;
|
42 |
|
43 |
-
$bt = debug_backtrace();
|
44 |
$caller = $bt[2];
|
45 |
|
46 |
if ( false !== strpos( $caller['file'], 'plugins' ) ) {
|
38 |
private static $_HOOKED_FOOTER = false;
|
39 |
|
40 |
private function __construct( $id, $on = false, $echo = false ) {
|
41 |
+
$bt = debug_backtrace();
|
42 |
+
|
43 |
$this->_id = $id;
|
44 |
|
|
|
45 |
$caller = $bt[2];
|
46 |
|
47 |
if ( false !== strpos( $caller['file'], 'plugins' ) ) {
|
freemius/includes/class-fs-plugin-updater.php
CHANGED
@@ -240,7 +240,11 @@
|
|
240 |
* @since 2.0.0
|
241 |
*/
|
242 |
private function add_transient_filters() {
|
243 |
-
if (
|
|
|
|
|
|
|
|
|
244 |
$this->_logger->log( 'Opted out sites cannot receive automatic software updates.' );
|
245 |
|
246 |
return;
|
@@ -610,11 +614,9 @@
|
|
610 |
if ( ! isset( $this->_translation_updates ) ) {
|
611 |
$this->_translation_updates = array();
|
612 |
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
$this->_translation_updates = $translation_updates;
|
617 |
-
}
|
618 |
}
|
619 |
}
|
620 |
|
@@ -648,7 +650,7 @@
|
|
648 |
}
|
649 |
|
650 |
/**
|
651 |
-
* Get module's required data for the updates mechanism.
|
652 |
*
|
653 |
* @author Vova Feldman (@svovaf)
|
654 |
* @since 2.0.0
|
240 |
* @since 2.0.0
|
241 |
*/
|
242 |
private function add_transient_filters() {
|
243 |
+
if (
|
244 |
+
$this->_fs->is_premium() &&
|
245 |
+
$this->_fs->is_registered() &&
|
246 |
+
! FS_Permission_Manager::instance( $this->_fs )->is_essentials_tracking_allowed()
|
247 |
+
) {
|
248 |
$this->_logger->log( 'Opted out sites cannot receive automatic software updates.' );
|
249 |
|
250 |
return;
|
614 |
if ( ! isset( $this->_translation_updates ) ) {
|
615 |
$this->_translation_updates = array();
|
616 |
|
617 |
+
$translation_updates = $this->fetch_wp_org_module_translation_updates( $module_type, $slug );
|
618 |
+
if ( ! empty( $translation_updates ) ) {
|
619 |
+
$this->_translation_updates = $translation_updates;
|
|
|
|
|
620 |
}
|
621 |
}
|
622 |
|
650 |
}
|
651 |
|
652 |
/**
|
653 |
+
* Get module's required data for the updates' mechanism.
|
654 |
*
|
655 |
* @author Vova Feldman (@svovaf)
|
656 |
* @since 2.0.0
|
freemius/includes/class-fs-storage.php
CHANGED
@@ -15,9 +15,11 @@
|
|
15 |
*
|
16 |
* A wrapper class for handling network level and single site level storage.
|
17 |
*
|
18 |
-
* @property bool
|
19 |
-
* @property int
|
20 |
-
* @property
|
|
|
|
|
21 |
*/
|
22 |
class FS_Storage {
|
23 |
/**
|
@@ -72,6 +74,16 @@
|
|
72 |
*/
|
73 |
private static $_NETWORK_OPTIONS_MAP;
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
/**
|
76 |
* @author Leo Fajardo (@leorw)
|
77 |
*
|
@@ -142,10 +154,17 @@
|
|
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(
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
$this->_network_storage->store( $key, $value, $flush );
|
150 |
} else {
|
151 |
$storage = $this->get_site_storage( $network_level_or_blog_id );
|
@@ -199,11 +218,17 @@
|
|
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(
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
207 |
return $this->_network_storage->get( $key, $default );
|
208 |
} else {
|
209 |
$storage = $this->get_site_storage( $network_level_or_blog_id );
|
@@ -289,19 +314,6 @@
|
|
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 |
}
|
@@ -336,63 +348,61 @@
|
|
336 |
private static function load_network_options_map() {
|
337 |
self::$_NETWORK_OPTIONS_MAP = array(
|
338 |
// Network level options.
|
339 |
-
'affiliate_application_data' =>
|
340 |
-
'beta_data' =>
|
341 |
-
'connectivity_test' =>
|
342 |
-
'handle_gdpr_admin_notice' =>
|
343 |
-
'has_trial_plan' =>
|
344 |
-
'install_sync_timestamp' =>
|
345 |
-
'install_sync_cron' =>
|
346 |
-
'is_anonymous_ms' =>
|
347 |
-
'is_network_activated' =>
|
348 |
-
'is_on' =>
|
349 |
-
'is_plugin_new_install' =>
|
350 |
-
'network_install_blog_id' =>
|
351 |
-
'pending_sites_info' =>
|
352 |
-
'plugin_last_version' =>
|
353 |
-
'plugin_main_file' =>
|
354 |
-
'plugin_version' =>
|
355 |
-
'sdk_downgrade_mode' =>
|
356 |
-
'sdk_last_version' =>
|
357 |
-
'sdk_upgrade_mode' =>
|
358 |
-
'sdk_version' =>
|
359 |
-
'sticky_optin_added_ms' =>
|
360 |
-
'subscriptions' =>
|
361 |
-
'sync_timestamp' =>
|
362 |
-
'sync_cron' =>
|
363 |
-
'was_plugin_loaded' =>
|
364 |
-
'network_user_id' =>
|
365 |
-
'plugin_upgrade_mode' =>
|
366 |
-
'plugin_downgrade_mode' =>
|
367 |
-
'is_network_connected' =>
|
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' =>
|
374 |
-
'license_migration' =>
|
375 |
|
376 |
// When network activated, then network level.
|
377 |
-
'install_timestamp' =>
|
378 |
-
'prev_is_premium' =>
|
379 |
-
'require_license_activation' =>
|
380 |
|
381 |
// If not network activated OR delegated, then site level.
|
382 |
-
'activation_timestamp'
|
383 |
-
'expired_license_notice_shown'
|
384 |
-
'is_whitelabeled'
|
385 |
-
'last_license_key'
|
386 |
-
'last_license_user_id'
|
387 |
-
'prev_user_id'
|
388 |
-
'sticky_optin_added'
|
389 |
-
'uninstall_reason'
|
390 |
-
'is_pending_activation'
|
391 |
-
'pending_license_key'
|
392 |
-
'is_extensions_tracking_allowed' => 2,
|
393 |
|
394 |
// Site level options.
|
395 |
-
'is_anonymous' =>
|
|
|
396 |
);
|
397 |
}
|
398 |
|
@@ -403,25 +413,33 @@
|
|
403 |
* @since 2.0.0
|
404 |
*
|
405 |
* @param string $key
|
|
|
406 |
*
|
407 |
-
* @return bool
|
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 (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
415 |
// Option not found -> use site level storage.
|
416 |
return false;
|
417 |
}
|
418 |
|
419 |
-
if (
|
420 |
// Option found and set to always use the network level storage on a multisite.
|
421 |
return true;
|
422 |
}
|
423 |
|
424 |
-
if (
|
425 |
// Option found and set to always use the site level storage on a multisite.
|
426 |
return false;
|
427 |
}
|
@@ -430,12 +448,15 @@
|
|
430 |
return false;
|
431 |
}
|
432 |
|
433 |
-
if (
|
434 |
// Network activated.
|
435 |
return true;
|
436 |
}
|
437 |
|
438 |
-
if (
|
|
|
|
|
|
|
439 |
// Network activated and not delegated.
|
440 |
return true;
|
441 |
}
|
@@ -448,10 +469,15 @@
|
|
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(
|
|
|
|
|
|
|
|
|
455 |
if ( ! $this->_is_multisite ) {
|
456 |
// Not a multisite environment.
|
457 |
return false;
|
@@ -463,12 +489,12 @@
|
|
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 |
/**
|
@@ -529,4 +555,4 @@
|
|
529 |
}
|
530 |
|
531 |
#endregion
|
532 |
-
}
|
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 bool|null $is_extensions_tracking_allowed
|
21 |
+
* @property bool|null $is_diagnostic_tracking_allowed
|
22 |
+
* @property object $sync_cron
|
23 |
*/
|
24 |
class FS_Storage {
|
25 |
/**
|
74 |
*/
|
75 |
private static $_NETWORK_OPTIONS_MAP;
|
76 |
|
77 |
+
const OPTION_LEVEL_UNDEFINED = -1;
|
78 |
+
// The option should be stored on the network level.
|
79 |
+
const OPTION_LEVEL_NETWORK = 0;
|
80 |
+
// The option should be stored on the network level when the plugin is network-activated.
|
81 |
+
const OPTION_LEVEL_NETWORK_ACTIVATED = 1;
|
82 |
+
// The option should be stored on the network level when the plugin is network-activated and the opt-in connection was NOT delegated to the sub-site admin.
|
83 |
+
const OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED = 2;
|
84 |
+
// The option should be stored on the site level.
|
85 |
+
const OPTION_LEVEL_SITE = 3;
|
86 |
+
|
87 |
/**
|
88 |
* @author Leo Fajardo (@leorw)
|
89 |
*
|
154 |
* @param string $key
|
155 |
* @param mixed $value
|
156 |
* @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).
|
157 |
+
* @param int $option_level Since 2.5.1
|
158 |
* @param bool $flush
|
159 |
*/
|
160 |
+
function store(
|
161 |
+
$key,
|
162 |
+
$value,
|
163 |
+
$network_level_or_blog_id = null,
|
164 |
+
$option_level = self::OPTION_LEVEL_UNDEFINED,
|
165 |
+
$flush = true
|
166 |
+
) {
|
167 |
+
if ( $this->should_use_network_storage( $key, $network_level_or_blog_id, $option_level ) ) {
|
168 |
$this->_network_storage->store( $key, $value, $flush );
|
169 |
} else {
|
170 |
$storage = $this->get_site_storage( $network_level_or_blog_id );
|
218 |
* @param string $key
|
219 |
* @param mixed $default
|
220 |
* @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).
|
221 |
+
* @param int $option_level Since 2.5.1
|
222 |
*
|
223 |
* @return mixed
|
224 |
*/
|
225 |
+
function get(
|
226 |
+
$key,
|
227 |
+
$default = false,
|
228 |
+
$network_level_or_blog_id = null,
|
229 |
+
$option_level = self::OPTION_LEVEL_UNDEFINED
|
230 |
+
) {
|
231 |
+
if ( $this->should_use_network_storage( $key, $network_level_or_blog_id, $option_level ) ) {
|
232 |
return $this->_network_storage->get( $key, $default );
|
233 |
} else {
|
234 |
$storage = $this->get_site_storage( $network_level_or_blog_id );
|
314 |
// Migrate option to the network storage.
|
315 |
$this->_network_storage->store( $option, $this->_storage->{$option}, false );
|
316 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
$updated = true;
|
318 |
}
|
319 |
}
|
348 |
private static function load_network_options_map() {
|
349 |
self::$_NETWORK_OPTIONS_MAP = array(
|
350 |
// Network level options.
|
351 |
+
'affiliate_application_data' => self::OPTION_LEVEL_NETWORK,
|
352 |
+
'beta_data' => self::OPTION_LEVEL_NETWORK,
|
353 |
+
'connectivity_test' => self::OPTION_LEVEL_NETWORK,
|
354 |
+
'handle_gdpr_admin_notice' => self::OPTION_LEVEL_NETWORK,
|
355 |
+
'has_trial_plan' => self::OPTION_LEVEL_NETWORK,
|
356 |
+
'install_sync_timestamp' => self::OPTION_LEVEL_NETWORK,
|
357 |
+
'install_sync_cron' => self::OPTION_LEVEL_NETWORK,
|
358 |
+
'is_anonymous_ms' => self::OPTION_LEVEL_NETWORK,
|
359 |
+
'is_network_activated' => self::OPTION_LEVEL_NETWORK,
|
360 |
+
'is_on' => self::OPTION_LEVEL_NETWORK,
|
361 |
+
'is_plugin_new_install' => self::OPTION_LEVEL_NETWORK,
|
362 |
+
'network_install_blog_id' => self::OPTION_LEVEL_NETWORK,
|
363 |
+
'pending_sites_info' => self::OPTION_LEVEL_NETWORK,
|
364 |
+
'plugin_last_version' => self::OPTION_LEVEL_NETWORK,
|
365 |
+
'plugin_main_file' => self::OPTION_LEVEL_NETWORK,
|
366 |
+
'plugin_version' => self::OPTION_LEVEL_NETWORK,
|
367 |
+
'sdk_downgrade_mode' => self::OPTION_LEVEL_NETWORK,
|
368 |
+
'sdk_last_version' => self::OPTION_LEVEL_NETWORK,
|
369 |
+
'sdk_upgrade_mode' => self::OPTION_LEVEL_NETWORK,
|
370 |
+
'sdk_version' => self::OPTION_LEVEL_NETWORK,
|
371 |
+
'sticky_optin_added_ms' => self::OPTION_LEVEL_NETWORK,
|
372 |
+
'subscriptions' => self::OPTION_LEVEL_NETWORK,
|
373 |
+
'sync_timestamp' => self::OPTION_LEVEL_NETWORK,
|
374 |
+
'sync_cron' => self::OPTION_LEVEL_NETWORK,
|
375 |
+
'was_plugin_loaded' => self::OPTION_LEVEL_NETWORK,
|
376 |
+
'network_user_id' => self::OPTION_LEVEL_NETWORK,
|
377 |
+
'plugin_upgrade_mode' => self::OPTION_LEVEL_NETWORK,
|
378 |
+
'plugin_downgrade_mode' => self::OPTION_LEVEL_NETWORK,
|
379 |
+
'is_network_connected' => self::OPTION_LEVEL_NETWORK,
|
380 |
/**
|
381 |
+
* Special flag that is used when a super-admin upgrades to the new version of the SDK that supports network level integration, when the connection decision wasn't made for all the sites in the network.
|
|
|
|
|
382 |
*/
|
383 |
+
'is_network_activation' => self::OPTION_LEVEL_NETWORK,
|
384 |
+
'license_migration' => self::OPTION_LEVEL_NETWORK,
|
385 |
|
386 |
// When network activated, then network level.
|
387 |
+
'install_timestamp' => self::OPTION_LEVEL_NETWORK_ACTIVATED,
|
388 |
+
'prev_is_premium' => self::OPTION_LEVEL_NETWORK_ACTIVATED,
|
389 |
+
'require_license_activation' => self::OPTION_LEVEL_NETWORK_ACTIVATED,
|
390 |
|
391 |
// If not network activated OR delegated, then site level.
|
392 |
+
'activation_timestamp' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
393 |
+
'expired_license_notice_shown' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
394 |
+
'is_whitelabeled' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
395 |
+
'last_license_key' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
396 |
+
'last_license_user_id' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
397 |
+
'prev_user_id' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
398 |
+
'sticky_optin_added' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
399 |
+
'uninstall_reason' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
400 |
+
'is_pending_activation' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
401 |
+
'pending_license_key' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
|
|
|
402 |
|
403 |
// Site level options.
|
404 |
+
'is_anonymous' => self::OPTION_LEVEL_SITE,
|
405 |
+
'clone_id' => self::OPTION_LEVEL_SITE,
|
406 |
);
|
407 |
}
|
408 |
|
413 |
* @since 2.0.0
|
414 |
*
|
415 |
* @param string $key
|
416 |
+
* @param int $option_level Since 2.5.1
|
417 |
*
|
418 |
+
* @return bool
|
419 |
*/
|
420 |
+
private function is_multisite_option( $key, $option_level = self::OPTION_LEVEL_UNDEFINED ) {
|
421 |
if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
|
422 |
self::load_network_options_map();
|
423 |
}
|
424 |
|
425 |
+
if (
|
426 |
+
self::OPTION_LEVEL_UNDEFINED === $option_level &&
|
427 |
+
isset( self::$_NETWORK_OPTIONS_MAP[ $key ] )
|
428 |
+
) {
|
429 |
+
$option_level = self::$_NETWORK_OPTIONS_MAP[ $key ];
|
430 |
+
}
|
431 |
+
|
432 |
+
if ( self::OPTION_LEVEL_UNDEFINED === $option_level ) {
|
433 |
// Option not found -> use site level storage.
|
434 |
return false;
|
435 |
}
|
436 |
|
437 |
+
if ( self::OPTION_LEVEL_NETWORK === $option_level ) {
|
438 |
// Option found and set to always use the network level storage on a multisite.
|
439 |
return true;
|
440 |
}
|
441 |
|
442 |
+
if ( self::OPTION_LEVEL_SITE === $option_level ) {
|
443 |
// Option found and set to always use the site level storage on a multisite.
|
444 |
return false;
|
445 |
}
|
448 |
return false;
|
449 |
}
|
450 |
|
451 |
+
if ( self::OPTION_LEVEL_NETWORK_ACTIVATED === $option_level ) {
|
452 |
// Network activated.
|
453 |
return true;
|
454 |
}
|
455 |
|
456 |
+
if (
|
457 |
+
self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED === $option_level &&
|
458 |
+
! $this->_is_delegated_connection
|
459 |
+
) {
|
460 |
// Network activated and not delegated.
|
461 |
return true;
|
462 |
}
|
469 |
*
|
470 |
* @param string $key
|
471 |
* @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).
|
472 |
+
* @param int $option_level Since 2.5.1
|
473 |
*
|
474 |
* @return bool
|
475 |
*/
|
476 |
+
private function should_use_network_storage(
|
477 |
+
$key,
|
478 |
+
$network_level_or_blog_id = null,
|
479 |
+
$option_level = self::OPTION_LEVEL_UNDEFINED
|
480 |
+
) {
|
481 |
if ( ! $this->_is_multisite ) {
|
482 |
// Not a multisite environment.
|
483 |
return false;
|
489 |
}
|
490 |
|
491 |
if ( is_bool( $network_level_or_blog_id ) ) {
|
492 |
+
// Explicitly specified whether it should use the network or blog level storage.
|
493 |
return $network_level_or_blog_id;
|
494 |
}
|
495 |
|
496 |
// Determine which storage to use based on the option.
|
497 |
+
return $this->is_multisite_option( $key, $option_level );
|
498 |
}
|
499 |
|
500 |
/**
|
555 |
}
|
556 |
|
557 |
#endregion
|
558 |
+
}
|
freemius/includes/class-fs-user-lock.php
CHANGED
@@ -10,18 +10,16 @@
|
|
10 |
exit;
|
11 |
}
|
12 |
|
|
|
|
|
13 |
/**
|
14 |
* Class FS_User_Lock
|
15 |
*/
|
16 |
class FS_User_Lock {
|
17 |
/**
|
18 |
-
* @var
|
19 |
-
*/
|
20 |
-
private $_wp_user_id;
|
21 |
-
/**
|
22 |
-
* @var int
|
23 |
*/
|
24 |
-
private $
|
25 |
|
26 |
#--------------------------------------------------------------------------------
|
27 |
#region Singleton
|
@@ -49,10 +47,10 @@
|
|
49 |
#endregion
|
50 |
|
51 |
private function __construct() {
|
52 |
-
$
|
53 |
-
$this->_thread_id = mt_rand( 0, 32000 );
|
54 |
-
}
|
55 |
|
|
|
|
|
56 |
|
57 |
/**
|
58 |
* Try to acquire lock. If the lock is already set or is being acquired by another locker, don't do anything.
|
@@ -65,20 +63,7 @@
|
|
65 |
* @return bool TRUE if successfully acquired lock.
|
66 |
*/
|
67 |
function try_lock( $expiration = 0 ) {
|
68 |
-
|
69 |
-
// Already locked.
|
70 |
-
return false;
|
71 |
-
}
|
72 |
-
|
73 |
-
set_site_transient( "locked_{$this->_wp_user_id}", $this->_thread_id, $expiration );
|
74 |
-
|
75 |
-
if ( $this->has_lock() ) {
|
76 |
-
set_site_transient( "locked_{$this->_wp_user_id}", true, $expiration );
|
77 |
-
|
78 |
-
return true;
|
79 |
-
}
|
80 |
-
|
81 |
-
return false;
|
82 |
}
|
83 |
|
84 |
/**
|
@@ -90,19 +75,7 @@
|
|
90 |
* @param int $expiration
|
91 |
*/
|
92 |
function lock( $expiration = 0 ) {
|
93 |
-
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* Checks if lock is currently acquired.
|
98 |
-
*
|
99 |
-
* @author Vova Feldman (@svovaf)
|
100 |
-
* @since 2.1.0
|
101 |
-
*
|
102 |
-
* @return bool
|
103 |
-
*/
|
104 |
-
function is_locked() {
|
105 |
-
return ( false !== get_site_transient( "locked_{$this->_wp_user_id}" ) );
|
106 |
}
|
107 |
|
108 |
/**
|
@@ -112,15 +85,6 @@
|
|
112 |
* @since 2.1.0
|
113 |
*/
|
114 |
function unlock() {
|
115 |
-
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Checks if lock is currently acquired by the current locker.
|
120 |
-
*
|
121 |
-
* @return bool
|
122 |
-
*/
|
123 |
-
private function has_lock() {
|
124 |
-
return ( $this->_thread_id == get_site_transient( "locked_{$this->_wp_user_id}" ) );
|
125 |
}
|
126 |
}
|
10 |
exit;
|
11 |
}
|
12 |
|
13 |
+
require_once WP_FS__DIR_INCLUDES . '/class-fs-lock.php';
|
14 |
+
|
15 |
/**
|
16 |
* Class FS_User_Lock
|
17 |
*/
|
18 |
class FS_User_Lock {
|
19 |
/**
|
20 |
+
* @var FS_Lock
|
|
|
|
|
|
|
|
|
21 |
*/
|
22 |
+
private $_lock;
|
23 |
|
24 |
#--------------------------------------------------------------------------------
|
25 |
#region Singleton
|
47 |
#endregion
|
48 |
|
49 |
private function __construct() {
|
50 |
+
$current_user_id = Freemius::get_current_wp_user_id();
|
|
|
|
|
51 |
|
52 |
+
$this->_lock = new FS_Lock( "locked_{$current_user_id}" );
|
53 |
+
}
|
54 |
|
55 |
/**
|
56 |
* Try to acquire lock. If the lock is already set or is being acquired by another locker, don't do anything.
|
63 |
* @return bool TRUE if successfully acquired lock.
|
64 |
*/
|
65 |
function try_lock( $expiration = 0 ) {
|
66 |
+
return $this->_lock->try_lock( $expiration );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
|
69 |
/**
|
75 |
* @param int $expiration
|
76 |
*/
|
77 |
function lock( $expiration = 0 ) {
|
78 |
+
$this->_lock->lock( $expiration );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
}
|
80 |
|
81 |
/**
|
85 |
* @since 2.1.0
|
86 |
*/
|
87 |
function unlock() {
|
88 |
+
$this->_lock->unlock();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}
|
90 |
}
|
freemius/includes/customizer/class-fs-customizer-upsell-control.php
CHANGED
@@ -101,11 +101,11 @@
|
|
101 |
}
|
102 |
}
|
103 |
}
|
|
|
|
|
104 |
}
|
105 |
}
|
106 |
|
107 |
-
$this->json['plans'] = $pricing->plans;
|
108 |
-
|
109 |
$this->json['strings'] = array(
|
110 |
'plan' => $this->fs->get_text_x_inline( 'Plan', 'as product pricing plan', 'plan' ),
|
111 |
);
|
101 |
}
|
102 |
}
|
103 |
}
|
104 |
+
|
105 |
+
$this->json['plans'] = $pricing->plans;
|
106 |
}
|
107 |
}
|
108 |
|
|
|
|
|
109 |
$this->json['strings'] = array(
|
110 |
'plan' => $this->fs->get_text_x_inline( 'Plan', 'as product pricing plan', 'plan' ),
|
111 |
);
|
freemius/includes/entities/class-fs-affiliate-terms.php
CHANGED
@@ -84,6 +84,10 @@
|
|
84 |
* @var bool If `true`, allow referrals from any site.
|
85 |
*/
|
86 |
public $is_any_site_allowed;
|
|
|
|
|
|
|
|
|
87 |
|
88 |
#endregion Properties
|
89 |
|
84 |
* @var bool If `true`, allow referrals from any site.
|
85 |
*/
|
86 |
public $is_any_site_allowed;
|
87 |
+
/**
|
88 |
+
* @var string $plugin_title Title of the plugin. This is used in case we are showing affiliate form for a Bundle instead of the `plugin` in context.
|
89 |
+
*/
|
90 |
+
public $plugin_title;
|
91 |
|
92 |
#endregion Properties
|
93 |
|
freemius/includes/entities/class-fs-site.php
CHANGED
@@ -10,6 +10,9 @@
|
|
10 |
exit;
|
11 |
}
|
12 |
|
|
|
|
|
|
|
13 |
class FS_Site extends FS_Scope_Entity {
|
14 |
/**
|
15 |
* @var number
|
@@ -39,10 +42,6 @@
|
|
39 |
* @var string E.g. en-GB
|
40 |
*/
|
41 |
public $language;
|
42 |
-
/**
|
43 |
-
* @var string E.g. UTF-8
|
44 |
-
*/
|
45 |
-
public $charset;
|
46 |
/**
|
47 |
* @var string Platform version (e.g WordPress version).
|
48 |
*/
|
@@ -86,6 +85,8 @@
|
|
86 |
* @author Leo Fajardo (@leorw)
|
87 |
*
|
88 |
* @since 1.2.1.5
|
|
|
|
|
89 |
*
|
90 |
* @var bool
|
91 |
*/
|
@@ -190,7 +191,13 @@
|
|
190 |
// DesktopServer
|
191 |
fs_ends_with( $subdomain, '.dev.cc' ) ||
|
192 |
// Pressable
|
193 |
-
fs_ends_with( $subdomain, '.mystagingwebsite.com' )
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
);
|
195 |
}
|
196 |
|
@@ -223,31 +230,25 @@
|
|
223 |
}
|
224 |
|
225 |
/**
|
226 |
-
* @author
|
227 |
-
* @since 2.0.0
|
228 |
*
|
229 |
* @return bool
|
230 |
*/
|
231 |
-
function
|
232 |
-
return ( true
|
233 |
}
|
234 |
|
235 |
/**
|
236 |
-
* @author
|
237 |
-
* @since
|
238 |
*
|
239 |
-
* @
|
240 |
-
*/
|
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
|
251 |
-
|
|
|
|
|
252 |
}
|
253 |
}
|
10 |
exit;
|
11 |
}
|
12 |
|
13 |
+
/**
|
14 |
+
* @property int $blog_id
|
15 |
+
*/
|
16 |
class FS_Site extends FS_Scope_Entity {
|
17 |
/**
|
18 |
* @var number
|
42 |
* @var string E.g. en-GB
|
43 |
*/
|
44 |
public $language;
|
|
|
|
|
|
|
|
|
45 |
/**
|
46 |
* @var string Platform version (e.g WordPress version).
|
47 |
*/
|
85 |
* @author Leo Fajardo (@leorw)
|
86 |
*
|
87 |
* @since 1.2.1.5
|
88 |
+
* @deprecated Since 2.5.1
|
89 |
+
* @todo Remove after a few releases.
|
90 |
*
|
91 |
* @var bool
|
92 |
*/
|
191 |
// DesktopServer
|
192 |
fs_ends_with( $subdomain, '.dev.cc' ) ||
|
193 |
// Pressable
|
194 |
+
fs_ends_with( $subdomain, '.mystagingwebsite.com' ) ||
|
195 |
+
// WPMU DEV
|
196 |
+
( fs_ends_with( $subdomain, '.tempurl.host' ) || fs_ends_with( $subdomain, '.wpmudev.host' ) ) ||
|
197 |
+
// Vendasta
|
198 |
+
( fs_ends_with( $subdomain, '.websitepro-staging.com' ) || fs_ends_with( $subdomain, '.websitepro.hosting' ) ) ||
|
199 |
+
// InstaWP
|
200 |
+
fs_ends_with( $subdomain, '.instawp.xyz' )
|
201 |
);
|
202 |
}
|
203 |
|
230 |
}
|
231 |
|
232 |
/**
|
233 |
+
* @author Edgar Melkonyan
|
|
|
234 |
*
|
235 |
* @return bool
|
236 |
*/
|
237 |
+
function is_beta() {
|
238 |
+
return ( isset( $this->is_beta ) && true === $this->is_beta );
|
239 |
}
|
240 |
|
241 |
/**
|
242 |
+
* @author Leo Fajardo (@leorw)
|
243 |
+
* @since 2.5.1
|
244 |
*
|
245 |
+
* @param string $site_url
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
*
|
247 |
* @return bool
|
248 |
*/
|
249 |
+
function is_clone( $site_url ) {
|
250 |
+
$clone_install_url = trailingslashit( fs_strip_url_protocol( $this->url ) );
|
251 |
+
|
252 |
+
return ( $clone_install_url !== $site_url );
|
253 |
}
|
254 |
}
|
freemius/includes/entities/class-fs-user.php
CHANGED
@@ -56,7 +56,18 @@
|
|
56 |
return ( isset( $this->is_verified ) && true === $this->is_verified );
|
57 |
}
|
58 |
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
return 'user';
|
61 |
}
|
62 |
}
|
56 |
return ( isset( $this->is_verified ) && true === $this->is_verified );
|
57 |
}
|
58 |
|
59 |
+
/**
|
60 |
+
* @author Leo Fajardo (@leorw)
|
61 |
+
* @since 2.4.2
|
62 |
+
*
|
63 |
+
* @return bool
|
64 |
+
*/
|
65 |
+
function is_beta() {
|
66 |
+
// Return `false` since this is just for backward compatibility.
|
67 |
+
return false;
|
68 |
+
}
|
69 |
+
|
70 |
+
static function get_type() {
|
71 |
return 'user';
|
72 |
}
|
73 |
}
|
freemius/includes/fs-core-functions.php
CHANGED
@@ -756,7 +756,7 @@
|
|
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
|
760 |
elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) {
|
761 |
return 0;
|
762 |
}
|
@@ -770,6 +770,12 @@
|
|
770 |
#region Localization
|
771 |
#--------------------------------------------------------------------------------
|
772 |
|
|
|
|
|
|
|
|
|
|
|
|
|
773 |
if ( ! function_exists( 'fs_text' ) ) {
|
774 |
/**
|
775 |
* Retrieve a translated text by key.
|
@@ -782,12 +788,10 @@
|
|
782 |
*
|
783 |
* @return string
|
784 |
*
|
785 |
-
* @global $
|
786 |
*/
|
787 |
function fs_text( $key, $slug = 'freemius' ) {
|
788 |
-
global $
|
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 ] ) ) {
|
@@ -800,22 +804,6 @@
|
|
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 |
|
@@ -1349,7 +1337,7 @@
|
|
1349 |
function fs_is_plugin_uninstall() {
|
1350 |
return (
|
1351 |
defined( 'WP_UNINSTALL_PLUGIN' ) ||
|
1352 |
-
( 0 < did_action( '
|
1353 |
);
|
1354 |
}
|
1355 |
}
|
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 it's a tie.
|
760 |
elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) {
|
761 |
return 0;
|
762 |
}
|
770 |
#region Localization
|
771 |
#--------------------------------------------------------------------------------
|
772 |
|
773 |
+
global $fs_text_overrides;
|
774 |
+
|
775 |
+
if ( ! isset( $fs_text_overrides ) ) {
|
776 |
+
$fs_text_overrides = array();
|
777 |
+
}
|
778 |
+
|
779 |
if ( ! function_exists( 'fs_text' ) ) {
|
780 |
/**
|
781 |
* Retrieve a translated text by key.
|
788 |
*
|
789 |
* @return string
|
790 |
*
|
791 |
+
* @global $fs_text_overrides
|
792 |
*/
|
793 |
function fs_text( $key, $slug = 'freemius' ) {
|
794 |
+
global $fs_text_overrides;
|
|
|
|
|
795 |
|
796 |
if ( isset( $fs_text_overrides[ $slug ] ) ) {
|
797 |
if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
|
804 |
}
|
805 |
}
|
806 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
807 |
return $key;
|
808 |
}
|
809 |
|
1337 |
function fs_is_plugin_uninstall() {
|
1338 |
return (
|
1339 |
defined( 'WP_UNINSTALL_PLUGIN' ) ||
|
1340 |
+
( 0 < did_action( 'pre_uninstall_plugin' ) )
|
1341 |
);
|
1342 |
}
|
1343 |
}
|
freemius/includes/fs-essential-functions.php
CHANGED
@@ -149,111 +149,21 @@
|
|
149 |
|
150 |
#endregion Core Redirect (copied from BuddyPress) -----------------------------------------
|
151 |
|
152 |
-
if ( ! function_exists( '__fs' ) ) {
|
153 |
-
global $fs_text_overrides;
|
154 |
-
|
155 |
-
if ( ! isset( $fs_text_overrides ) ) {
|
156 |
-
$fs_text_overrides = array();
|
157 |
-
}
|
158 |
-
|
159 |
-
/**
|
160 |
-
* Retrieve a translated text by key.
|
161 |
-
*
|
162 |
-
* @deprecated Use `fs_text()` instead since methods starting with `__` trigger warnings in Php 7.
|
163 |
-
* @todo Remove this method in the future.
|
164 |
-
*
|
165 |
-
* @author Vova Feldman (@svovaf)
|
166 |
-
* @since 1.1.4
|
167 |
-
*
|
168 |
-
* @param string $key
|
169 |
-
* @param string $slug
|
170 |
-
*
|
171 |
-
* @return string
|
172 |
-
*
|
173 |
-
* @global $fs_text, $fs_text_overrides
|
174 |
-
*/
|
175 |
-
function __fs( $key, $slug = 'freemius' ) {
|
176 |
-
_deprecated_function( __FUNCTION__, '2.0.0', 'fs_text()' );
|
177 |
-
|
178 |
-
global $fs_text,
|
179 |
-
$fs_module_info_text,
|
180 |
-
$fs_text_overrides;
|
181 |
-
|
182 |
-
if ( isset( $fs_text_overrides[ $slug ] ) ) {
|
183 |
-
if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
|
184 |
-
return $fs_text_overrides[ $slug ][ $key ];
|
185 |
-
}
|
186 |
-
|
187 |
-
$lower_key = strtolower( $key );
|
188 |
-
if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
|
189 |
-
return $fs_text_overrides[ $slug ][ $lower_key ];
|
190 |
-
}
|
191 |
-
}
|
192 |
-
|
193 |
-
if ( ! isset( $fs_text ) ) {
|
194 |
-
$dir = defined( 'WP_FS__DIR_INCLUDES' ) ?
|
195 |
-
WP_FS__DIR_INCLUDES :
|
196 |
-
dirname( __FILE__ );
|
197 |
-
|
198 |
-
require_once $dir . '/i18n.php';
|
199 |
-
}
|
200 |
-
|
201 |
-
if ( isset( $fs_text[ $key ] ) ) {
|
202 |
-
return $fs_text[ $key ];
|
203 |
-
}
|
204 |
-
|
205 |
-
if ( isset( $fs_module_info_text[ $key ] ) ) {
|
206 |
-
return $fs_module_info_text[ $key ];
|
207 |
-
}
|
208 |
-
|
209 |
-
return $key;
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* Output a translated text by key.
|
214 |
-
*
|
215 |
-
* @deprecated Use `fs_echo()` instead for consistency with `fs_text()`.
|
216 |
-
*
|
217 |
-
* @todo Remove this method in the future.
|
218 |
-
*
|
219 |
-
* @author Vova Feldman (@svovaf)
|
220 |
-
* @since 1.1.4
|
221 |
-
*
|
222 |
-
* @param string $key
|
223 |
-
* @param string $slug
|
224 |
-
*/
|
225 |
-
function _efs( $key, $slug = 'freemius' ) {
|
226 |
-
fs_echo( $key, $slug );
|
227 |
-
}
|
228 |
-
}
|
229 |
-
|
230 |
if ( ! function_exists( 'fs_get_ip' ) ) {
|
231 |
/**
|
232 |
-
* Get
|
233 |
-
|
|
|
|
|
234 |
* @author Vova Feldman (@svovaf)
|
235 |
* @since 1.1.2
|
236 |
*
|
237 |
* @return string|null
|
238 |
*/
|
239 |
function fs_get_ip() {
|
240 |
-
$
|
241 |
-
|
242 |
-
|
243 |
-
'HTTP_X_FORWARDED_FOR',
|
244 |
-
'HTTP_X_FORWARDED',
|
245 |
-
'HTTP_FORWARDED_FOR',
|
246 |
-
'HTTP_FORWARDED',
|
247 |
-
'REMOTE_ADDR',
|
248 |
-
);
|
249 |
-
|
250 |
-
foreach ( $fields as $ip_field ) {
|
251 |
-
if ( ! empty( $_SERVER[ $ip_field ] ) ) {
|
252 |
-
return $_SERVER[ $ip_field ];
|
253 |
-
}
|
254 |
-
}
|
255 |
-
|
256 |
-
return null;
|
257 |
}
|
258 |
}
|
259 |
|
149 |
|
150 |
#endregion Core Redirect (copied from BuddyPress) -----------------------------------------
|
151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
if ( ! function_exists( 'fs_get_ip' ) ) {
|
153 |
/**
|
154 |
+
* Get server IP.
|
155 |
+
*
|
156 |
+
* @since 2.5.1 This method returns the server IP.
|
157 |
+
*
|
158 |
* @author Vova Feldman (@svovaf)
|
159 |
* @since 1.1.2
|
160 |
*
|
161 |
* @return string|null
|
162 |
*/
|
163 |
function fs_get_ip() {
|
164 |
+
return empty( $_SERVER[ 'SERVER_ADDR' ] ) ?
|
165 |
+
null :
|
166 |
+
$_SERVER[ 'SERVER_ADDR' ];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
}
|
168 |
}
|
169 |
|
freemius/includes/fs-plugin-info-dialog.php
CHANGED
@@ -1306,8 +1306,8 @@
|
|
1306 |
<?php endif ?>
|
1307 |
</div>
|
1308 |
</div>
|
1309 |
-
</div>
|
1310 |
<?php endforeach ?>
|
|
|
1311 |
<?php endif ?>
|
1312 |
<?php endif ?>
|
1313 |
<div>
|
1306 |
<?php endif ?>
|
1307 |
</div>
|
1308 |
</div>
|
|
|
1309 |
<?php endforeach ?>
|
1310 |
+
</div>
|
1311 |
<?php endif ?>
|
1312 |
<?php endif ?>
|
1313 |
<div>
|
freemius/includes/managers/class-fs-admin-notice-manager.php
CHANGED
@@ -160,7 +160,10 @@
|
|
160 |
false,
|
161 |
isset( $msg['wp_user_id'] ) ? $msg['wp_user_id'] : null,
|
162 |
! empty( $msg['plugin'] ) ? $msg['plugin'] : null,
|
163 |
-
$is_network_and_blog_admins
|
|
|
|
|
|
|
164 |
);
|
165 |
}
|
166 |
}
|
@@ -224,9 +227,6 @@
|
|
224 |
return;
|
225 |
}
|
226 |
|
227 |
-
|
228 |
-
$show_admin_notices = ( ! $this->is_gutenberg_page() );
|
229 |
-
|
230 |
foreach ( $this->_notices as $id => $msg ) {
|
231 |
if ( isset( $msg['wp_user_id'] ) && is_numeric( $msg['wp_user_id'] ) ) {
|
232 |
if ( get_current_user_id() != $msg['wp_user_id'] ) {
|
@@ -269,7 +269,7 @@
|
|
269 |
$show_notice = call_user_func_array( 'fs_apply_filter', array(
|
270 |
$this->_module_unique_affix,
|
271 |
'show_admin_notice',
|
272 |
-
$show_admin_notices,
|
273 |
$msg
|
274 |
) );
|
275 |
|
@@ -323,6 +323,30 @@
|
|
323 |
return false;
|
324 |
}
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
/**
|
327 |
* Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked.
|
328 |
*
|
@@ -339,6 +363,8 @@
|
|
339 |
* @param string|null $plugin_title
|
340 |
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
|
341 |
* and blog admin pages.
|
|
|
|
|
342 |
*
|
343 |
* @uses add_action()
|
344 |
*/
|
@@ -351,7 +377,9 @@
|
|
351 |
$store_if_sticky = true,
|
352 |
$wp_user_id = null,
|
353 |
$plugin_title = null,
|
354 |
-
$is_network_and_blog_admins = false
|
|
|
|
|
355 |
) {
|
356 |
$notices_type = $this->get_notices_type();
|
357 |
|
@@ -371,14 +399,16 @@
|
|
371 |
}
|
372 |
|
373 |
$message_object = array(
|
374 |
-
'message'
|
375 |
-
'title'
|
376 |
-
'type'
|
377 |
-
'sticky'
|
378 |
-
'id'
|
379 |
-
'manager_id'
|
380 |
-
'plugin'
|
381 |
-
'wp_user_id'
|
|
|
|
|
382 |
);
|
383 |
|
384 |
if ( $is_sticky && $store_if_sticky ) {
|
@@ -393,15 +423,16 @@
|
|
393 |
* @since 1.0.7
|
394 |
*
|
395 |
* @param string|string[] $ids
|
|
|
396 |
*/
|
397 |
-
function remove_sticky( $ids ) {
|
398 |
if ( ! is_array( $ids ) ) {
|
399 |
$ids = array( $ids );
|
400 |
}
|
401 |
|
402 |
foreach ( $ids as $id ) {
|
403 |
// Remove from sticky storage.
|
404 |
-
$this->_sticky_storage->remove( $id );
|
405 |
|
406 |
if ( isset( $this->_notices[ $id ] ) ) {
|
407 |
unset( $this->_notices[ $id ] );
|
@@ -437,14 +468,32 @@
|
|
437 |
* @param string|null $plugin_title
|
438 |
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
|
439 |
* and blog admin pages.
|
|
|
|
|
440 |
*/
|
441 |
-
function add_sticky( $message, $id, $title = '', $type = 'success', $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false ) {
|
442 |
if ( ! empty( $this->_module_unique_affix ) ) {
|
443 |
$message = fs_apply_filter( $this->_module_unique_affix, "sticky_message_{$id}", $message );
|
444 |
$title = fs_apply_filter( $this->_module_unique_affix, "sticky_title_{$id}", $title );
|
445 |
}
|
446 |
|
447 |
-
$this->add( $message, $title, $type, true, $id, true, $wp_user_id, $plugin_title, $is_network_and_blog_admins );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
}
|
449 |
|
450 |
/**
|
@@ -452,9 +501,15 @@
|
|
452 |
*
|
453 |
* @author Vova Feldman (@svovaf)
|
454 |
* @since 1.0.8
|
|
|
|
|
455 |
*/
|
456 |
-
function clear_all_sticky() {
|
457 |
-
$
|
|
|
|
|
|
|
|
|
458 |
}
|
459 |
|
460 |
#--------------------------------------------------------------------------------
|
160 |
false,
|
161 |
isset( $msg['wp_user_id'] ) ? $msg['wp_user_id'] : null,
|
162 |
! empty( $msg['plugin'] ) ? $msg['plugin'] : null,
|
163 |
+
$is_network_and_blog_admins,
|
164 |
+
isset( $msg['dismissible'] ) ?
|
165 |
+
$msg['dismissible'] :
|
166 |
+
null
|
167 |
);
|
168 |
}
|
169 |
}
|
227 |
return;
|
228 |
}
|
229 |
|
|
|
|
|
|
|
230 |
foreach ( $this->_notices as $id => $msg ) {
|
231 |
if ( isset( $msg['wp_user_id'] ) && is_numeric( $msg['wp_user_id'] ) ) {
|
232 |
if ( get_current_user_id() != $msg['wp_user_id'] ) {
|
269 |
$show_notice = call_user_func_array( 'fs_apply_filter', array(
|
270 |
$this->_module_unique_affix,
|
271 |
'show_admin_notice',
|
272 |
+
$this->show_admin_notices(),
|
273 |
$msg
|
274 |
) );
|
275 |
|
323 |
return false;
|
324 |
}
|
325 |
|
326 |
+
/**
|
327 |
+
* Check if admin notices should be shown on page. E.g., we don't want to show notices in the Visual Editor.
|
328 |
+
*
|
329 |
+
* @author Xiaheng Chen (@xhchen)
|
330 |
+
* @since 2.4.2
|
331 |
+
*
|
332 |
+
* @return bool
|
333 |
+
*/
|
334 |
+
function show_admin_notices() {
|
335 |
+
global $pagenow;
|
336 |
+
|
337 |
+
if ( 'about.php' === $pagenow ) {
|
338 |
+
// Don't show admin notices on the About page.
|
339 |
+
return false;
|
340 |
+
}
|
341 |
+
|
342 |
+
if ( $this->is_gutenberg_page() ) {
|
343 |
+
// Don't show admin notices in Gutenberg (visual editor).
|
344 |
+
return false;
|
345 |
+
}
|
346 |
+
|
347 |
+
return true;
|
348 |
+
}
|
349 |
+
|
350 |
/**
|
351 |
* Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked.
|
352 |
*
|
363 |
* @param string|null $plugin_title
|
364 |
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
|
365 |
* and blog admin pages.
|
366 |
+
* @param bool|null $is_dismissible
|
367 |
+
* @param array $data
|
368 |
*
|
369 |
* @uses add_action()
|
370 |
*/
|
377 |
$store_if_sticky = true,
|
378 |
$wp_user_id = null,
|
379 |
$plugin_title = null,
|
380 |
+
$is_network_and_blog_admins = false,
|
381 |
+
$is_dismissible = null,
|
382 |
+
$data = array()
|
383 |
) {
|
384 |
$notices_type = $this->get_notices_type();
|
385 |
|
399 |
}
|
400 |
|
401 |
$message_object = array(
|
402 |
+
'message' => $message,
|
403 |
+
'title' => $title,
|
404 |
+
'type' => $type,
|
405 |
+
'sticky' => $is_sticky,
|
406 |
+
'id' => $id,
|
407 |
+
'manager_id' => $this->_id,
|
408 |
+
'plugin' => ( ! is_null( $plugin_title ) ? $plugin_title : $this->_title ),
|
409 |
+
'wp_user_id' => $wp_user_id,
|
410 |
+
'dismissible' => $is_dismissible,
|
411 |
+
'data' => $data
|
412 |
);
|
413 |
|
414 |
if ( $is_sticky && $store_if_sticky ) {
|
423 |
* @since 1.0.7
|
424 |
*
|
425 |
* @param string|string[] $ids
|
426 |
+
* @param bool $store
|
427 |
*/
|
428 |
+
function remove_sticky( $ids, $store = true ) {
|
429 |
if ( ! is_array( $ids ) ) {
|
430 |
$ids = array( $ids );
|
431 |
}
|
432 |
|
433 |
foreach ( $ids as $id ) {
|
434 |
// Remove from sticky storage.
|
435 |
+
$this->_sticky_storage->remove( $id, $store );
|
436 |
|
437 |
if ( isset( $this->_notices[ $id ] ) ) {
|
438 |
unset( $this->_notices[ $id ] );
|
468 |
* @param string|null $plugin_title
|
469 |
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
|
470 |
* and blog admin pages.
|
471 |
+
* @param bool $is_dimissible
|
472 |
+
* @param array $data
|
473 |
*/
|
474 |
+
function add_sticky( $message, $id, $title = '', $type = 'success', $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false, $is_dimissible = true, $data = array() ) {
|
475 |
if ( ! empty( $this->_module_unique_affix ) ) {
|
476 |
$message = fs_apply_filter( $this->_module_unique_affix, "sticky_message_{$id}", $message );
|
477 |
$title = fs_apply_filter( $this->_module_unique_affix, "sticky_title_{$id}", $title );
|
478 |
}
|
479 |
|
480 |
+
$this->add( $message, $title, $type, true, $id, true, $wp_user_id, $plugin_title, $is_network_and_blog_admins, $is_dimissible, $data );
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Retrieves the data of an sticky notice.
|
485 |
+
*
|
486 |
+
* @author Leo Fajardo (@leorw)
|
487 |
+
* @since 2.4.3
|
488 |
+
*
|
489 |
+
* @param string $id Message ID.
|
490 |
+
*
|
491 |
+
* @return array|null
|
492 |
+
*/
|
493 |
+
function get_sticky( $id ) {
|
494 |
+
return isset( $this->_sticky_storage->{$id} ) ?
|
495 |
+
$this->_sticky_storage->{$id} :
|
496 |
+
null;
|
497 |
}
|
498 |
|
499 |
/**
|
501 |
*
|
502 |
* @author Vova Feldman (@svovaf)
|
503 |
* @since 1.0.8
|
504 |
+
*
|
505 |
+
* @param bool $is_temporary @since 2.5.1
|
506 |
*/
|
507 |
+
function clear_all_sticky( $is_temporary = false ) {
|
508 |
+
if ( $is_temporary ) {
|
509 |
+
$this->_notices = array();
|
510 |
+
} else {
|
511 |
+
$this->_sticky_storage->clear_all();
|
512 |
+
}
|
513 |
}
|
514 |
|
515 |
#--------------------------------------------------------------------------------
|
freemius/includes/managers/class-fs-clone-manager.php
ADDED
@@ -0,0 +1,1660 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* @author Leo Fajardo (@leorw)
|
7 |
+
* @since 2.5.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Manages the detection of clones and provides the logged-in WordPress user with options for manually resolving them.
|
16 |
+
*
|
17 |
+
* @since 2.5.0
|
18 |
+
*
|
19 |
+
* @property int $clone_identification_timestamp
|
20 |
+
* @property int $temporary_duplicate_mode_selection_timestamp
|
21 |
+
* @property int $temporary_duplicate_notice_shown_timestamp
|
22 |
+
* @property string $request_handler_id
|
23 |
+
* @property int $request_handler_timestamp
|
24 |
+
* @property int $request_handler_retries_count
|
25 |
+
* @property bool $hide_manual_resolution
|
26 |
+
* @property array $new_blog_install_map
|
27 |
+
*/
|
28 |
+
class FS_Clone_Manager {
|
29 |
+
/**
|
30 |
+
* @var FS_Option_Manager
|
31 |
+
*/
|
32 |
+
private $_storage;
|
33 |
+
/**
|
34 |
+
* @var FS_Option_Manager
|
35 |
+
*/
|
36 |
+
private $_network_storage;
|
37 |
+
/**
|
38 |
+
* @var FS_Admin_Notices
|
39 |
+
*/
|
40 |
+
private $_notices;
|
41 |
+
/**
|
42 |
+
* @var FS_Logger
|
43 |
+
*/
|
44 |
+
protected $_logger;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var int 3 minutes
|
48 |
+
*/
|
49 |
+
const CLONE_RESOLUTION_MAX_EXECUTION_TIME = 180;
|
50 |
+
/**
|
51 |
+
* @var int
|
52 |
+
*/
|
53 |
+
const CLONE_RESOLUTION_MAX_RETRIES = 3;
|
54 |
+
/**
|
55 |
+
* @var int
|
56 |
+
*/
|
57 |
+
const TEMPORARY_DUPLICATE_PERIOD = WP_FS__TIME_WEEK_IN_SEC * 2;
|
58 |
+
/**
|
59 |
+
* @var string
|
60 |
+
*/
|
61 |
+
const OPTION_NAME = 'clone_resolution';
|
62 |
+
/**
|
63 |
+
* @var string
|
64 |
+
*/
|
65 |
+
const OPTION_MANAGER_NAME = 'clone_management';
|
66 |
+
/**
|
67 |
+
* @var string
|
68 |
+
*/
|
69 |
+
const OPTION_TEMPORARY_DUPLICATE = 'temporary_duplicate';
|
70 |
+
/**
|
71 |
+
* @var string
|
72 |
+
*/
|
73 |
+
const OPTION_LONG_TERM_DUPLICATE = 'long_term_duplicate';
|
74 |
+
/**
|
75 |
+
* @var string
|
76 |
+
*/
|
77 |
+
const OPTION_NEW_HOME = 'new_home';
|
78 |
+
|
79 |
+
#--------------------------------------------------------------------------------
|
80 |
+
#region Singleton
|
81 |
+
#--------------------------------------------------------------------------------
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @var FS_Clone_Manager
|
85 |
+
*/
|
86 |
+
private static $_instance;
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @return FS_Clone_Manager
|
90 |
+
*/
|
91 |
+
static function instance() {
|
92 |
+
if ( ! isset( self::$_instance ) ) {
|
93 |
+
self::$_instance = new self();
|
94 |
+
}
|
95 |
+
|
96 |
+
return self::$_instance;
|
97 |
+
}
|
98 |
+
|
99 |
+
#endregion
|
100 |
+
|
101 |
+
private function __construct() {
|
102 |
+
$this->_storage = FS_Option_Manager::get_manager( WP_FS___OPTION_PREFIX . self::OPTION_MANAGER_NAME, true );
|
103 |
+
$this->_network_storage = FS_Option_Manager::get_manager( WP_FS___OPTION_PREFIX . self::OPTION_MANAGER_NAME, true, true );
|
104 |
+
|
105 |
+
$this->maybe_migrate_options();
|
106 |
+
|
107 |
+
$this->_notices = FS_Admin_Notices::instance( 'global_clone_resolution_notices', '', '', true );
|
108 |
+
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . '_clone_manager', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Migrate clone resolution options from 2.5.0 array-based structure, to a new flat structure.
|
113 |
+
*
|
114 |
+
* The reason this logic is not in a separate migration script is that we want to be 100% sure data is migrated before any execution of clone logic.
|
115 |
+
*
|
116 |
+
* @todo Delete this one in the future.
|
117 |
+
*/
|
118 |
+
private function maybe_migrate_options() {
|
119 |
+
$storages = array(
|
120 |
+
$this->_storage,
|
121 |
+
$this->_network_storage
|
122 |
+
);
|
123 |
+
|
124 |
+
foreach ( $storages as $storage ) {
|
125 |
+
$clone_data = $storage->get_option( self::OPTION_NAME );
|
126 |
+
if ( is_array( $clone_data ) && ! empty( $clone_data ) ) {
|
127 |
+
foreach ( $clone_data as $key => $val ) {
|
128 |
+
if ( ! is_null( $val ) ) {
|
129 |
+
$storage->set_option( $key, $val );
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
$storage->unset_option( self::OPTION_NAME, true );
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* @author Leo Fajardo (@leorw)
|
140 |
+
* @since 2.5.0
|
141 |
+
*/
|
142 |
+
function _init() {
|
143 |
+
if ( is_admin() ) {
|
144 |
+
if ( Freemius::is_admin_post() ) {
|
145 |
+
add_action( 'admin_post_fs_clone_resolution', array( $this, '_handle_clone_resolution' ) );
|
146 |
+
}
|
147 |
+
|
148 |
+
if ( Freemius::is_ajax() ) {
|
149 |
+
Freemius::add_ajax_action_static( 'handle_clone_resolution', array( $this, '_clone_resolution_action_ajax_handler' ) );
|
150 |
+
} else {
|
151 |
+
if (
|
152 |
+
empty( $this->get_clone_identification_timestamp() ) &&
|
153 |
+
(
|
154 |
+
! fs_is_network_admin() ||
|
155 |
+
! ( $this->is_clone_resolution_options_notice_shown() || $this->is_temporary_duplicate_notice_shown() )
|
156 |
+
)
|
157 |
+
) {
|
158 |
+
$this->hide_clone_admin_notices();
|
159 |
+
} else if ( ! Freemius::is_cron() && ! Freemius::is_admin_post() ) {
|
160 |
+
$this->try_resolve_clone_automatically();
|
161 |
+
$this->maybe_show_clone_admin_notice();
|
162 |
+
|
163 |
+
add_action( 'admin_footer', array( $this, '_add_clone_resolution_javascript' ) );
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Retrieves the timestamp that was stored when a clone was identified.
|
171 |
+
*
|
172 |
+
* @return int|null
|
173 |
+
*/
|
174 |
+
function get_clone_identification_timestamp() {
|
175 |
+
return $this->get_option( 'clone_identification_timestamp', true );
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* @author Leo Fajardo (@leorw)
|
180 |
+
* @since 2.5.1
|
181 |
+
*
|
182 |
+
* @param string $sdk_last_version
|
183 |
+
*/
|
184 |
+
function maybe_update_clone_resolution_support_flag( $sdk_last_version ) {
|
185 |
+
if ( null !== $this->hide_manual_resolution ) {
|
186 |
+
return;
|
187 |
+
}
|
188 |
+
|
189 |
+
$this->hide_manual_resolution = (
|
190 |
+
! empty( $sdk_last_version ) &&
|
191 |
+
version_compare( $sdk_last_version, '2.5.0', '<' )
|
192 |
+
);
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Stores the time when a clone was identified.
|
197 |
+
*/
|
198 |
+
function store_clone_identification_timestamp() {
|
199 |
+
$this->clone_identification_timestamp = time();
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Retrieves the timestamp for the temporary duplicate mode's expiration.
|
204 |
+
*
|
205 |
+
* @return int
|
206 |
+
*/
|
207 |
+
function get_temporary_duplicate_expiration_timestamp() {
|
208 |
+
$temporary_duplicate_mode_start_timestamp = $this->was_temporary_duplicate_mode_selected() ?
|
209 |
+
$this->temporary_duplicate_mode_selection_timestamp :
|
210 |
+
$this->get_clone_identification_timestamp();
|
211 |
+
|
212 |
+
return ( $temporary_duplicate_mode_start_timestamp + self::TEMPORARY_DUPLICATE_PERIOD );
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Determines if the SDK should handle clones. The SDK handles clones only up to 3 times with 3 min interval.
|
217 |
+
*
|
218 |
+
* @return bool
|
219 |
+
*/
|
220 |
+
private function should_handle_clones() {
|
221 |
+
if ( ! isset( $this->request_handler_timestamp ) ) {
|
222 |
+
return true;
|
223 |
+
}
|
224 |
+
|
225 |
+
if ( $this->request_handler_retries_count >= self::CLONE_RESOLUTION_MAX_RETRIES ) {
|
226 |
+
return false;
|
227 |
+
}
|
228 |
+
|
229 |
+
// Give the logic that handles clones enough time to finish (it is given 3 minutes for now).
|
230 |
+
return ( time() > ( $this->request_handler_timestamp + self::CLONE_RESOLUTION_MAX_EXECUTION_TIME ) );
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* @author Leo Fajardo (@leorw)
|
235 |
+
* @since 2.5.1
|
236 |
+
*
|
237 |
+
* @return bool
|
238 |
+
*/
|
239 |
+
function should_hide_manual_resolution() {
|
240 |
+
return ( true === $this->hide_manual_resolution );
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Executes the clones handler logic if it should be executed, i.e., based on the return value of the should_handle_clones() method.
|
245 |
+
*
|
246 |
+
* @author Leo Fajardo (@leorw)
|
247 |
+
* @since 2.5.0
|
248 |
+
*/
|
249 |
+
function maybe_run_clone_resolution() {
|
250 |
+
if ( ! $this->should_handle_clones() ) {
|
251 |
+
return;
|
252 |
+
}
|
253 |
+
|
254 |
+
$this->request_handler_retries_count = isset( $this->request_handler_retries_count ) ?
|
255 |
+
( $this->request_handler_retries_count + 1 ) :
|
256 |
+
1;
|
257 |
+
|
258 |
+
$this->request_handler_timestamp = time();
|
259 |
+
|
260 |
+
$handler_id = ( rand() . microtime() );
|
261 |
+
$this->request_handler_id = $handler_id;
|
262 |
+
|
263 |
+
// Add cookies to trigger request with the same user access permissions.
|
264 |
+
$cookies = array();
|
265 |
+
foreach ( $_COOKIE as $name => $value ) {
|
266 |
+
$cookies[] = new WP_Http_Cookie( array(
|
267 |
+
'name' => $name,
|
268 |
+
'value' => $value,
|
269 |
+
) );
|
270 |
+
}
|
271 |
+
|
272 |
+
wp_remote_post(
|
273 |
+
admin_url( 'admin-post.php' ),
|
274 |
+
array(
|
275 |
+
'method' => 'POST',
|
276 |
+
'body' => array(
|
277 |
+
'action' => 'fs_clone_resolution',
|
278 |
+
'handler_id' => $handler_id,
|
279 |
+
),
|
280 |
+
'timeout' => 0.01,
|
281 |
+
'blocking' => false,
|
282 |
+
'sslverify' => false,
|
283 |
+
'cookies' => $cookies,
|
284 |
+
)
|
285 |
+
);
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Executes the clones handler logic.
|
290 |
+
*
|
291 |
+
* @author Leo Fajardo (@leorw)
|
292 |
+
* @since 2.5.0
|
293 |
+
*/
|
294 |
+
function _handle_clone_resolution() {
|
295 |
+
$handler_id = fs_request_get( 'handler_id' );
|
296 |
+
|
297 |
+
if ( empty( $handler_id ) ) {
|
298 |
+
return;
|
299 |
+
}
|
300 |
+
|
301 |
+
if (
|
302 |
+
! isset( $this->request_handler_id ) ||
|
303 |
+
$this->request_handler_id !== $handler_id
|
304 |
+
) {
|
305 |
+
return;
|
306 |
+
}
|
307 |
+
|
308 |
+
if ( ! $this->try_automatic_resolution() ) {
|
309 |
+
$this->clear_temporary_duplicate_notice_shown_timestamp();
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
#--------------------------------------------------------------------------------
|
314 |
+
#region Automatic Clone Resolution
|
315 |
+
#--------------------------------------------------------------------------------
|
316 |
+
|
317 |
+
/**
|
318 |
+
* @var array All installs cache.
|
319 |
+
*/
|
320 |
+
|