| @@ -1,77 +1,133 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace WPIDE\App\Classes; |
| 4 | 4 | |
| 5 | -use WPIDE\App\App ; | |
| 6 | -use const WPIDE\Constants\ASSETS_DIR ; | |
| 7 | -use const WPIDE\Constants\ASSETS_URL ; | |
| 8 | -use const WPIDE\Constants\AUTHOR ; | |
| 9 | -use const WPIDE\Constants\DIR ; | |
| 10 | -use const WPIDE\Constants\FS_ID ; | |
| 11 | -use const WPIDE\Constants\FS_KEY ; | |
| 12 | -use const WPIDE\Constants\GTM_ID ; | |
| 13 | -use const WPIDE\Constants\NAME ; | |
| 14 | -use const WPIDE\Constants\SLUG ; | |
| 15 | -use const WPIDE\Constants\VERSION ; | |
| 16 | -class Freemius | |
| 17 | -{ | |
| 18 | - public static $fs ; | |
| 19 | - public static $loaded = false ; | |
| 5 | +use Freemius_Api; | |
| 6 | +use WPIDE\App\App; | |
| 7 | +use const WPIDE\Constants\ASSETS_DIR; | |
| 8 | +use const WPIDE\Constants\ASSETS_URL; | |
| 9 | +use const WPIDE\Constants\AUTHOR; | |
| 10 | +use const WPIDE\Constants\DIR; | |
| 11 | +use const WPIDE\Constants\FS_ID; | |
| 12 | +use const WPIDE\Constants\FS_KEY; | |
| 13 | +use const WPIDE\Constants\GTM_ID; | |
| 14 | +use const WPIDE\Constants\NAME; | |
| 15 | +use const WPIDE\Constants\SLUG; | |
| 16 | +use const WPIDE\Constants\VERSION; | |
| 17 | +class Freemius { | |
| 18 | + private const RESERVED_PRICING_REQUEST_PARAMETERS = [ | |
| 19 | + 'action', | |
| 20 | + 'bundle_id', | |
| 21 | + 'contact_url', | |
| 22 | + 'disable_single_package', | |
| 23 | + 'fs_wp_endpoint_url', | |
| 24 | + 'home_url', | |
| 25 | + 'is_production', | |
| 26 | + 'license', | |
| 27 | + 'menu_slug', | |
| 28 | + 'mode', | |
| 29 | + 'module_id', | |
| 30 | + 'plugin_icon', | |
| 31 | + 'plugin_id', | |
| 32 | + 'plugin_public_key', | |
| 33 | + 'plugin_version', | |
| 34 | + 'pricing_action', | |
| 35 | + 'request_handler_url', | |
| 36 | + 's_ctx_id', | |
| 37 | + 's_ctx_secure', | |
| 38 | + 's_ctx_ts', | |
| 39 | + 's_ctx_type', | |
| 40 | + 'sandbox', | |
| 41 | + 'security', | |
| 42 | + 'selector', | |
| 43 | + 'show_annual_in_monthly', | |
| 44 | + 'unique_affix' | |
| 45 | + ]; | |
| 46 | + | |
| 47 | + public static $fs; | |
| 48 | + | |
| 49 | + public static $api; | |
| 50 | + | |
| 51 | + public static $loaded = false; | |
| 52 | + | |
| 20 | 53 | /** |
| 21 | 54 | * @throws \Freemius_Exception |
| 22 | 55 | */ |
| 23 | - public static function init() | |
| 24 | - { | |
| 25 | - | |
| 56 | + public static function init() { | |
| 26 | 57 | if ( !isset( self::$fs ) ) { |
| 58 | + self::sanitizePricingRequest(); | |
| 59 | + if ( !defined( 'WP_FS__PRODUCT_' . FS_ID . '_MULTISITE' ) ) { | |
| 60 | + define( 'WP_FS__PRODUCT_' . FS_ID . '_MULTISITE', true ); | |
| 61 | + } | |
| 27 | 62 | // Init Freemius SDK. |
| 28 | 63 | require_once DIR . 'freemius/start.php'; |
| 29 | 64 | self::$fs = fs_dynamic_init( array( |
| 30 | - 'id' => FS_ID, | |
| 31 | - 'slug' => SLUG, | |
| 32 | - 'premium_slug' => SLUG . '-pro', | |
| 33 | - 'type' => 'plugin', | |
| 34 | - 'public_key' => FS_KEY, | |
| 35 | - 'is_premium' => false, | |
| 36 | - 'premium_suffix' => 'Pro', | |
| 37 | - 'has_addons' => false, | |
| 38 | - 'has_paid_plans' => true, | |
| 39 | - 'trial' => array( | |
| 40 | - 'days' => 14, | |
| 41 | - 'is_require_payment' => true, | |
| 42 | - ), | |
| 43 | - 'menu' => array( | |
| 44 | - 'slug' => SLUG, | |
| 45 | - ), | |
| 46 | - 'is_live' => true, | |
| 65 | + 'id' => FS_ID, | |
| 66 | + 'slug' => SLUG, | |
| 67 | + 'premium_slug' => SLUG . '-pro', | |
| 68 | + 'type' => 'plugin', | |
| 69 | + 'public_key' => FS_KEY, | |
| 70 | + 'is_premium' => false, | |
| 71 | + 'premium_suffix' => 'Pro', | |
| 72 | + 'has_addons' => false, | |
| 73 | + 'has_paid_plans' => true, | |
| 74 | + 'trial' => array( | |
| 75 | + 'days' => 14, | |
| 76 | + 'is_require_payment' => true, | |
| 77 | + ), | |
| 78 | + 'menu' => array( | |
| 79 | + 'slug' => SLUG, | |
| 80 | + 'support' => false, | |
| 81 | + 'affiliation' => false, | |
| 82 | + 'network' => true, | |
| 83 | + ), | |
| 84 | + 'is_live' => true, | |
| 85 | + 'is_org_compliant' => true, | |
| 47 | 86 | ) ); |
| 48 | - self::$fs->add_action( 'connect/before', [ __CLASS__, 'beforeConnectBox' ] ); | |
| 49 | - self::$fs->add_action( 'connect/after', [ __CLASS__, 'afterConnectBox' ] ); | |
| 50 | - self::$fs->add_filter( 'checkout/purchaseCompleted', [ __CLASS__, 'afterPurchaseJs' ] ); | |
| 51 | - self::$fs->add_filter( 'templates/checkout.php', [ __CLASS__, 'checkoutGtmScript' ] ); | |
| 52 | - self::$fs->add_filter( 'freemius_pricing_js_path', [ __CLASS__, 'pricingJsPath' ] ); | |
| 53 | - self::$fs->add_filter( 'plugin_icon', [ __CLASS__, 'pluginIcon' ] ); | |
| 87 | + $GLOBALS['wpide_fs'] = self::$fs; | |
| 88 | + self::$fs->add_action( 'connect/before', [__CLASS__, 'beforeConnectBox'] ); | |
| 89 | + self::$fs->add_action( 'connect/after', [__CLASS__, 'afterConnectBox'] ); | |
| 90 | + self::$fs->add_filter( 'checkout/purchaseCompleted', [__CLASS__, 'afterPurchaseJs'] ); | |
| 91 | + self::$fs->add_filter( 'templates/checkout.php', [__CLASS__, 'checkoutGtmScript'] ); | |
| 92 | + self::$fs->add_filter( 'freemius_pricing_js_path', [__CLASS__, 'pricingJsPath'] ); | |
| 93 | + self::$fs->add_filter( 'plugin_icon', [__CLASS__, 'pluginIcon'] ); | |
| 54 | 94 | self::$fs->add_filter( 'hide_account_tabs', '__return_true' ); |
| 55 | 95 | self::$fs->add_filter( 'hide_freemius_powered_by', '__return_true' ); |
| 56 | 96 | self::$fs->add_filter( 'hide_billing_and_payments_info', '__return_true' ); |
| 57 | - add_action( 'admin_enqueue_scripts', [ __CLASS__, 'admin_enqueue_scripts' ] ); | |
| 97 | + self::$fs->add_action( 'plugins_loaded', [__CLASS__, 'override_freemius_strings'] ); | |
| 98 | + add_action( 'admin_enqueue_scripts', [__CLASS__, 'admin_enqueue_scripts'] ); | |
| 58 | 99 | self::$loaded = true; |
| 59 | 100 | // Signal that SDK was initiated. |
| 60 | 101 | do_action( 'wpide_fs_loaded' ); |
| 61 | 102 | } |
| 62 | - | |
| 63 | 103 | } |
| 64 | - | |
| 65 | - public static function admin_enqueue_scripts() | |
| 66 | - { | |
| 104 | + | |
| 105 | + /** | |
| 106 | + * Prevent request parameters from overriding trusted pricing-page config. | |
| 107 | + */ | |
| 108 | + public static function sanitizePricingRequest() : void { | |
| 109 | + // Only sanitize when rendering the pricing page — never on admin-ajax, | |
| 110 | + // where the pricing JS legitimately passes these same params (incl. `action`). | |
| 111 | + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + $page = ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '' ); | |
| 115 | + if ( SLUG . '-pricing' !== $page ) { | |
| 116 | + return; | |
| 117 | + } | |
| 118 | + foreach ( self::RESERVED_PRICING_REQUEST_PARAMETERS as $parameter ) { | |
| 119 | + unset($_GET[$parameter], $_REQUEST[$parameter]); | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + public static function admin_enqueue_scripts() { | |
| 67 | 124 | if ( App::instance()->isFreemiusScreen() ) { |
| 68 | 125 | self::freemius_custom_styles(); |
| 69 | 126 | } |
| 70 | 127 | } |
| 71 | - | |
| 72 | - public static function freemius_custom_styles() | |
| 73 | - { | |
| 128 | + | |
| 129 | + public static function freemius_custom_styles() { | |
| 74 | 130 | wp_enqueue_style( |
| 75 | 131 | SLUG . '-fs-connect', |
| 76 | 132 | ASSETS_URL . 'css/freemius/freemius.css', |
| 77 | 133 | [], |
| @@ -77,11 +133,10 @@ | ||
| 77 | 133 | [], |
| 78 | 134 | VERSION |
| 79 | 135 | ); |
| 80 | 136 | } |
| 81 | - | |
| 82 | - public static function beforeConnectBox() | |
| 83 | - { | |
| 137 | + | |
| 138 | + public static function beforeConnectBox() { | |
| 84 | 139 | wp_enqueue_style( |
| 85 | 140 | SLUG . '-fs-connect', |
| 86 | 141 | ASSETS_URL . 'css/freemius/freemius.css', |
| 87 | 142 | [], |
| @@ -86,18 +141,16 @@ | ||
| 86 | 141 | ASSETS_URL . 'css/freemius/freemius.css', |
| 87 | 142 | [], |
| 88 | 143 | VERSION |
| 89 | 144 | ); |
| 90 | - echo '<div id="fs-connect-wrap">' ; | |
| 145 | + echo '<div id="fs-connect-wrap">'; | |
| 91 | 146 | } |
| 92 | - | |
| 93 | - public static function afterConnectBox() | |
| 94 | - { | |
| 95 | - echo '</div>' ; | |
| 147 | + | |
| 148 | + public static function afterConnectBox() { | |
| 149 | + echo '</div>'; | |
| 96 | 150 | } |
| 97 | - | |
| 98 | - public static function afterPurchaseJs() : string | |
| 99 | - { | |
| 151 | + | |
| 152 | + public static function afterPurchaseJs() : string { | |
| 100 | 153 | return 'function ( data ) { |
| 101 | 154 | |
| 102 | 155 | /** |
| 103 | 156 | * Since the user just entered their personal & billing information, agreed to the TOS & privacy, |
| @@ -142,31 +195,74 @@ | ||
| 142 | 195 | } |
| 143 | 196 | }); |
| 144 | 197 | }'; |
| 145 | 198 | } |
| 146 | - | |
| 147 | - public static function checkoutGtmScript( $html ) : string | |
| 148 | - { | |
| 199 | + | |
| 200 | + public static function checkoutGtmScript( $html ) : string { | |
| 149 | 201 | return "\n <script>window.dataLayer = window.dataLayer || [];</script>\n <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\n new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\n j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\n 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\n })(window,document,'script','dataLayer', '" . GTM_ID . "');</script>\n " . $html; |
| 150 | 202 | } |
| 151 | - | |
| 152 | - public static function pricingJsPath() : string | |
| 153 | - { | |
| 203 | + | |
| 204 | + public static function pricingJsPath() : string { | |
| 154 | 205 | return ASSETS_DIR . 'pricing/freemius-pricing.js'; |
| 155 | 206 | } |
| 156 | - | |
| 157 | - public static function pluginIcon() : string | |
| 158 | - { | |
| 207 | + | |
| 208 | + public static function pluginIcon() : string { | |
| 159 | 209 | return ASSETS_DIR . 'img/icon.png'; |
| 160 | 210 | } |
| 161 | - | |
| 162 | - public static function sdk() | |
| 163 | - { | |
| 211 | + | |
| 212 | + /** | |
| 213 | + * Add license dialog boxes | |
| 214 | + * | |
| 215 | + * @since 1.0.0 | |
| 216 | + */ | |
| 217 | + public static function addLicenseActivationDialogBox() { | |
| 218 | + if ( !did_action( SLUG . '_license_activation_dialog_added' ) && !App::instance()->isFreemiusScreen( 'account' ) ) { | |
| 219 | + self::sdk()->_add_license_activation_dialog_box(); | |
| 220 | + fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); | |
| 221 | + do_action( SLUG . '_license_activation_dialog_added' ); | |
| 222 | + } | |
| 223 | + } | |
| 224 | + | |
| 225 | + public static function showSubmenus() : bool { | |
| 226 | + $is_activation_mode = self::sdk()->is_activation_mode(); | |
| 227 | + if ( $is_activation_mode ) { | |
| 228 | + $show_submenus = false; | |
| 229 | + } else { | |
| 230 | + if ( fs_is_network_admin() ) { | |
| 231 | + /** | |
| 232 | + * Add submenu items or action links to network level when plugin was network activated and the super | |
| 233 | + * admin did NOT delegate the connection of all sites to site admins. | |
| 234 | + */ | |
| 235 | + $show_submenus = App::instance()->isNetworkActive() && (WP_FS__SHOW_NETWORK_EVEN_WHEN_DELEGATED || !self::sdk()->is_network_delegated_connection()); | |
| 236 | + } else { | |
| 237 | + $show_submenus = !App::instance()->isNetworkActive() || self::sdk()->is_delegated_connection(); | |
| 238 | + } | |
| 239 | + } | |
| 240 | + return $show_submenus; | |
| 241 | + } | |
| 242 | + | |
| 243 | + public static function showUpgradeLink() : bool { | |
| 244 | + $show_submenus = self::showSubmenus(); | |
| 245 | + $is_activation_mode = self::sdk()->is_activation_mode(); | |
| 246 | + $add_upgrade_link = ($show_submenus || $is_activation_mode && self::sdk()->is_only_premium()) && !self::sdk()->is_whitelabeled(); | |
| 247 | + return $add_upgrade_link && self::sdk()->is_pricing_page_visible() && self::sdk()->is_submenu_item_visible( 'pricing' ); | |
| 248 | + } | |
| 249 | + | |
| 250 | + public static function showTrialLink() : bool { | |
| 251 | + return self::sdk()->apply_filters( 'show_trial', true ) && self::sdk()->has_trial_plan() && !self::sdk()->is_trial_utilized(); | |
| 252 | + } | |
| 253 | + | |
| 254 | + public static function sdk() : \Freemius { | |
| 164 | 255 | return self::$fs; |
| 165 | 256 | } |
| 166 | - | |
| 167 | - public static function loaded() | |
| 168 | - { | |
| 257 | + | |
| 258 | + public static function loaded() : bool { | |
| 169 | 259 | return self::$loaded; |
| 170 | 260 | } |
| 171 | 261 | |
| 172 | -} | |
| 262 | + public static function override_freemius_strings() : void { | |
| 263 | + self::$fs->override_i18n( array( | |
| 264 | + 'contact-us' => __( 'Support', 'wpide' ), | |
| 265 | + ) ); | |
| 266 | + } | |
| 267 | + | |
| 268 | +} | |