strtotime( $expiration, current_time( 'timestamp' ) ), 'value' => json_encode( $value ), ]; $updated = update_option( $cache_key, $data, false ); if ( false === $updated ) { self::$transient_data[ $cache_key ] = $data; } } private static function get_transient( $cache_key ) { $cache = self::$transient_data[ $cache_key ] ?? get_option( $cache_key ); if ( empty( $cache['timeout'] ) ) { return false; } if ( current_time( 'timestamp' ) > $cache['timeout'] && is_user_logged_in() ) { return false; } return json_decode( $cache['value'], true ); } public static function set_license_data( $license_data, $expiration = null ) { } public static function get_license_data( $force_request = false ) { $license_data['success'] = true; $license_data['expires'] = 'lifetime'; $license_data['features'] = [ 'custom-attributes', 'custom_code', 'custom-css', 'global-css', 'display-conditions', 'dynamic-tags-acf', 'dynamic-tags-pods', 'dynamic-tags-toolset', 'element-manager-permissions', 'global-widget', 'editor_comments', 'stripe-button', 'popup', 'role-manager', 'woocommerce-menu-cart', 'product-single', 'product-archive', 'settings-woocommerce-pages', 'settings-woocommerce-notices', 'dynamic-tags-wc', 'atomic-custom-attributes', 'theme-builder', 'form-submissions', 'akismet', 'activity-log', 'cf7db', 'transitions', 'size-variable' ]; return $license_data; } public static function get_version( $force_update = true, $additional_status = '' ) { return []; } public static function get_plugin_package_url( $version ) { return ''; } public static function get_errors() { return [ 'no_activations_left' => '', 'expired' => '', 'missing' => '', 'cancelled' => '', 'key_mismatch' => '', ]; } public static function get_error_message( $error ) { $errors = self::get_errors(); if ( isset( $errors[ $error ] ) ) { $error_msg = $errors[ $error ]; } else { $error_msg = esc_html__( 'An error occurred. Please check your internet connection and try again. If the problem persists, contact our support.', 'elementor-pro' ) . ' (' . $error . ')'; } return $error_msg; } public static function is_license_active() { $license_data = self::get_license_data(); return (bool) $license_data['success']; } public static function is_license_expired() { $license_data = self::get_license_data(); return ! empty( $license_data['error'] ) && self::STATUS_EXPIRED === $license_data['error']; } public static function is_licence_pro_trial() { return self::is_licence_has_feature( self::FEATURE_PRO_TRIAL ); } public static function is_licence_has_feature( $feature_name, $license_check_validator = null ) { $license_data = self::get_license_data(); if ( self::custom_licence_validator_passed( $license_check_validator ) ) { return true; } return ! empty( $license_data['features'] ) && in_array( $feature_name, $license_data['features'], true ); } private static function custom_licence_validator_passed( $license_check_validator ) { return null !== $license_check_validator && is_callable( [ __CLASS__, $license_check_validator ] ) && self::$license_check_validator(); } private static function should_allow_all_features() { return ! self::licence_supports_tiers() || self::is_frontend(); } private static function is_frontend() { return ! is_admin() && ! Plugin::elementor()->preview->is_preview_mode(); } /* * We can consider removing this function and it's usages at a future point if * we feel confident that all user's Licence Caches has been refreshed * and should definitely contain a tier and generation. */ private static function licence_supports_tiers() { $license_data = self::get_license_data(); return ! empty( $license_data[ static::LICENCE_TIER_KEY ] ) && ! empty( $license_data[ static::LICENCE_GENERATION_KEY ] ); } public static function is_need_to_show_upgrade_promotion() { if ( ! self::licence_supports_tiers() ) { return false; } return self::is_licence_tier( static::TIER_ESSENENTIAL ) && self::is_licence_generation( static::GENERATION_EMPTY ); } private static function is_licence_tier( $tier ) { if ( ! self::licence_supports_tiers() ) { return false; } return self::get_license_data()[ static::LICENCE_TIER_KEY ] === $tier; } private static function is_licence_generation( $generation ) { if ( ! self::licence_supports_tiers() ) { return false; } return self::get_license_data()[ static::LICENCE_GENERATION_KEY ] === $generation; } public static function filter_active_features( $features ) { if ( self::should_allow_all_features() ) { return array_values( $features ); } $license_data = self::get_license_data(); $filtered_values = []; if ( ! is_array( $license_data['features'] ) ) { $license_data['features'] = []; } foreach ( $license_data['features'] as $key ) { if ( ! array_key_exists( $key, $features ) ) { continue; } $filtered_values[] = $features[ $key ]; } return $filtered_values; } public static function get_promotion_widgets() { $promotions = Core_API::get_promotion_widgets(); $license_data = self::get_license_data(); if ( ! self::licence_supports_tiers() ) { return []; } if ( ! is_array( $license_data['features'] ) ) { $license_data['features'] = []; } foreach ( $promotions as $key => $promotion ) { if ( ! in_array( $promotion['name'], $license_data['features'] ) ) { continue; } unset( $promotions[ $key ] ); } return array_values( $promotions ); } /* * Check if the Licence is not Expired and also has a Feature. * Needed because even Expired Licences keep the features array for BC. */ public static function active_licence_has_feature( $feature_name ) { return ! self::is_license_expired() && self::is_licence_has_feature( $feature_name, static::BC_VALIDATION_CALLBACK ); } public static function is_license_about_to_expire() { $license_data = self::get_license_data(); if ( ! empty( $license_data['recurring'] ) ) { return false; } if ( 'lifetime' === $license_data['expires'] ) { return false; } return time() > strtotime( '-28 days', strtotime( $license_data['expires'] ) ); } /** * @param string $library_type * * @return int */ public static function get_library_access_level( $library_type = 'template' ) { $license_data = static::get_license_data(); $access_level = ConnectModule::ACCESS_LEVEL_CORE; if ( static::is_license_active() ) { $access_level = ConnectModule::ACCESS_LEVEL_PRO; } // For BC: making sure that it returns the correct access_level even if "features" is not defined in the license data. if ( ! isset( $license_data['features'] ) || ! is_array( $license_data['features'] ) ) { return $access_level; } $library_access_level_prefix = "{$library_type}_access_level_"; foreach ( $license_data['features'] as $feature ) { if ( strpos( $feature, $library_access_level_prefix ) !== 0 ) { continue; } $access_level = (int) str_replace( $library_access_level_prefix, '', $feature ); } return $access_level; } /** * The license API uses "tiers" and "generations". * Because we don't use the same logic, and have a flat list of prioritized tiers & generations, * we take the generation if exists and fallback to the tier otherwise. * * For example: * [ 'tier' => 'essential', 'generation' => 'essential-oct2023' ] => 'essential-oct2023' * [ 'tier' => 'essential', 'generation' => 'empty' ] => 'essential' * [ 'tier' => '', 'generation' => '' ] => 'essential-oct2023' * [] => 'essential-oct2023' * * @return string */ public static function get_access_tier() { if ( ! static::is_license_active() ) { return 'free'; } $license_data = static::get_license_data(); $tier = $license_data['tier'] ?? null; $generation = $license_data['generation'] ?? null; // Fallback to legacy license when the API returns empty values. $is_legacy_api = empty( $tier ) || empty( $generation ); if ( $is_legacy_api ) { return 'essential-oct2023'; } // The license API returns "empty" instead of empty string. $has_generation = 'empty' !== $generation; if ( $has_generation ) { return $generation; } return $tier; } public static function get_plan_type() { if ( ! static::is_license_active() ) { return 'free'; } $license_data = static::get_license_data(); $plan_type = $license_data['tier'] ?? 'free'; return $plan_type; } }