: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
self::$_static_logger->entrance();
if ( is_object( $this->_site ) && ! $this->is_registered() ) {
if ( isset( $this->_is_on ) ) {
// If already installed or pending then sure it's on :)
if ( $this->is_registered() || $this->is_pending_activation() ) {
* @author Vova Feldman (@svovaf)
* @param bool $flush_if_no_connectivity
private function should_run_connectivity_test( $flush_if_no_connectivity = false ) {
if ( ! isset( $this->_storage->connectivity_test ) ) {
// Connectivity test was never executed, or cache was cleared.
if ( WP_FS__PING_API_ON_IP_OR_HOST_CHANGES ) {
if ( WP_FS__IS_HTTP_REQUEST ) {
if ( $_SERVER['HTTP_HOST'] != $this->_storage->connectivity_test['host'] ) {
if ( WP_FS__REMOTE_ADDR != $this->_storage->connectivity_test['server_ip'] ) {
if ( $this->_storage->connectivity_test['is_connected'] &&
$this->_storage->connectivity_test['is_active']
// API connected and Freemius is active - no need to run connectivity check.
if ( $flush_if_no_connectivity ) {
* If explicitly asked to flush when no connectivity - do it only
* if at least 10 sec passed from the last API connectivity test.
return ( isset( $this->_storage->connectivity_test['timestamp'] ) &&
( WP_FS__SCRIPT_START_TIME - $this->_storage->connectivity_test['timestamp'] ) > 10 );
* @since 1.1.7 Don't check for connectivity on plugin downgrade.
$version = $this->get_plugin_version();
if ( version_compare( $version, $this->_storage->connectivity_test['version'], '>' ) ) {
// If it's a plugin version upgrade and Freemius is off or no connectivity, run connectivity test.
* @author Leo Fajardo (@leorw)
private function should_turn_fs_on( $is_update = true ) {
empty( $this->_plugin->opt_in_moderation ) ||
! is_array( $this->_plugin->opt_in_moderation )
$optin_config = $this->_plugin->opt_in_moderation;
( ! isset( $optin_config['localhost'] ) || false !== $optin_config['localhost'] )
$optin_config_key = $is_update ?
if ( ! isset( $optin_config[ $optin_config_key ] ) ) {
$visibility_percentage = $optin_config[ $optin_config_key ];
if ( 0 == $visibility_percentage ) {
if ( ! is_numeric( $visibility_percentage ) ) {
if ( function_exists( 'random_int' ) ) {
$random = random_int( $min, $max ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.random_intFound
$random = rand( $min, $max );
return ( $random <= $visibility_percentage );
* Check if there's any connectivity issue to Freemius API.
* @author Vova Feldman (@svovaf)
* @param bool $flush_if_no_connectivity
function has_api_connectivity( $flush_if_no_connectivity = false ) {
$this->_logger->entrance();
if ( isset( $this->_has_api_connection ) && ( $this->_has_api_connection || ! $flush_if_no_connectivity ) ) {
return $this->_has_api_connection;
if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY &&
isset( $this->_storage->connectivity_test ) &&
true === $this->_storage->connectivity_test['is_connected']
$this->clear_connectivity_info();
if ( ! $this->should_run_connectivity_test( $flush_if_no_connectivity ) ) {
$this->_has_api_connection = $this->_storage->connectivity_test['is_connected'];
* @since 1.1.6 During dev mode, if there's connectivity - turn Freemius on regardless the configuration.
* @since 1.2.1.5 If the user running the premium version then ignore the 'is_active' flag and turn Freemius on to enable license key activation.
$this->_is_on = $this->_storage->connectivity_test['is_active'] ||
( WP_FS__DEV_MODE && $this->_has_api_connection && ! WP_FS__SIMULATE_FREEMIUS_OFF );
return $this->_has_api_connection;
! empty( $this->_storage->connectivity_test ) &&
isset( $this->_storage->connectivity_test['is_active'] )
$is_active = $this->_storage->connectivity_test['is_active'];
$is_active = $this->should_turn_fs_on( $this->apply_filters( 'is_plugin_update', $this->is_plugin_update() ) );
$this->store_connectivity_info( (object) array( 'is_active' => $is_active ), null );
return $this->_has_api_connection;
* @author Leo Fajardo (@leorw)
private function clear_connectivity_info() {
unset( $this->_storage->connectivity_test );
FS_Api::clear_force_http_flag();
* @author Vova Feldman (@svovaf)
* @param bool|null $is_connected
private function store_connectivity_info( $pong, $is_connected ) {
$this->_logger->entrance();
$version = $this->get_plugin_version();
if ( false === $is_connected || WP_FS__SIMULATE_FREEMIUS_OFF ) {
$is_active = ( isset( $pong->is_active ) && true == $pong->is_active );
$is_active = $this->apply_filters(
$this->is_plugin_update(),
$this->_storage->connectivity_test = array(
'is_connected' => $is_connected,
'host' => $_SERVER['HTTP_HOST'],
'server_ip' => WP_FS__REMOTE_ADDR,
'is_active' => $is_active,
'timestamp' => WP_FS__SCRIPT_START_TIME,
// Last version with connectivity attempt.
$this->_has_api_connection = $is_connected;
$this->_is_on = $is_active || ( WP_FS__DEV_MODE && $is_connected && ! WP_FS__SIMULATE_FREEMIUS_OFF );
* @author Leo Fajardo (@leorw)
* @param bool $is_connected
private function update_connectivity_info( $is_connected ) {
$this->store_connectivity_info(
// This is true since we update the connection info only after a successful opt-in or license activation which means that Freemius has already been on even before the process.
(object) array( 'is_active' => true ),
* Force turning Freemius on.
* @author Vova Feldman (@svovaf)
* @return bool TRUE if successfully turned on.
private function turn_on() {
$this->_logger->entrance();
if ( $this->is_on() || ! isset( $this->_storage->connectivity_test['is_active'] ) ) {
$updated_connectivity = $this->_storage->connectivity_test;
$updated_connectivity['is_active'] = true;
$updated_connectivity['timestamp'] = WP_FS__SCRIPT_START_TIME;
$this->_storage->connectivity_test = $updated_connectivity;
* Anonymous and unique site identifier (Hash).
* @author Vova Feldman (@svovaf)
* @param null|int $blog_id Since 2.0.0
function get_anonymous_id( $blog_id = null ) {
$unique_id = self::$_accounts->get_option( 'unique_id', null, $blog_id );
if ( empty( $unique_id ) || ! is_string( $unique_id ) ) {
$key = self::get_unfiltered_site_url( $blog_id, true );
$secure_auth = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
if ( empty( $secure_auth ) ||
false !== strpos( $secure_auth, ' ' ) ||
'put your unique phrase here' === $secure_auth
// Protect against default auth key.
$secure_auth = md5( microtime() );
* Base the unique identifier on the WP secure authentication key. Which
* turns the key into a secret anonymous identifier. This will help us
* to avoid duplicate installs generation on the backend upon opt-in.
* @author Vova Feldman (@svovaf)
$unique_id = md5( $key . $secure_auth );
self::$_accounts->set_option( 'unique_id', $unique_id, true, $blog_id );
$this->_logger->departure( $unique_id );
* Returns anonymous network ID.
function get_anonymous_network_id() {
return $this->get_anonymous_id( get_network()->site_id );
* @author Vova Feldman (@svovaf)
static function _get_current_wp_user() {
self::require_pluggable_essentials();
self::wp_cookie_constants();
return wp_get_current_user();
* Define cookie constants which are required by Freemius::_get_current_wp_user() since
* it uses wp_get_current_user() which needs the cookie constants set. When a plugin
* is network activated the cookie constants are only configured after the network
* plugins activation, therefore, if we don't define those constants WP will throw
* @author Vova Feldman (@svovaf)
private static function wp_cookie_constants() {
if ( defined( 'LOGGED_IN_COOKIE' ) &&
( defined( 'AUTH_COOKIE' ) || defined( 'SECURE_AUTH_COOKIE' ) )
* Used to guarantee unique hash cookies
if ( ! defined( 'COOKIEHASH' ) ) {
$siteurl = get_site_option( 'siteurl' );
define( 'COOKIEHASH', md5( $siteurl ) );
define( 'COOKIEHASH', '' );
if ( ! defined( 'LOGGED_IN_COOKIE' ) ) {
define( 'LOGGED_IN_COOKIE', 'wordpress_logged_in_' . COOKIEHASH );
if ( ! defined( 'AUTH_COOKIE' ) ) {
define( 'AUTH_COOKIE', 'wordpress_' . COOKIEHASH );
if ( ! defined( 'SECURE_AUTH_COOKIE' ) ) {
define( 'SECURE_AUTH_COOKIE', 'wordpress_sec_' . COOKIEHASH );
* @author Vova Feldman (@svovaf)
static function get_current_wp_user_id() {
$wp_user = self::_get_current_wp_user();
* @author Vova Feldman (@svovaf)
static function is_valid_email( $email ) {
if ( false === filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
$parts = explode( '@', $email );
if ( 2 !== count( $parts ) || empty( $parts[1] ) ) {
// Make sure domain is not one of the blacklisted.
foreach ( $blacklist as $invalid ) {
if ( 0 === strpos( $parts[1], $invalid ) ) {
// Get the UTF encoded domain name.
* @note - The check of `defined('...')` is there to account for PHP servers compiled with some older version of ICU where the constants are not defined.
$is_new_idn_available = (
version_compare( PHP_VERSION, '5.6.40') > 0 &&
defined( 'IDNA_DEFAULT' ) &&
defined( 'INTL_IDNA_VARIANT_UTS46' )
if ( $is_new_idn_available ) {
$domain = idn_to_ascii( $parts[1], IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46 );
$domain = idn_to_ascii( $parts[1] ); // phpcs:ignore PHPCompatibility.ParameterValues.NewIDNVariantDefault.NotSet
return ( checkdnsrr( $domain, 'MX' ) || checkdnsrr( $domain, 'A' ) );
#----------------------------------------------------------------------------------
#----------------------------------------------------------------------------------
* Generates and sends an HTML email with customizable sections.
* @author Leo Fajardo (@leorw)
* @param string $to_address
* @return bool Whether the email contents were sent successfully.
private function send_email(
$default_sections = $this->get_email_sections();
// Insert new sections or replace the default email sections.
if ( is_array( $sections ) && ! empty( $sections ) ) {
foreach ( $sections as $section_id => $custom_section ) {
if ( ! isset( $default_sections[ $section_id ] ) ) {
// If the section does not exist, add it.
$default_sections[ $section_id ] = $custom_section;
// If the section already exists, override it.