: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
return $this->is_api_result_entity( $result ) ?
new FS_Plugin_Plan( $result ) :
* @author Vova Feldman (@svovaf)
* @param number|bool $plugin_id
* @param number|bool $site_license_id
* @param array $foreign_licenses @since 2.0.0. This is used by network-activated plugins.
* @param number|null $blog_id
* @return FS_Plugin_License[]|object
private function _fetch_licenses(
$site_license_id = false,
$foreign_licenses = array(),
$this->_logger->entrance();
$api = $this->get_api_user_scope();
if ( ! is_numeric( $plugin_id ) ) {
$plugin_id = $this->_plugin->id;
$user_licenses_endpoint = "/plugins/{$plugin_id}/licenses.json?is_enriched=true";
if ( ! empty ( $foreign_licenses ) ) {
$foreign_licenses = array(
// Prefix with `+` to tell the server to include foreign licenses in the licenses collection.
'ids' => ( urlencode( '+' ) . implode( ',', $foreign_licenses['ids'] ) ),
'license_keys' => implode( ',', array_map( 'urlencode', $foreign_licenses['license_keys'] ) )
$user_licenses_endpoint = add_query_arg( $foreign_licenses, $user_licenses_endpoint );
$result = $api->get( $user_licenses_endpoint, true );
$is_site_license_synced = false;
if ( $this->is_api_result_object( $result, 'licenses' ) &&
is_array( $result->licenses )
for ( $i = 0, $len = count( $result->licenses ); $i < $len; $i ++ ) {
$result->licenses[ $i ] = new FS_Plugin_License( $result->licenses[ $i ] );
if ( ( ! $is_site_license_synced ) && is_numeric( $site_license_id ) ) {
$is_site_license_synced = ( $site_license_id == $result->licenses[ $i ]->id );
$result = $result->licenses;
if ( ! $is_site_license_synced ) {
if ( ! is_null( $blog_id ) ) {
* If blog ID is not null, the request is for syncing of the license of a single site via the
* network-level "Account" page.
* @author Leo Fajardo (@leorw)
$this->switch_to_blog( $blog_id );
$api = $this->get_api_site_scope();
if ( is_numeric( $site_license_id ) ) {
// Try to retrieve a foreign license that is linked to the install.
$api_result = $api->call( '/licenses.json?is_enriched=true' );
if ( $this->is_api_result_object( $api_result, 'licenses' ) &&
is_array( $api_result->licenses )
$licenses = $api_result->licenses;
if ( ! empty( $licenses ) ) {
$result[] = new FS_Plugin_License( $licenses[0] );
$api_errors[] = $api_result;
is_object( $this->_license ) &&
* Sync only if the license belongs to the context plugin. `$plugin_id` can be an add-on ID while
* the FS instance that does the syncing is the parent FS instance.
* @author Leo Fajardo (@leorw)
$this->_license->plugin_id == $plugin_id
$is_license_in_result = false;
if ( ! empty( $result ) ) {
foreach ( $result as $license ) {
if ( $license->id == $this->_license->id ) {
$is_license_in_result = true;
if ( ! $is_license_in_result ) {
// Fetch foreign license by ID and license key.
$license = $api->get( "/licenses/{$this->_license->id}.json?license_key=" .
urlencode( $this->_license->secret_key ) . '&is_enriched=true' );
if ( $this->is_api_result_entity( $license ) ) {
$result[] = new FS_Plugin_License( $license );
$api_errors[] = $license;
if ( ! is_null( $blog_id ) ) {
$this->switch_to_blog( $this->_storage->network_install_blog_id );
if ( is_array( $result ) && 0 < count( $result ) ) {
// If found at least one license, return license collection even if there are errors.
if ( ! empty( $api_errors ) ) {
// If found any errors and no licenses, return first error.
// Fallback to empty licenses list.
* @author Vova Feldman (@svovaf)
* @param number $license_id
* @param string $license_key
* @return \FS_Plugin_License|object
private function fetch_license_by_key( $license_id, $license_key ) {
$this->_logger->entrance();
$api = $this->get_current_or_network_user_api_scope();
$result = $api->get( "/licenses/{$license_id}.json?license_key=" . urlencode( $license_key ) );
return $this->is_api_result_entity( $result ) ?
new FS_Plugin_License( $result ) :
* @author Vova Feldman (@svovaf)
* @param number|bool $plugin_id
* @return FS_Payment[]|object
function _fetch_payments( $plugin_id = false, $flush = false ) {
$this->_logger->entrance();
$api = $this->get_api_user_scope();
if ( ! is_numeric( $plugin_id ) ) {
$plugin_id = $this->_plugin->id;
is_object( $this->_plugin ) &&
FS_Plugin::is_valid_id( $this->_plugin->bundle_id )
"/plugins/{$plugin_id}/payments.json?include_addons=true" . ($include_bundles ? '&include_bundles=true' : ''),
if ( ! isset( $result->error ) ) {
for ( $i = 0, $len = count( $result->payments ); $i < $len; $i ++ ) {
$result->payments[ $i ] = new FS_Payment( $result->payments[ $i ] );
$result = $result->payments;
* @author Vova Feldman (@svovaf)
* @return \FS_Billing|mixed
function _fetch_billing( $flush = false ) {
require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-billing.php';
$billing = $this->get_api_user_scope()->get( 'billing.json', $flush );
if ( $this->is_api_result_entity( $billing ) ) {
$billing = new FS_Billing( $billing );
* @author Vova Feldman (@svovaf)
* @param FS_Plugin_License[] $licenses
* @param number $module_id
private function _update_licenses( $licenses, $module_id ) {
$this->_logger->entrance();
if ( is_array( $licenses ) ) {
for ( $i = 0, $len = count( $licenses ); $i < $len; $i ++ ) {
$licenses[ $i ]->updated = time();
$this->_store_licenses( true, $module_id, $licenses );
* @author Vova Feldman (@svovaf)
* @param bool|number $plugin_id
* @param bool $flush Since 1.1.7.3
* @param int $expiration Since 1.2.2.7
* @param bool|string $newer_than Since 2.2.1
* @return object|false New plugin tag info if exist.
private function _fetch_newer_version( $plugin_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false ) {
$latest_tag = $this->_fetch_latest_version( $plugin_id, $flush, $expiration, $newer_than );
if ( ! is_object( $latest_tag ) ) {
$plugin_version = $this->get_plugin_version();
// Check if version is actually newer.
// If it's an non-installed add-on then always return latest.
( $this->_is_addon_id( $plugin_id ) && ! $this->is_addon_activated( $plugin_id ) ) ||
version_compare( $plugin_version, $latest_tag->version, '<' );
$this->_logger->departure( $has_new_version ? 'Found newer plugin version ' . $latest_tag->version : 'No new version' );
$is_latest_version_beta = ( 'beta' === $latest_tag->release_mode );
$this->_storage->beta_data = array(
'is_beta' => $is_latest_version_beta,
'version' => $latest_tag->version
return $has_new_version ? $latest_tag : false;
* @author Vova Feldman (@svovaf)
* @param bool|number $plugin_id
* @param bool $flush Since 1.1.7.3
* @param int $expiration Since 1.2.2.7
* @param bool|string $newer_than Since 2.2.1
* @return bool|FS_Plugin_Tag
function get_update( $plugin_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false ) {
$this->_logger->entrance();
if ( ! is_numeric( $plugin_id ) ) {
$plugin_id = $this->_plugin->id;
$this->check_updates( true, $plugin_id, $flush, $expiration, $newer_than );
$updates = $this->get_all_updates();
return isset( $updates[ $plugin_id ] ) && is_object( $updates[ $plugin_id ] ) ? $updates[ $plugin_id ] : false;
* Check if site assigned with active license.
* @author Vova Feldman (@svovaf)
* @deprecated Please use has_active_valid_license() instead because license can be cancelled.
function has_active_license() {
is_object( $this->_license ) &&
is_numeric( $this->_license->id ) &&
! $this->_license->is_expired()
* Check if site assigned with active & valid (not expired) license.
* @author Vova Feldman (@svovaf)
* @param bool $check_expiration
function has_active_valid_license( $check_expiration = true ) {
return self::is_active_valid_license( $this->_license, $check_expiration );
* @author Leo Fajardo (@leorw)
function is_data_debug_mode() {
if ( is_null( $this->is_whitelabeled ) || ! $this->is_whitelabeled ) {
$fs = $this->is_addon() ?
$this->get_parent_instance() :
if ( $fs->is_network_active() && fs_is_network_admin() ) {
$is_developer_license_debug_mode = get_site_transient( "fs_{$this->get_id()}_data_debug_mode" );
$is_developer_license_debug_mode = get_transient( "fs_{$this->get_id()}_data_debug_mode" );
return ( 'true' === $is_developer_license_debug_mode );
* @author Leo Fajardo (@leorw)
function _set_data_debug_mode() {
if ( ! $this->is_whitelabeled( true ) ) {
$license_or_user_key = fs_request_get_raw( 'license_or_user_key' );
$transient_value = ( ! empty( $license_or_user_key ) ) ?
if ( 'true' === $transient_value ) {
$stored_key = $this->_storage->get( ! FS_User::is_valid_id( $this->_storage->last_license_user_id ) ?
if ( md5( $license_or_user_key ) !== $stored_key ) {
$this->shoot_ajax_failure( sprintf(
$this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ),
'seems like the key you entered doesn\'t match our records.',
'developer-or-license-not-found'
if ( $this->is_network_active() && fs_is_network_admin() ) {
"fs_{$this->get_id()}_data_debug_mode",
WP_FS__TIME_24_HOURS_IN_SEC / 24
"fs_{$this->get_id()}_data_debug_mode",
WP_FS__TIME_24_HOURS_IN_SEC / 24
if ( 'true' === $transient_value ) {
$this->_admin_notices->add_sticky(
'Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.',
'data_debug_mode_enabled'
'data_debug_mode_enabled'
$this->shoot_ajax_success();
* Check if a given license is active & valid (not expired).
* @author Vova Feldman (@svovaf)
* @param FS_Plugin_License $license
* @param bool $check_expiration
private static function is_active_valid_license( $license, $check_expiration = true ) {
FS_Plugin_License::is_valid_id( $license->id ) &&
( ! $check_expiration || $license->is_valid() )
* Checks if there's any site that is associated with an active & valid license.
* This logic is used to determine if the admin can download the premium code base from a network level admin.
* @author Vova Feldman (@svovaf)
function has_any_active_valid_license() {
if ( ! fs_is_network_admin() ) {
return $this->has_active_valid_license();
$installs = $this->get_blog_install_map();
$all_plugin_licenses = self::get_all_licenses( $this->_module_id );
foreach ( $installs as $blog_id => $install ) {
if ( ! FS_Plugin_License::is_valid_id( $install->license_id ) ) {
foreach ( $all_plugin_licenses as $license ) {
if ( $license->id == $install->license_id ) {
if ( self::is_active_valid_license( $license ) ) {
* Check if site assigned with license with enabled features.
* @author Vova Feldman (@svovaf)
function has_features_enabled_license() {
is_object( $this->_license ) &&
is_numeric( $this->_license->id ) &&
$this->_license->is_features_enabled()
* Checks if the product is activated with a bundle license.
* @author Leo Fajardo (@leorw)
function is_activated_with_bundle_license() {
if ( ! $this->has_features_enabled_license() ) {