--- a/form-vibes/form-vibes.php
+++ b/form-vibes/form-vibes.php
@@ -1,35 +1,84 @@
<?php
-/*
-Plugin Name: Form Vibes
-Plugin URI: https://formvibes.com
-Description: Lead Management and Graphical Reports for Elementor Pro, Contact Form 7 & Caldera form submissions.
-Author: WPVibes
-Version: 1.4.13
-Author URI: https://wpvibes.com/
-Text Domain: wpv-fv
-License: GPLv2
-*/
-if ( !defined( 'ABSPATH' ) ) {
- exit;
- // Exit if accessed directly
+/**
+ * Plugin Name: Form Vibes
+ * Plugin URI: https://formvibes.com
+ * Description: Lead Management and Graphical Reports for Elementor Pro, Contact Form 7 & Caldera form submissions.
+ * Author: WPVibes
+ * Version: 1.5.0
+ * Author URI: https://wpvibes.com/
+ * Text Domain: wpv-fv
+ * License: GPLv2
+ * Domain Path: /languages
+ * Requires at least: 5.0
+ * Requires PHP: 7.4
+ *
+ * @fs_premium_only inc/pro, assets/css/pro, assets/script/pro, assets/dist/pro
+ */
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit; // Exit if accessed directly
+}
+
+if ( ! defined( 'WPV_FV__PATH' ) ) {
+ define( 'WPV_FV__VERSION', '1.5.0' );
+ // recommended pro version for free
+ // define( 'WPV_FV__PRO_RECOMMENDED_VERSION', '0.5' );
+ define( 'WPV_FV__URL', plugins_url( '/', __FILE__ ) );
+ define( 'WPV_FV__PATH', plugin_dir_path( __FILE__ ) );
+ define( 'WPV_FV_PLUGIN_BASE', plugin_basename( __FILE__ ) );
+
+ if ( ! defined( 'WPV_PRO_FV_VERSION' ) ) {
+ // maintain
+ define( 'WPV_PRO_FV_VERSION', '1.5.0' );
+ define( 'WPV_FV_MIN_VERSION', '1.3.6' );
+ }
}
-if ( !defined( 'WPV_FV__PATH' ) ) {
- define( 'WPV_FV__VERSION', '1.4.13' );
- // recommended pro version for free
- // define( 'WPV_FV__PRO_RECOMMENDED_VERSION', '0.5' );
- define( 'WPV_FV__URL', plugins_url( '/', __FILE__ ) );
- define( 'WPV_FV__PATH', plugin_dir_path( __FILE__ ) );
- define( 'WPV_FV_PLUGIN_BASE', plugin_basename( __FILE__ ) );
- if ( !defined( 'WPV_PRO_FV_VERSION' ) ) {
- // maintain
- define( 'WPV_PRO_FV_VERSION', '1.4.13' );
- define( 'WPV_FV_MIN_VERSION', '1.3.6' );
- }
+
+if ( ! function_exists( 'wpv_fv' ) ) {
+ // Create a helper function for easy SDK access.
+ function wpv_fv() {
+ global $wpv_fv;
+ if ( ! isset( $wpv_fv ) ) {
+ // Include Freemius SDK.
+ require_once dirname( __FILE__ ) . '/freemius/start.php';
+ $wpv_fv = fs_dynamic_init(
+ [
+ 'id' => '4666',
+ 'slug' => 'form-vibes',
+ 'premium_slug' => 'form-vibes-pro',
+ 'type' => 'plugin',
+ 'public_key' => 'pk_321780b7f1d1ee45009cf6da38431',
+ 'is_premium' => true,
+ 'premium_suffix' => 'Pro',
+ // If your plugin is a serviceware, set this option to false.
+ 'has_premium_version' => true,
+ 'has_addons' => false,
+ 'has_paid_plans' => true,
+ 'menu' => [
+ 'slug' => 'fv-leads',
+ 'first-path' => 'admin.php?page=fv-db-settings',
+ 'support' => false,
+ ],
+ ]
+ );
+ }
+ return $wpv_fv;
+ }
+ // Init Freemius.
+ wpv_fv();
+ // Signal that SDK was initiated.
+ do_action( 'wpv_fv_loaded' );
}
+// Load the plugin text domain for translations.
+add_action( 'init', function () {
+ load_plugin_textdomain( 'wpv-fv', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
+} );
+
+add_action('plugins_loaded', function(){
-add_action( 'plugins_loaded', function () {
- require_once WPV_FV__PATH . '/vendor/autoload.php';
- require_once WPV_FV__PATH . '/inc/bootstrap.php';
- FormVibesClassesDbTables::fv_plugin_activated();
-} );
No newline at end of file
+ require_once WPV_FV__PATH . '/vendor/autoload.php';
+ require_once WPV_FV__PATH . '/inc/bootstrap.php';
+ FormVibesClassesDbTables::fv_plugin_activated();
+ //load_plugin_textdomain( 'wpv-fv', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
+});
No newline at end of file
--- a/form-vibes/freemius/assets/css/admin/index.php
+++ b/form-vibes/freemius/assets/css/admin/index.php
@@ -0,0 +1,3 @@
+<?php
+ // Silence is golden.
+ // Hide file structure from users on unprotected servers.
No newline at end of file
--- a/form-vibes/freemius/assets/css/index.php
+++ b/form-vibes/freemius/assets/css/index.php
@@ -0,0 +1,3 @@
+<?php
+ // Silence is golden.
+ // Hide file structure from users on unprotected servers.
No newline at end of file
--- a/form-vibes/freemius/assets/img/index.php
+++ b/form-vibes/freemius/assets/img/index.php
@@ -0,0 +1,3 @@
+<?php
+ // Silence is golden.
+ // Hide file structure from users on unprotected servers.
No newline at end of file
--- a/form-vibes/freemius/assets/index.php
+++ b/form-vibes/freemius/assets/index.php
@@ -0,0 +1,3 @@
+<?php
+ // Silence is golden.
+ // Hide file structure from users on unprotected servers.
No newline at end of file
--- a/form-vibes/freemius/assets/js/index.php
+++ b/form-vibes/freemius/assets/js/index.php
@@ -0,0 +1,3 @@
+<?php
+ // Silence is golden.
+ // Hide file structure from users on unprotected servers.
No newline at end of file
--- a/form-vibes/freemius/config.php
+++ b/form-vibes/freemius/config.php
@@ -0,0 +1,391 @@
+<?php
+ /**
+ * @package Freemius
+ * @copyright Copyright (c) 2015, Freemius, Inc.
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
+ * @since 1.0.4
+ */
+
+ if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+ }
+
+ if ( ! defined( 'WP_FS__SLUG' ) ) {
+ define( 'WP_FS__SLUG', 'freemius' );
+ }
+ if ( ! defined( 'WP_FS__DEV_MODE' ) ) {
+ define( 'WP_FS__DEV_MODE', false );
+ }
+
+ #--------------------------------------------------------------------------------
+ #region API Connectivity Issues Simulation
+ #--------------------------------------------------------------------------------
+
+ if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY' ) ) {
+ define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY', false );
+ }
+ if ( ! defined( 'WP_FS__SIMULATE_NO_CURL' ) ) {
+ define( 'WP_FS__SIMULATE_NO_CURL', false );
+ }
+ if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE' ) ) {
+ define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', false );
+ }
+ if ( ! defined( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL' ) ) {
+ define( 'WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', false );
+ }
+ if ( WP_FS__SIMULATE_NO_CURL ) {
+ define( 'FS_SDK__SIMULATE_NO_CURL', true );
+ }
+ if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) {
+ define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE', true );
+ }
+ if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) {
+ define( 'FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL', true );
+ }
+
+ #endregion
+
+ if ( ! defined( 'WP_FS__SIMULATE_FREEMIUS_OFF' ) ) {
+ define( 'WP_FS__SIMULATE_FREEMIUS_OFF', false );
+ }
+
+ if ( ! defined( 'WP_FS__PING_API_ON_IP_OR_HOST_CHANGES' ) ) {
+ /**
+ * @since 1.1.7.3
+ * @author Vova Feldman (@svovaf)
+ *
+ * I'm not sure if shared servers periodically change IP, or the subdomain of the
+ * admin dashboard. Also, I've seen sites that have strange loop of switching
+ * between domains on a daily basis. Therefore, to eliminate the risk of
+ * multiple unwanted connectivity test pings, temporary ignore domain or
+ * server IP changes.
+ */
+ define( 'WP_FS__PING_API_ON_IP_OR_HOST_CHANGES', false );
+ }
+
+ /**
+ * If your dev environment supports custom public network IP setup
+ * like VVV, please update WP_FS__LOCALHOST_IP with your public IP
+ * and uncomment it during dev.
+ */
+ if ( ! defined( 'WP_FS__LOCALHOST_IP' ) ) {
+ // VVV default public network IP.
+ define( 'WP_FS__VVV_DEFAULT_PUBLIC_IP', '192.168.50.4' );
+
+// define( 'WP_FS__LOCALHOST_IP', WP_FS__VVV_DEFAULT_PUBLIC_IP );
+ }
+
+ /**
+ * If true and running with secret key, the opt-in process
+ * will skip the email activation process which is invoked
+ * when the email of the context user already exist in Freemius
+ * database (as a security precaution, to prevent sharing user
+ * secret with unauthorized entity).
+ *
+ * IMPORTANT:
+ * AS A SECURITY PRECAUTION, WE VALIDATE THE TIMESTAMP OF THE OPT-IN REQUEST.
+ * THEREFORE, MAKE SURE THAT WHEN USING THIS PARAMETER,YOUR TESTING ENVIRONMENT'S
+ * CLOCK IS SYNCED.
+ */
+ if ( ! defined( 'WP_FS__SKIP_EMAIL_ACTIVATION' ) ) {
+ define( 'WP_FS__SKIP_EMAIL_ACTIVATION', false );
+ }
+
+
+ #--------------------------------------------------------------------------------
+ #region Directories
+ #--------------------------------------------------------------------------------
+
+ if ( ! defined( 'WP_FS__DIR' ) ) {
+ define( 'WP_FS__DIR', dirname( __FILE__ ) );
+ }
+ if ( ! defined( 'WP_FS__DIR_INCLUDES' ) ) {
+ define( 'WP_FS__DIR_INCLUDES', WP_FS__DIR . '/includes' );
+ }
+ if ( ! defined( 'WP_FS__DIR_TEMPLATES' ) ) {
+ define( 'WP_FS__DIR_TEMPLATES', WP_FS__DIR . '/templates' );
+ }
+ if ( ! defined( 'WP_FS__DIR_ASSETS' ) ) {
+ define( 'WP_FS__DIR_ASSETS', WP_FS__DIR . '/assets' );
+ }
+ if ( ! defined( 'WP_FS__DIR_CSS' ) ) {
+ define( 'WP_FS__DIR_CSS', WP_FS__DIR_ASSETS . '/css' );
+ }
+ if ( ! defined( 'WP_FS__DIR_JS' ) ) {
+ define( 'WP_FS__DIR_JS', WP_FS__DIR_ASSETS . '/js' );
+ }
+ if ( ! defined( 'WP_FS__DIR_IMG' ) ) {
+ define( 'WP_FS__DIR_IMG', WP_FS__DIR_ASSETS . '/img' );
+ }
+ if ( ! defined( 'WP_FS__DIR_SDK' ) ) {
+ define( 'WP_FS__DIR_SDK', WP_FS__DIR_INCLUDES . '/sdk' );
+ }
+
+ #endregion
+
+ /**
+ * Domain / URL / Address
+ */
+ define( 'WP_FS__ROOT_DOMAIN_PRODUCTION', 'freemius.com' );
+ define( 'WP_FS__DOMAIN_PRODUCTION', 'wp.freemius.com' );
+ define( 'WP_FS__ADDRESS_PRODUCTION', 'https://' . WP_FS__DOMAIN_PRODUCTION );
+
+ if ( ! defined( 'WP_FS__DOMAIN_LOCALHOST' ) ) {
+ define( 'WP_FS__DOMAIN_LOCALHOST', 'wp.freemius' );
+ }
+ if ( ! defined( 'WP_FS__ADDRESS_LOCALHOST' ) ) {
+ define( 'WP_FS__ADDRESS_LOCALHOST', 'http://' . WP_FS__DOMAIN_LOCALHOST . ':8080' );
+ }
+
+ if ( ! defined( 'WP_FS__TESTING_DOMAIN' ) ) {
+ define( 'WP_FS__TESTING_DOMAIN', 'fswp' );
+ }
+
+ #--------------------------------------------------------------------------------
+ #region HTTP
+ #--------------------------------------------------------------------------------
+
+ if ( ! defined( 'WP_FS__IS_HTTP_REQUEST' ) ) {
+ define( 'WP_FS__IS_HTTP_REQUEST', isset( $_SERVER['HTTP_HOST'] ) && isset( $_SERVER['REQUEST_METHOD'] ) );
+ }
+
+ if ( ! defined( 'WP_FS__IS_HTTPS' ) ) {
+ define( 'WP_FS__IS_HTTPS', ( WP_FS__IS_HTTP_REQUEST &&
+ // Checks if CloudFlare's HTTPS (Flexible SSL support).
+ isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) &&
+ 'https' === strtolower( $_SERVER['HTTP_X_FORWARDED_PROTO'] )
+ ) ||
+ // Check if HTTPS request.
+ ( isset( $_SERVER['HTTPS'] ) && 'on' == $_SERVER['HTTPS'] ) ||
+ ( isset( $_SERVER['SERVER_PORT'] ) && 443 == $_SERVER['SERVER_PORT'] )
+ );
+ }
+
+ if ( ! defined( 'WP_FS__IS_POST_REQUEST' ) ) {
+ define( 'WP_FS__IS_POST_REQUEST', ( WP_FS__IS_HTTP_REQUEST &&
+ strtoupper( $_SERVER['REQUEST_METHOD'] ) == 'POST' ) );
+ }
+
+ if ( ! defined( 'WP_FS__REMOTE_ADDR' ) ) {
+ define( 'WP_FS__REMOTE_ADDR', fs_get_ip() );
+ }
+
+ if ( ! defined( 'WP_FS__IS_LOCALHOST' ) ) {
+ if ( defined( 'WP_FS__LOCALHOST_IP' ) ) {
+ define( 'WP_FS__IS_LOCALHOST', ( WP_FS__LOCALHOST_IP === WP_FS__REMOTE_ADDR ) );
+ } else {
+ define( 'WP_FS__IS_LOCALHOST', WP_FS__IS_HTTP_REQUEST &&
+ is_string( WP_FS__REMOTE_ADDR ) &&
+ ( substr( WP_FS__REMOTE_ADDR, 0, 4 ) === '127.' ||
+ WP_FS__REMOTE_ADDR === '::1' )
+ );
+ }
+ }
+
+ if ( ! defined( 'WP_FS__IS_LOCALHOST_FOR_SERVER' ) ) {
+ define( 'WP_FS__IS_LOCALHOST_FOR_SERVER', ( ! WP_FS__IS_HTTP_REQUEST ||
+ false !== strpos( $_SERVER['HTTP_HOST'], 'localhost' ) ) );
+ }
+
+ #endregion
+
+ if ( ! defined( 'WP_FS__IS_PRODUCTION_MODE' ) ) {
+ // By default, run with Freemius production servers.
+ define( 'WP_FS__IS_PRODUCTION_MODE', true );
+ }
+
+ if ( ! defined( 'WP_FS__ADDRESS' ) ) {
+ define( 'WP_FS__ADDRESS', ( WP_FS__IS_PRODUCTION_MODE ? WP_FS__ADDRESS_PRODUCTION : WP_FS__ADDRESS_LOCALHOST ) );
+ }
+
+
+ #--------------------------------------------------------------------------------
+ #region API
+ #--------------------------------------------------------------------------------
+
+ if ( ! defined( 'WP_FS__API_ADDRESS_LOCALHOST' ) ) {
+ define( 'WP_FS__API_ADDRESS_LOCALHOST', 'http://api.freemius-local.com:8080' );
+ }
+ if ( ! defined( 'WP_FS__API_SANDBOX_ADDRESS_LOCALHOST' ) ) {
+ define( 'WP_FS__API_SANDBOX_ADDRESS_LOCALHOST', 'http://sandbox-api.freemius:8080' );
+ }
+
+ // Set API address for local testing.
+ if ( ! WP_FS__IS_PRODUCTION_MODE ) {
+ if ( ! defined( 'FS_API__ADDRESS' ) ) {
+ define( 'FS_API__ADDRESS', WP_FS__API_ADDRESS_LOCALHOST );
+ }
+ if ( ! defined( 'FS_API__SANDBOX_ADDRESS' ) ) {
+ define( 'FS_API__SANDBOX_ADDRESS', WP_FS__API_SANDBOX_ADDRESS_LOCALHOST );
+ }
+ }
+
+ #endregion
+
+ #--------------------------------------------------------------------------------
+ #region Checkout
+ #--------------------------------------------------------------------------------
+
+ if ( ! defined( 'FS_CHECKOUT__ADDRESS_PRODUCTION' ) ) {
+ define( 'FS_CHECKOUT__ADDRESS_PRODUCTION', 'https://checkout.freemius.com' );
+ }
+
+ if ( ! defined( 'FS_CHECKOUT__ADDRESS_LOCALHOST' ) ) {
+ define( 'FS_CHECKOUT__ADDRESS_LOCALHOST', 'http://checkout.freemius-local.com:8080' );
+ }
+
+ if ( ! defined( 'FS_CHECKOUT__ADDRESS' ) ) {
+ define( 'FS_CHECKOUT__ADDRESS', ( WP_FS__IS_PRODUCTION_MODE ? FS_CHECKOUT__ADDRESS_PRODUCTION : FS_CHECKOUT__ADDRESS_LOCALHOST ) );
+ }
+
+ #endregion
+
+ define( 'WP_FS___OPTION_PREFIX', 'fs' . ( WP_FS__IS_PRODUCTION_MODE ? '' : '_dbg' ) . '_' );
+
+ if ( ! defined( 'WP_FS__ACCOUNTS_OPTION_NAME' ) ) {
+ define( 'WP_FS__ACCOUNTS_OPTION_NAME', WP_FS___OPTION_PREFIX . 'accounts' );
+ }
+ if ( ! defined( 'WP_FS__API_CACHE_OPTION_NAME' ) ) {
+ define( 'WP_FS__API_CACHE_OPTION_NAME', WP_FS___OPTION_PREFIX . 'api_cache' );
+ }
+ if ( ! defined( 'WP_FS__GDPR_OPTION_NAME' ) ) {
+ define( 'WP_FS__GDPR_OPTION_NAME', WP_FS___OPTION_PREFIX . 'gdpr' );
+ }
+ define( 'WP_FS__OPTIONS_OPTION_NAME', WP_FS___OPTION_PREFIX . 'options' );
+
+ /**
+ * Module types
+ *
+ * @since 1.2.2
+ */
+ define( 'WP_FS__MODULE_TYPE_PLUGIN', 'plugin' );
+ define( 'WP_FS__MODULE_TYPE_THEME', 'theme' );
+
+ /**
+ * Billing Frequencies
+ */
+ define( 'WP_FS__PERIOD_ANNUALLY', 'annual' );
+ define( 'WP_FS__PERIOD_MONTHLY', 'monthly' );
+ define( 'WP_FS__PERIOD_LIFETIME', 'lifetime' );
+
+ /**
+ * Plans
+ */
+ define( 'WP_FS__PLAN_DEFAULT_PAID', false );
+ define( 'WP_FS__PLAN_FREE', 'free' );
+ define( 'WP_FS__PLAN_TRIAL', 'trial' );
+
+ /**
+ * Times in seconds
+ */
+ if ( ! defined( 'WP_FS__TIME_5_MIN_IN_SEC' ) ) {
+ define( 'WP_FS__TIME_5_MIN_IN_SEC', 300 );
+ }
+ if ( ! defined( 'WP_FS__TIME_10_MIN_IN_SEC' ) ) {
+ define( 'WP_FS__TIME_10_MIN_IN_SEC', 600 );
+ }
+// define( 'WP_FS__TIME_15_MIN_IN_SEC', 900 );
+ if ( ! defined( 'WP_FS__TIME_12_HOURS_IN_SEC' ) ) {
+ define( 'WP_FS__TIME_12_HOURS_IN_SEC', 43200 );
+ }
+ if ( ! defined( 'WP_FS__TIME_24_HOURS_IN_SEC' ) ) {
+ define( 'WP_FS__TIME_24_HOURS_IN_SEC', WP_FS__TIME_12_HOURS_IN_SEC * 2 );
+ }
+ if ( ! defined( 'WP_FS__TIME_WEEK_IN_SEC' ) ) {
+ define( 'WP_FS__TIME_WEEK_IN_SEC', 7 * WP_FS__TIME_24_HOURS_IN_SEC );
+ }
+
+ #--------------------------------------------------------------------------------
+ #region Debugging
+ #--------------------------------------------------------------------------------
+
+ if ( ! defined( 'WP_FS__DEBUG_SDK' ) ) {
+ $debug_mode = get_option( 'fs_debug_mode', null );
+
+ if ( $debug_mode === null ) {
+ $debug_mode = false;
+ add_option( 'fs_debug_mode', $debug_mode );
+ }
+
+ define( 'WP_FS__DEBUG_SDK', is_numeric( $debug_mode ) ? ( 0 < $debug_mode ) : WP_FS__DEV_MODE );
+ }
+
+ if ( ! defined( 'WP_FS__ECHO_DEBUG_SDK' ) ) {
+ define( 'WP_FS__ECHO_DEBUG_SDK', WP_FS__DEV_MODE && ! empty( $_GET['fs_dbg_echo'] ) );
+ }
+ if ( ! defined( 'WP_FS__LOG_DATETIME_FORMAT' ) ) {
+ define( 'WP_FS__LOG_DATETIME_FORMAT', 'Y-m-d H:i:s' );
+ }
+ if ( ! defined( 'FS_API__LOGGER_ON' ) ) {
+ define( 'FS_API__LOGGER_ON', WP_FS__DEBUG_SDK );
+ }
+
+ if ( WP_FS__ECHO_DEBUG_SDK ) {
+ error_reporting( E_ALL );
+ }
+
+ #endregion
+
+ if ( ! defined( 'WP_FS__SCRIPT_START_TIME' ) ) {
+ define( 'WP_FS__SCRIPT_START_TIME', time() );
+ }
+ if ( ! defined( 'WP_FS__DEFAULT_PRIORITY' ) ) {
+ define( 'WP_FS__DEFAULT_PRIORITY', 10 );
+ }
+ if ( ! defined( 'WP_FS__LOWEST_PRIORITY' ) ) {
+ define( 'WP_FS__LOWEST_PRIORITY', 999999999 );
+ }
+
+ #--------------------------------------------------------------------------------
+ #region Multisite Network
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Do not use this define directly, it will have the wrong value
+ * during plugin uninstall/deletion when the inclusion of the plugin
+ * is triggered due to registration with register_uninstall_hook().
+ *
+ * Instead, use fs_is_network_admin().
+ *
+ * @author Vova Feldman (@svovaf)
+ */
+ if ( ! defined( 'WP_FS__IS_NETWORK_ADMIN' ) ) {
+ define( 'WP_FS__IS_NETWORK_ADMIN',
+ is_multisite() &&
+ ( is_network_admin() ||
+ ( ( defined( 'DOING_AJAX' ) && DOING_AJAX &&
+ ( isset( $_REQUEST['_fs_network_admin'] ) && 'true' === $_REQUEST['_fs_network_admin'] /*||
+ ( ! empty( $_REQUEST['action'] ) && 'delete-plugin' === $_REQUEST['action'] )*/ )
+ ) ||
+ // Plugin uninstall.
+ defined( 'WP_UNINSTALL_PLUGIN' ) )
+ )
+ );
+ }
+
+ /**
+ * Do not use this define directly, it will have the wrong value
+ * during plugin uninstall/deletion when the inclusion of the plugin
+ * is triggered due to registration with register_uninstall_hook().
+ *
+ * Instead, use fs_is_blog_admin().
+ *
+ * @author Vova Feldman (@svovaf)
+ */
+ if ( ! defined( 'WP_FS__IS_BLOG_ADMIN' ) ) {
+ define( 'WP_FS__IS_BLOG_ADMIN', is_blog_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['_fs_blog_admin'] ) ) );
+ }
+
+ if ( ! defined( 'WP_FS__SHOW_NETWORK_EVEN_WHEN_DELEGATED' ) ) {
+ // Set to true to show network level settings even if delegated to site admins.
+ define( 'WP_FS__SHOW_NETWORK_EVEN_WHEN_DELEGATED', false );
+ }
+
+ #endregion
+
+ if ( ! defined( 'WP_FS__DEMO_MODE' ) ) {
+ define( 'WP_FS__DEMO_MODE', false );
+ }
+ if ( ! defined( 'FS_SDK__SSLVERIFY' ) ) {
+ define( 'FS_SDK__SSLVERIFY', false );
+ }
--- a/form-vibes/freemius/includes/class-freemius-abstract.php
+++ b/form-vibes/freemius/includes/class-freemius-abstract.php
@@ -0,0 +1,538 @@
+<?php
+ /**
+ * @package Freemius
+ * @copyright Copyright (c) 2015, Freemius, Inc.
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
+ * @since 1.0.7
+ */
+
+ if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+ }
+
+
+ /**
+ * - Each instance of Freemius class represents a single plugin
+ * install by a single user (the installer of the plugin).
+ *
+ * - Each website can only have one install of the same plugin.
+ *
+ * - Install entity is only created after a user connects his account with Freemius.
+ *
+ * Class Freemius_Abstract
+ */
+ abstract class Freemius_Abstract {
+
+ #----------------------------------------------------------------------------------
+ #region Identity
+ #----------------------------------------------------------------------------------
+
+ /**
+ * Check if user has connected his account (opted-in).
+ *
+ * Note:
+ * If the user opted-in and opted-out on a later stage,
+ * this will still return true. If you want to check if the
+ * user is currently opted-in, use:
+ * `$fs->is_registered() && $fs->is_tracking_allowed()`
+ *
+ * @since 1.0.1
+ *
+ * @param bool $ignore_anonymous_state Since 2.5.1
+ *
+ * @return bool
+ */
+ abstract function is_registered( $ignore_anonymous_state = false );
+
+ /**
+ * Check if the user skipped connecting the account with Freemius.
+ *
+ * @since 1.0.7
+ *
+ * @return bool
+ */
+ abstract function is_anonymous();
+
+ /**
+ * Check if the user currently in activation mode.
+ *
+ * @since 1.0.7
+ *
+ * @return bool
+ */
+ abstract function is_activation_mode();
+
+ #endregion
+
+ #----------------------------------------------------------------------------------
+ #region Module Type
+ #----------------------------------------------------------------------------------
+
+ /**
+ * Checks if the plugin's type is "plugin". The other type is "theme".
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 1.2.2
+ *
+ * @return bool
+ */
+ abstract function is_plugin();
+
+ /**
+ * Checks if the module type is "theme". The other type is "plugin".
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 1.2.2
+ *
+ * @return bool
+ */
+ function is_theme() {
+ return ( ! $this->is_plugin() );
+ }
+
+ #endregion
+
+ #----------------------------------------------------------------------------------
+ #region Permissions
+ #----------------------------------------------------------------------------------
+
+ /**
+ * Check if plugin must be WordPress.org compliant.
+ *
+ * @since 1.0.7
+ *
+ * @return bool
+ */
+ abstract function is_org_repo_compliant();
+
+ /**
+ * Check if plugin is allowed to install executable files.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.5
+ *
+ * @return bool
+ */
+ function is_allowed_to_install() {
+ return ( $this->is_premium() || ! $this->is_org_repo_compliant() );
+ }
+
+ #endregion
+
+ /**
+ * Check if user in trial or in free plan (not paying).
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.4
+ *
+ * @return bool
+ */
+ function is_not_paying() {
+ return ( $this->is_trial() || $this->is_free_plan() );
+ }
+
+ /**
+ * Check if the user has an activated and valid paid license on current plugin's install.
+ *
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ abstract function is_paying();
+
+ /**
+ * Check if the user is paying or in trial.
+ *
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ function is_paying_or_trial() {
+ return ( $this->is_paying() || $this->is_trial() );
+ }
+
+ /**
+ * Check if user in a trial or have feature enabled license.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.7
+ *
+ * @return bool
+ */
+ abstract function can_use_premium_code();
+
+ #----------------------------------------------------------------------------------
+ #region Premium Only
+ #----------------------------------------------------------------------------------
+
+ /**
+ * All logic wrapped in methods with "__premium_only()" suffix will be only
+ * included in the premium code.
+ *
+ * Example:
+ * if ( freemius()->is__premium_only() ) {
+ * ...
+ * }
+ */
+
+ /**
+ * Returns true when running premium plugin code.
+ *
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ function is__premium_only() {
+ return $this->is_premium();
+ }
+
+ /**
+ * Check if the user has an activated and valid paid license on current plugin's install.
+ *
+ * @since 1.0.9
+ *
+ * @return bool
+ *
+ */
+ function is_paying__premium_only() {
+ return ( $this->is__premium_only() && $this->is_paying() );
+ }
+
+ /**
+ * All code wrapped in this statement will be only included in the premium code.
+ *
+ * @since 1.0.9
+ *
+ * @param string $plan Plan name.
+ * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans.
+ *
+ * @return bool
+ */
+ function is_plan__premium_only( $plan, $exact = false ) {
+ return ( $this->is_premium() && $this->is_plan( $plan, $exact ) );
+ }
+
+ /**
+ * Check if plan matches active license' plan or active trial license' plan.
+ *
+ * All code wrapped in this statement will be only included in the premium code.
+ *
+ * @since 1.0.9
+ *
+ * @param string $plan Plan name.
+ * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans.
+ *
+ * @return bool
+ */
+ function is_plan_or_trial__premium_only( $plan, $exact = false ) {
+ return ( $this->is_premium() && $this->is_plan_or_trial( $plan, $exact ) );
+ }
+
+ /**
+ * Check if the user is paying or in trial.
+ *
+ * All code wrapped in this statement will be only included in the premium code.
+ *
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ function is_paying_or_trial__premium_only() {
+ return $this->is_premium() && $this->is_paying_or_trial();
+ }
+
+ /**
+ * Check if the user has an activated and valid paid license on current plugin's install.
+ *
+ * @since 1.0.4
+ *
+ * @return bool
+ *
+ * @deprecated Method name is confusing since it's not clear from the name the code will be removed.
+ * @using Alias to is_paying__premium_only()
+ */
+ function is_paying__fs__() {
+ return $this->is_paying__premium_only();
+ }
+
+ /**
+ * Check if user in a trial or have feature enabled license.
+ *
+ * All code wrapped in this statement will be only included in the premium code.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.9
+ *
+ * @return bool
+ */
+ function can_use_premium_code__premium_only() {
+ return $this->is_premium() && $this->can_use_premium_code();
+ }
+
+ #endregion
+
+ #----------------------------------------------------------------------------------
+ #region Trial
+ #----------------------------------------------------------------------------------
+
+ /**
+ * Check if the user in a trial.
+ *
+ * @since 1.0.3
+ *
+ * @return bool
+ */
+ abstract function is_trial();
+
+ /**
+ * Check if trial already utilized.
+ *
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ abstract function is_trial_utilized();
+
+ #endregion
+
+ #----------------------------------------------------------------------------------
+ #region Plans
+ #----------------------------------------------------------------------------------
+
+ /**
+ * Check if the user is on the free plan of the product.
+ *
+ * @since 1.0.4
+ *
+ * @return bool
+ */
+ abstract function is_free_plan();
+
+ /**
+ * @since 1.0.2
+ *
+ * @param string $plan Plan name.
+ * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans.
+ *
+ * @return bool
+ */
+ abstract function is_plan( $plan, $exact = false );
+
+ /**
+ * Check if plan based on trial. If not in trial mode, should return false.
+ *
+ * @since 1.0.9
+ *
+ * @param string $plan Plan name.
+ * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans.
+ *
+ * @return bool
+ */
+ abstract function is_trial_plan( $plan, $exact = false );
+
+ /**
+ * Check if plan matches active license' plan or active trial license' plan.
+ *
+ * @since 1.0.9
+ *
+ * @param string $plan Plan name.
+ * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans.
+ *
+ * @return bool
+ */
+ function is_plan_or_trial( $plan, $exact = false ) {
+ return $this->is_plan( $plan, $exact ) ||
+ $this->is_trial_plan( $plan, $exact );
+ }
+
+ /**
+ * Check if plugin has any paid plans.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.7
+ *
+ * @return bool
+ */
+ abstract function has_paid_plan();
+
+ /**
+ * Check if plugin has any free plan, or is it premium only.
+ *
+ * Note: If no plans configured, assume plugin is free.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.7
+ *
+ * @return bool
+ */
+ abstract function has_free_plan();
+
+ /**
+ * Check if plugin is premium only (no free plans).
+ *
+ * NOTE: is__premium_only() is very different method, don't get confused.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.9
+ *
+ * @return bool
+ */
+ abstract function is_only_premium();
+
+ /**
+ * Check if module has a premium code version.
+ *
+ * Serviceware module might be freemium without any
+ * premium code version, where the paid features
+ * are all part of the service.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.2.1.6
+ *
+ * @return bool
+ */
+ abstract function has_premium_version();
+
+ /**
+ * Check if module has any release on Freemius,
+ * or all plugin's code is on WordPress.org (Serviceware).
+ *
+ * @return bool
+ */
+ function has_release_on_freemius() {
+ return ! $this->is_org_repo_compliant() ||
+ $this->has_premium_version();
+ }
+
+ /**
+ * Checks if it's a freemium plugin.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.9
+ *
+ * @return bool
+ */
+ function is_freemium() {
+ return $this->has_paid_plan() &&
+ $this->has_free_plan();
+ }
+
+ /**
+ * Check if module has only one plan.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.2.1.7
+ *
+ * @return bool
+ */
+ abstract function is_single_plan();
+
+ #endregion
+
+ /**
+ * Check if running payments in sandbox mode.
+ *
+ * @since 1.0.4
+ *
+ * @return bool
+ */
+ abstract function is_payments_sandbox();
+
+ /**
+ * Check if running test vs. live plugin.
+ *
+ * @since 1.0.5
+ *
+ * @return bool
+ */
+ abstract function is_live();
+
+ /**
+ * Check if running premium plugin code.
+ *
+ * @since 1.0.5
+ *
+ * @return bool
+ */
+ abstract function is_premium();
+
+ /**
+ * Get upgrade URL.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.2
+ *
+ * @param string $period Billing cycle.
+ *
+ * @return string
+ */
+ abstract function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY );
+
+ /**
+ * Check if Freemius was first added in a plugin update.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.5
+ *
+ * @return bool
+ */
+ function is_plugin_update() {
+ return ! $this->is_plugin_new_install();
+ }
+
+ /**
+ * Check if Freemius was part of the plugin when the user installed it first.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.5
+ *
+ * @return bool
+ */
+ abstract function is_plugin_new_install();
+
+ #----------------------------------------------------------------------------------
+ #region Marketing
+ #----------------------------------------------------------------------------------
+
+ /**
+ * Check if current user purchased any other plugins before.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ abstract function has_purchased_before();
+
+ /**
+ * Check if current user classified as an agency.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ abstract function is_agency();
+
+ /**
+ * Check if current user classified as a developer.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ abstract function is_developer();
+
+ /**
+ * Check if current user classified as a business.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.9
+ *
+ * @return bool
+ */
+ abstract function is_business();
+
+ #endregion
+ }
No newline at end of file
--- a/form-vibes/freemius/includes/class-freemius.php
+++ b/form-vibes/freemius/includes/class-freemius.php
@@ -0,0 +1,26368 @@
+<?php
+ /**
+ * @package Freemius
+ * @copyright Copyright (c) 2015, Freemius, Inc.
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
+ * @since 1.0.3
+ */
+ if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+ }
+
+ // "final class"
+ class Freemius extends Freemius_Abstract {
+ /**
+ * SDK Version
+ *
+ * @var string
+ */
+ public $version = WP_FS__SDK_VERSION;
+
+ #region Plugin Info
+
+ /**
+ * @since 1.0.1
+ *
+ * @var string
+ */
+ private $_slug;
+
+ /**
+ * @since 1.0.0
+ *
+ * @var string
+ */
+ private $_plugin_basename;
+ /**
+ * @since 2.2.1
+ *
+ * @var string
+ */
+ private $_premium_plugin_basename;
+ /**
+ * @since 1.0.0
+ *
+ * @var string
+ */
+ private $_free_plugin_basename;
+ /**
+ * @since 1.0.0
+ *
+ * @var string
+ */
+ private $_plugin_dir_path;
+ /**
+ * @since 1.0.0
+ *
+ * @var string
+ */
+ private $_plugin_dir_name;
+ /**
+ * @since 1.0.0
+ *
+ * @var string
+ */
+ private $_plugin_main_file_path;
+ /**
+ * @var string[]
+ */
+ private $_plugin_data;
+ /**
+ * @since 1.0.9
+ *
+ * @var string
+ */
+ private $_plugin_name;
+ /**
+ * @since 1.2.2
+ *
+ * @var string
+ */
+ private $_module_type;
+
+ #endregion Plugin Info
+
+ /**
+ * @since 1.0.9
+ *
+ * @var bool If false, don't turn Freemius on.
+ */
+ private $_is_on;
+
+ /**
+ * @since 1.1.3
+ *
+ * @var bool If false, don't turn Freemius on.
+ */
+ private $_is_anonymous;
+
+ /**
+ * @since 1.0.9
+ * @var bool If false, issues with connectivity to Freemius API.
+ */
+ private $_has_api_connection;
+
+ /**
+ * @since 1.0.9
+ * @since 2.0.0 Default to true since we need the property during the instance construction, prior to the dynamic_init() execution.
+ * @var bool Hints the SDK if plugin can support anonymous mode (if skip connect is visible).
+ */
+ private $_enable_anonymous = true;
+
+ /**
+ * @since 2.9.1
+ * @var string|null Hints the SDK whether the plugin supports parallel activation mode, preventing the auto-deactivation of the free version when the premium version is activated, and vice versa.
+ */
+ private $_premium_plugin_basename_from_parallel_activation;
+
+ /**
+ * @since 1.1.7.5
+ * @var bool Hints the SDK if plugin should run in anonymous mode (only adds feedback form).
+ */
+ private $_anonymous_mode;
+
+ /**
+ * @since 1.1.9
+ * @var bool Hints the SDK if plugin have any free plans.
+ */
+ private $_is_premium_only;
+
+ /**
+ * @since 1.2.1.6
+ * @var bool Hints the SDK if plugin have premium code version at all.
+ */
+ private $_has_premium_version;
+
+ /**
+ * @since 1.2.1.6
+ * @var bool Hints the SDK if plugin should ignore pending mode by simulating a skip.
+ */
+ private $_ignore_pending_mode;
+
+ /**
+ * @since 1.0.8
+ * @var bool Hints the SDK if the plugin has any paid plans.
+ */
+ private $_has_paid_plans;
+
+ /**
+ * @since 1.2.1.5
+ * @var int Hints the SDK if the plugin offers a trial period. If negative, no trial, if zero - has a trial but
+ * without a specified period, if positive - the number of trial days.
+ */
+ private $_trial_days = - 1;
+
+ /**
+ * @since 1.2.1.5
+ * @var bool Hints the SDK if the trial requires a payment method or not.
+ */
+ private $_is_trial_require_payment = false;
+
+ /**
+ * @since 1.0.7
+ * @var bool Hints the SDK if the plugin is WordPress.org compliant.
+ */
+ private $_is_org_compliant;
+
+ /**
+ * @since 1.0.7
+ * @var bool Hints the SDK if the plugin is has add-ons.
+ */
+ private $_has_addons;
+
+ /**
+ * @since 2.4.5
+ * @var string Navigation type: 'menu' or 'tabs'.
+ */
+ private $_navigation;
+
+ const NAVIGATION_MENU = 'menu';
+ const NAVIGATION_TABS = 'tabs';
+
+ /**
+ * @since 1.1.6
+ * @var string[]bool.
+ */
+ private $_permissions;
+
+ /**
+ * @var FS_Storage
+ */
+ private $_storage;
+
+ /**
+ * @since 1.2.2.7
+ * @var FS_Cache_Manager
+ */
+ private $_cache;
+
+ /**
+ * @since 1.0.0
+ *
+ * @var FS_Logger
+ */
+ private $_logger;
+ /**
+ * @since 1.0.4
+ *
+ * @var FS_Plugin
+ */
+ private $_plugin = false;
+ /**
+ * @since 1.0.4
+ *
+ * @var FS_Plugin|false
+ */
+ private $_parent_plugin = false;
+ /**
+ * @since 1.1.1
+ *
+ * @var Freemius
+ */
+ private $_parent = false;
+ /**
+ * @since 1.0.1
+ *
+ * @var FS_User
+ */
+ private $_user = false;
+ /**
+ * @since 1.0.1
+ *
+ * @var FS_Site
+ */
+ private $_site = false;
+ /**
+ * @since 1.0.1
+ *
+ * @var FS_Plugin_License
+ */
+ private $_license;
+ /**
+ * @since 1.0.2
+ *
+ * @var FS_Plugin_Plan[]
+ */
+ private $_plans = false;
+ /**
+ * @var FS_Plugin_License[]
+ * @since 1.0.5
+ */
+ private $_licenses = false;
+
+ /**
+ * @since 1.0.1
+ *
+ * @var FS_Admin_Menu_Manager
+ */
+ private $_menu;
+
+ /**
+ * @var FS_Admin_Notices
+ */
+ private $_admin_notices;
+
+ /**
+ * @since 1.1.6
+ *
+ * @var FS_Admin_Notices
+ */
+ private static $_global_admin_notices;
+
+ /**
+ * @var FS_Logger
+ * @since 1.0.0
+ */
+ private static $_static_logger;
+
+ /**
+ * @var FS_Options
+ * @since 1.0.2
+ */
+ private static $_accounts;
+
+ /**
+ * @since 1.2.2
+ *
+ * @var number
+ */
+ private $_module_id;
+
+ /**
+ * @var Freemius[]
+ */
+ private static $_instances = array();
+
+ /**
+ * @since 1.2.3
+ *
+ * @var FS_Affiliate
+ */
+ private $affiliate = null;
+
+ /**
+ * @since 1.2.3
+ *
+ * @var FS_AffiliateTerms
+ */
+ private $plugin_affiliate_terms = null;
+
+ /**
+ * @since 1.2.3
+ *
+ * @var FS_AffiliateTerms
+ */
+ private $custom_affiliate_terms = null;
+
+ /**
+ * @since 2.0.0
+ *
+ * @var bool
+ */
+ private $_is_multisite_integrated;
+
+ /**
+ * @since 2.0.0
+ *
+ * @var bool True if the current request is for a network admin screen and the plugin is network active.
+ */
+ private $_is_network_active;
+
+ /**
+ * @since 2.0.0
+ *
+ * @var int|null The original blog ID the plugin was loaded with.
+ */
+ private $_blog_id = null;
+
+ /**
+ * @since 2.0.0
+ *
+ * @var int|null The current execution context. When true, run on network context. When int, run on the specified blog context.
+ */
+ private $_context_is_network_or_blog_id = null;
+
+ /**
+ * @since 2.0.0
+ *
+ * @var string
+ */
+ private $_dynamically_added_top_level_page_hook_name = '';
+
+ /**
+ * @author Leo Fajardo (@leorw)
+ * @since 2.3.1
+ *
+ * @var bool
+ */
+ private $is_whitelabeled;
+
+ /**
+ * @author Leo Fajardo (@leorw)
+ * @since 2.4.0
+ *
+ * @var bool
+ */
+ private $_is_bundle_license_auto_activation_enabled = false;
+
+ #region Uninstall Reasons IDs
+
+ const REASON_NO_LONGER_NEEDED = 1;
+ const REASON_FOUND_A_BETTER_PLUGIN = 2;
+ const REASON_NEEDED_FOR_A_SHORT_PERIOD = 3;
+ const REASON_BROKE_MY_SITE = 4;
+ const REASON_SUDDENLY_STOPPED_WORKING = 5;
+ const REASON_CANT_PAY_ANYMORE = 6;
+ const REASON_OTHER = 7;
+ const REASON_DIDNT_WORK = 8;
+ const REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION = 9;
+ const REASON_COULDNT_MAKE_IT_WORK = 10;
+ const REASON_GREAT_BUT_NEED_SPECIFIC_FEATURE = 11;
+ const REASON_NOT_WORKING = 12;
+ const REASON_NOT_WHAT_I_WAS_LOOKING_FOR = 13;
+ const REASON_DIDNT_WORK_AS_EXPECTED = 14;
+ const REASON_TEMPORARY_DEACTIVATION = 15;
+
+ #endregion
+
+ /**
+ * @author Leo Fajardo (@leorw)
+ * @since 2.4.2
+ *
+ * @var string|null
+ */
+ private $_pricing_js_path = null;
+
+ const VERSION_MAX_CHARS = 16;
+ const LANGUAGE_MAX_CHARS = 8;
+
+ /* Ctor
+------------------------------------------------------------------------------------------------------------------*/
+
+ /**
+ * Main singleton instance.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param number $module_id
+ * @param string|bool $slug
+ * @param bool $is_init Since 1.2.1 Is initiation sequence.
+ */
+ private function __construct( $module_id, $slug = false, $is_init = false ) {
+ $main_file = false;
+
+ if ( $is_init && is_numeric( $module_id ) && is_string( $slug ) ) {
+ $main_file = $this->store_id_slug_type_path_map( $module_id, $slug );
+ }
+
+ $this->_module_id = $module_id;
+ $this->_slug = $this->get_slug();
+ $this->_module_type = $this->get_module_type();
+
+ $this->_blog_id = is_multisite() ? get_current_blog_id() : null;
+
+ $this->_storage = FS_Storage::instance( $this->_module_type, $this->_slug );
+
+ // If not set or 24 hours have already passed from the last time it's set, set the last load timestamp to the current time.
+ if (
+ ! isset( $this->_storage->last_load_timestamp ) ||
+ $this->_storage->last_load_timestamp < ( time() - ( WP_FS__TIME_24_HOURS_IN_SEC ) )
+ ) {
+ $this->_storage->last_load_timestamp = time();
+ }
+
+ $this->_cache = FS_Cache_Manager::get_manager( WP_FS___OPTION_PREFIX . "cache_{$module_id}" );
+
+ $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->get_unique_affix(), WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
+
+ $this->_plugin_main_file_path = $this->_find_caller_plugin_file( $is_init, $main_file );
+ $this->_plugin_dir_path = plugin_dir_path( $this->_plugin_main_file_path );
+ $this->_plugin_basename = $this->get_plugin_basename();
+ $this->_free_plugin_basename = str_replace( '-premium/', '/', $this->_plugin_basename );
+
+ $this->_is_multisite_integrated = (
+ defined( "WP_FS__PRODUCT_{$module_id}_MULTISITE" ) &&
+ ( true === constant( "WP_FS__PRODUCT_{$module_id}_MULTISITE" ) )
+ );
+
+ $this->_is_network_active = (
+ is_multisite() &&
+ $this->_is_multisite_integrated &&
+ // Themes are always network activated, but the ACTUAL activation is per site.
+ $this->is_plugin() &&
+ (
+ is_plugin_active_for_network( $this->_plugin_basename ) ||
+ // Plugin network level activation or uninstall.
+ ( fs_is_network_admin() && is_plugin_inactive( $this->_plugin_basename ) )
+ )
+ );
+
+ $this->_storage->set_network_active(
+ $this->_is_network_active,
+ $this->is_delegated_connection()
+ );
+
+ if ( ! isset( $this->_storage->is_network_activated ) ) {
+ $this->_storage->is_network_activated = $this->_is_network_active;
+ }
+
+ if ( $this->_storage->is_network_activated != $this->_is_network_active ) {
+ // Update last activation level.
+ $this->_storage->is_network_activated = $this->_is_network_active;
+
+ $this->maybe_adjust_storage();
+ }
+
+ #region Migration
+
+ if ( is_multisite() ) {
+ /**
+ * If the install_timestamp exists on the site level but doesn't exist on the
+ * network level storage, it means that we need to process the storage with migration.
+ *
+ * The code in this `if` scope will only be executed once and only for the first site that will execute it because once we migrate the storage data, install_timestamp will be already set in the network level storage.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 2.0.0
+ */
+ if ( false === $this->_storage->get( 'install_timestamp', false, true ) &&
+ false !== $this->_storage->get( 'install_timestamp', false, false )
+ ) {
+ // Initiate storage migration.
+ $this->_storage->migrate_to_network();
+
+ // Migrate module cache to network level storage.
+ $this->_cache->migrate_to_network();
+ }
+ }
+
+ #endregion
+
+ $base_name_split = explode( '/', $this->_plugin_basename );
+ $this->_plugin_dir_name = $base_name_split[0];
+
+ if ( $this->_logger->is_on() ) {
+ $this->_logger->info( 'plugin_main_file_path = ' . $this->_plugin_main_file_path );
+ $this->_logger->info( 'plugin_dir_path = ' . $this->_plugin_dir_path );
+ $this->_logger->info( 'plugin_basename = ' . $this->_plugin_basename );
+ $this->_logger->info( 'free_plugin_basename = ' . $this->_free_plugin_basename );
+ $this->_logger->info( 'plugin_dir_name = ' . $this->_plugin_dir_name );
+ }
+
+ // Remember link between file to slug.
+ $this->store_file_slug_map();
+
+ // Store plugin's initial install timestamp.
+ if ( ! isset( $this->_storage->install_timestamp ) ) {
+ $this->_storage->install_timestamp = WP_FS__SCRIPT_START_TIME;
+ }
+
+ if ( ! is_object( $this->_plugin ) ) {
+ $this->_plugin = FS_Plugin_Manager::instance( $this->_module_id )->get();
+ }
+
+ $this->_admin_notices = FS_Admin_Notices::instance(
+ $this->_slug . ( $this->is_theme() ? ':theme' : '' ),
+ /**
+ * Ensure that the admin notice will always have a title by using the stored plugin title if available and
+ * retrieving the title via the "get_plugin_name" method if there is no stored plugin title available.
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 1.2.2
+ */
+ ( is_object( $this->_plugin ) && isset( $this->_plugin->title ) ?
+ $this->_plugin->title :
+ $this->get_plugin_name()
+ ),
+ $this->get_unique_affix()
+ );
+
+ if ( 'true' === fs_request_get( 'fs_clear_api_cache' ) ||
+ fs_request_is_action( 'restart_freemius' )
+ ) {
+ FS_Api::clear_cache();
+ $this->_cache->clear();
+ }
+
+ $this->register_constructor_hooks();
+
+ /**
+ * Starting from version 2.0.0, `FS_Site` entities no longer have the `plan` property and have `plan_id`
+ * instead. This should be called before calling `_load_account()`, otherwise, `$this->_site` will not be
+ * loaded in `_load_account` for versions of SDK starting from 2.0.0.
+ *
+ * @author Leo Fajardo (@leorw)
+ */
+ self::migrate_install_plan_to_plan_id( $this->_storage );
+
+ $this->_load_account();
+
+ $this->_version_updates_handler();
+ }
+
+ /**
+ * @author Leo Fajardo (@leorw)
+ * @since 2.3.0
+ */
+ private function maybe_adjust_storage() {
+ $install_timestamp = null;
+ $prev_is_premium = null;
+
+ $options_to_update = array();
+
+ $is_network_admin = fs_is_network_admin();
+
+ $network_install_timestamp = $this->_storage->get( 'install_timestamp', null, true );
+
+ if ( ! $is_network_admin ) {
+ if ( is_null( $network_install_timestamp ) ) {
+ // Plugin was not network-activated before.
+ return;
+ }
+
+ if ( is_null( $this->_storage->get( 'install_timestamp', null, false ) ) ) {
+ // Set the `install_timestamp` only if it's not yet set.
+ $install_timestamp = $network_install_timestamp;
+ }
+
+ $prev_is_premium = $this->_storage->get( 'prev_is_premium', null, true );
+ } else {
+ $current_wp_user = self::_get_current_wp_user();
+ $current_fs_user = self::_get_user_by_email( $current_wp_user->user_email );
+ $network_user_info = array();
+
+ $skips_count = 0;
+
+ $sites = self::get_sites();
+ $sites_count = count( $sites );
+
+ $blog_id_2_install_map = array();
+
+ $is_first_non_ignored_blog = true;
+
+ foreach ( $sites as $site ) {
+ $blog_id = self::get_site_blog_id( $site );
+
+ $blog_install_timestamp = $this->_storage->get( 'install_timestamp', null, $blog_id );
+
+ if ( is_null( $blog_install_timestamp ) ) {
+ // Plugin has not been installed on this blog.
+ continue;
+ }
+
+ $is_earlier_install = (
+ ! is_null( $install_timestamp ) &&
+ $blog_install_timestamp < $install_timestamp
+ );
+
+ $install = $this->get_install_by_blog_id( $blog_id );
+
+ $update_network_user_info = false;
+
+ if ( ! is_object( $install ) ) {
+ if ( ! $this->_storage->get( 'is_anonymous', false, $blog_id ) ) {
+ // The opt-in decision (whether to skip or opt in) is yet to be made.
+ continue;
+ }
+
+ $skips_count ++;
+ } else {
+ $blog_id_2_install_map[ $blog_id ] = $install;
+
+ if ( empty( $network_user_info ) ) {
+ // Set the network user info for the 1st time. Choose any user information whether or not it is for the current WP user.
+ $update_network_user_info = true;
+ }
+
+ if ( ! $update_network_user_info &&
+ is_object( $current_fs_user ) &&
+ $network_user_info['user_id'] != $current_fs_user->id &&
+ $install->user_id == $current_fs_user->id
+ ) {
+ // If an install that is owned by the current WP user is found, use its user information instead.
+ $update_network_user_info = true;
+ }
+
+ if ( ! $update_network_user_info &&
+ $is_earlier_install &&
+ ( ! is_object( $current_fs_user ) || $current_fs_user->id == $install->user_id )
+ ) {
+ // Update to the earliest install info if there's no install found so far that is owned by the current WP user; OR only if the found install is owned by the current WP user.
+ $update_network_user_info = true;
+ }
+ }
+
+ if ( $update_network_user_info ) {
+ $network_user_info = array(
+ 'user_id' => $install->user_id,
+ 'blog_id' => $blog_id
+ );
+ }
+
+ $site_prev_is_premium = $this->_storage->get( 'prev_is_premium', null, $blog_id );
+
+ if ( $is_first_non_ignored_blog ) {
+ $prev_is_premium = $site_prev_is_premium;
+
+ if ( is_null( $network_install_timestamp ) ) {
+ $install_timestamp = $blog_install_timestamp;
+ }
+
+ $is_first_non_ignored_blog = false;
+
+ continue;
+ }
+
+ if ( ! is_null( $prev_is_premium ) && $prev_is_premium !== $site_prev_is_premium ) {
+ // If a different `$site_prev_is_premium` value is found, do not include the option in the collection of options to update.
+ $prev_is_premium = null;
+ }
+
+ if ( $is_earlier_install ) {
+ // If an earlier install timestamp is found.
+ $install_timestamp = $blog_install_timestamp;
+ }
+ }
+
+ $installs_count = count( $blog_id_2_install_map );
+
+ if ( $sites_count === ( $installs_count + $skips_count ) ) {
+ if ( ! empty( $network_user_info ) ) {
+ $options_to_update['network_user_id'] = $network_user_info['user_id'];
+ $options_to_update['network_install_blog_id'] = $network_user_info['blog_id'];
+
+ foreach ( $blog_id_2_install_map as $blog_id => $install ) {
+ if ( $install->user_id == $network_user_info['user_id'] ) {
+ continue;
+ }
+
+ $this->_storage->store( 'is_delegated_connection', true, $blog_id );
+ }
+ }
+
+ if ( $sites_count === $skips_count ) {
+ /**
+ * Assume network-level skipping as the intended action if all actions identified were only
+ * skipping of the connection (i.e., no opt-ins and delegated connections so far).
+ */
+ $options_to_update['is_anonymous_ms'] = true;
+ } else if ( $sites_count === $installs_count ) {
+ /**
+ * Assume network-level opt-in as the intended action if all actions identified were only opt-ins
+ * (i.e., no delegation and skipping of the connections so far).
+ */
+ $options_to_update['is_network_connected'] = true;
+ }
+ }
+ }
+
+ if ( ! is_null( $install_timestamp ) ) {
+ $options_to_update['install_timestamp'] = $install_timestamp;
+ }
+
+ if ( ! is_null( $prev_is_premium ) ) {
+ $options_to_update['prev_is_premium'] = $prev_is_premium;
+ }
+
+ if ( ! empty( $options_to_update ) ) {
+ $this->adjust_storage( $options_to_update, $is_network_admin );
+ }
+ }
+
+ /**
+ * @author Leo Fajardo (@leorw)
+ * @since 2.3.0
+ *
+ * @param array $options
+ * @param bool $is_network_admin
+ */
+ private function adjust_storage( $options, $is_network_admin ) {
+ foreach ( $options as $name => $value ) {
+ $this->_storage->store( $name, $value, $is_network_admin ? true : null );
+ }
+ }
+
+ /**
+ * Checks whether this module has a settings menu.
+ *
+ * @author Leo Fajardo (@leorw)
+ * @since 1.2.2
+ *
+ * @return bool
+ */
+ function has_settings_menu() {
+ return ( $this->_is_network_active && fs_is_network_admin() ) ?
+ $this->_menu->has_network_menu() :
+ $this->_menu->has_menu();
+ }
+
+ /**
+ * If `true` the opt-in should be shown as a modal dialog box on the themes.php page. WordPress.org themes guidelines prohibit from redirecting the user from the themes.php page after activating a theme.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 2.4.5
+ *
+ * @return bool
+ */
+ function show_opt_in_on_themes_page() {
+ if ( ! $this->is_free_wp_org_theme() ) {
+ return false;
+ }
+
+ if ( ! $this->has_settings_menu() ) {
+ return true;
+ }
+
+ return $this->show_settings_with_tabs();
+ }
+
+ /**
+ * If `true` the opt-in sh