: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
private function activate_license(
$is_marketing_allowed = null,
$license_owner_id = null,
$is_extensions_tracking_allowed = null,
$is_diagnostic_tracking_allowed = null
$this->_logger->entrance();
$license_key = trim( $license_key );
$is_network_activation_or_migration = (
( ! empty( $sites ) && $this->is_migration() )
if ( ! $is_network_activation_or_migration ) {
// If the license activation is executed outside the context of a network admin, ignore the sites collection.
$fs = ( empty($plugin_id) || $plugin_id == $this->_module_id ) ?
$this->get_addon_instance( $plugin_id );
FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array(
FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed,
FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed,
$has_valid_blog_id = is_numeric( $blog_id );
if ( $fs->is_addon() && $fs->get_parent_instance()->is_registered() ) {
* When activating an add-on's license and the parent is opted-in, activate the license with the parent's opted-in user context.
* @author Vova Feldman (@svovaf)
$user = $fs->get_parent_instance()->get_current_or_network_user();
} else if ( $fs->is_registered() ) {
$user = $fs->get_current_or_network_user();
if ( $has_valid_blog_id ) {
* If a specific blog ID was provided, activate the license only on the specific blog that is associated with the given blog ID.
* @author Leo Fajardo (@leorw)
$fs->switch_to_blog( $blog_id );
if ( is_object( $user ) ) {
if ( $is_network_activation_or_migration && ! $has_valid_blog_id ) {
// If no specific blog ID was provided, activate the license for all sites in the network.
$blog_2_install_map = array();
foreach ( $sites as $site ) {
if ( ! isset( $site['blog_id'] ) || ! is_numeric( $site['blog_id'] ) ) {
$install = $fs->get_install_by_blog_id( $site['blog_id'] );
if ( is_object( $install ) ) {
$blog_2_install_map[ $site['blog_id'] ] = $install;
$site_ids[] = $site['blog_id'];
if ( ! empty( $blog_2_install_map ) ) {
$result = $fs->activate_license_on_many_installs( $user, $license_key, $blog_2_install_map );
if ( true === $result && ! empty( $site_ids ) ) {
$result = $fs->activate_license_on_many_sites( $user, $license_key, $site_ids );
if ( $fs->is_registered() ) {
'license_key' => $fs->apply_filters( 'license_key', $license_key )
$change_owner = FS_User::is_valid_id( $license_owner_id );
$params['user_id'] = $license_owner_id;
$installs_info_by_slug_map = $fs->get_parent_and_addons_installs_info();
foreach ( $installs_info_by_slug_map as $slug => $install_info ) {
$install_ids[ $slug ] = $install_info['install']->id;
$params['install_ids'] = implode( ',', array_values( $install_ids ) );
$api = $fs->get_api_site_scope();
$result = $api->call( $fs->add_show_pending( '/' ), 'put', $params );
if ( ! FS_Api::is_api_error( $result ) ) {
$fs->reconnect_locally( $has_valid_blog_id );
// If successful ownership change.
$fs->get_user()->id != $install->user_id
$fs->complete_ownership_change_by_license( $install->user_id, $install_ids );
} else /* ( $fs->is_addon() && $fs->get_parent_instance()->is_registered() ) */ {
$result = $fs->activate_license_on_site( $user, $license_key );
if ( true !== $result && ! FS_Api::is_api_result_entity( $result ) ) {
if ( FS_Api::is_blocked( $result ) ) {
$result->error->message = $this->generate_api_blocked_notice_message_from_result( $result );
$error = FS_Api::is_api_error_object( $result ) ?
$result->error->message :
var_export( $result, true );
$fs->network_upgrade_mode_completed();
if ( fs_is_network_admin() && ! $has_valid_blog_id ) {
$fs->_site = $fs->get_network_install();
$fs->_sync_license( true, $has_valid_blog_id );
$this->maybe_sync_install_user();
$next_page = $fs->is_addon() ?
$fs->get_parent_instance()->get_account_url() :
$fs->get_after_activation_url( 'after_connect_url' );
$next_page = $fs->opt_in(
if ( isset( $next_page->error ) ) {
$error = $next_page->error;
if ( $is_network_activation_or_migration ) {
* Get the list of sites that were just opted-in (and license activated).
* This is an optimization for the next part below saving some DB queries.
$connected_sites = array();
foreach ( $sites as $site ) {
if ( isset( $site['blog_id'] ) && is_numeric( $site['blog_id'] ) ) {
$connected_sites[ $site['blog_id'] ] = true;
$all_sites = self::get_sites();
$pending_blog_ids = array();
* Check if there are any sites that are not connected, skipped, nor delegated. For every site that falls into that category, if the product is freemium, skip the connection. If the product is premium only, delegate the connection to the site administrator.
* @author Vova Feldman (@svovaf)
foreach ( $all_sites as $site ) {
$blog_id = self::get_site_blog_id( $site );
if ( isset( $connected_sites[ $blog_id ] ) ) {
// Site was just connected.
if ( $fs->is_installed_on_site( $blog_id ) ) {
// Site was already connected before.
if ( $fs->is_site_delegated_connection( $blog_id ) ) {
// Site's connection was delegated.
if ( $fs->is_anonymous_site( $blog_id ) ) {
// Site connection was already skipped.
$pending_blog_ids[] = $blog_id;
if ( ! empty( $pending_blog_ids ) ) {
if ( $fs->is_freemium() && $fs->is_enable_anonymous() ) {
$fs->skip_connection( $pending_blog_ids );
$fs->delegate_connection( $pending_blog_ids );
if ( false === $error && true === $fs->_storage->require_license_activation ) {
$fs->_storage->require_license_activation = false;
'success' => ( false === $error )
if ( false !== $error ) {
$result['error'] = $fs->apply_filters( 'opt_in_error_message', $error );
if ( $fs->is_addon() || $fs->has_addons() ) {
* Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded,
* an updated valid user licenses collection will be fetched from the server which is used to also
* update the account add-ons (add-ons the user has licenses for).
* @author Leo Fajardo (@leorw)
$fs->purge_valid_user_licenses_cache();
$result['next_page'] = $next_page;
* @author Leo Fajardo (@leorw)
* @key string Product slug.
* @property FS_Site $site
* @property FS_Plugin_License $license
private function get_parent_and_addons_installs_info() {
$fs = $this->is_addon() ?
$this->get_parent_instance() :
$installed_addons_ids = array();
$installed_addons_instances = $fs->get_installed_addons();
foreach ( $installed_addons_instances as $instance ) {
$installed_addons_ids[] = $instance->get_id();
$addons_ids = array_unique( array_merge(
$fs->get_updated_account_addons()
// Add parent product info.
$installs_info_by_slug_map = array(
$fs->get_slug() => array(
'install' => $fs->get_site(),
'license' => $fs->_get_license()
foreach ( $addons_ids as $addon_id ) {
$is_installed = isset( $installed_addons_ids_map[ $addon_id ] );
$addon_info = $fs->_get_addon_info( $addon_id, $is_installed );
if ( ! isset( $addon_info['is_connected'] ) || ! $addon_info['is_connected'] ) {
// Add-on is not associated with an install entity.
$installs_info_by_slug_map[ $addon_info['slug'] ] = array(
'install' => $addon_info['site'],
'license' => isset( $addon_info['license'] ) ?
return $installs_info_by_slug_map;
* @author Leo Fajardo (@leorw)
function _network_activate_ajax_action() {
$this->_logger->entrance();
$this->check_ajax_referer( 'network_activate' );
$plugin_id = fs_request_get( 'module_id', '', 'post' );
$fs = ( $plugin_id == $this->_module_id ) ?
$this->get_addon_instance( $plugin_id );
$sites = fs_request_get( 'sites', array(), 'post' );
if ( is_array( $sites ) && ! empty( $sites ) ) {
$sites_by_action = array(
foreach ( $sites as $site ) {
$sites_by_action[ $site['action'] ][] = $site;
$total_sites = count( $sites );
$total_sites_to_delegate = count( $sites_by_action['delegate'] );
$has_any_install = fs_request_get_bool( 'has_any_install' );
if ( $total_sites === $total_sites_to_delegate &&
! $this->is_network_upgrade_mode() &&
$this->delegate_connection();
if ( ! empty( $sites_by_action['delegate'] ) ) {
$this->delegate_connection( self::get_sites_blog_ids( $sites_by_action['delegate'] ) );
if ( ! empty( $sites_by_action['skip'] ) ) {
$this->skip_connection( self::get_sites_blog_ids( $sites_by_action['skip'] ) );
if ( empty( $sites_by_action['allow'] ) ) {
if ( $has_any_install ) {
$first_install = $fs->find_first_install();
if ( ! is_null( $first_install ) ) {
$fs->_site = $first_install['install'];
$fs->_storage->network_install_blog_id = $first_install['blog_id'];
$fs->_user = self::_get_user_by_id( $fs->_site->user_id );
$fs->_storage->network_user_id = $fs->_user->id;
if ( ! $fs->is_registered() || ! $this->_is_network_active ) {
$next_page = $fs->opt_in(
fs_request_get_bool( 'is_marketing_allowed', null ),
$sites_by_action['allow']
$next_page = $fs->install_with_user(
$this->get_network_user(),
$sites_by_action['allow']
if ( is_object( $next_page ) && isset( $next_page->error ) ) {
$error = $next_page->error;
if ( empty( $next_page ) ) {
$next_page = $this->get_after_activation_url( 'after_network_activation_url' );
$error = $this->get_text_inline( 'Invalid site details collection.', 'invalid_site_details_collection' );
'success' => ( false === $error )
if ( false !== $error ) {
$result['error'] = $error;
$result['next_page'] = $next_page;
echo json_encode( $result );
* Billing update AJAX callback.
* @author Vova Feldman (@svovaf)
function _update_billing_ajax_action() {
$this->_logger->entrance();
$this->check_ajax_referer( 'update_billing' );
if ( ! $this->is_user_admin() ) {
self::shoot_ajax_failure();
$billing = fs_request_get( 'billing' );
$api = $this->get_api_user_scope();
$result = $api->call( '/billing.json', 'put', array_merge( $billing, array(
'plugin_id' => $this->get_parent_id(),
if ( ! $this->is_api_result_entity( $result ) ) {
self::shoot_ajax_failure();
$this->get_api_user_scope()->purge_cache( 'billing.json' );
self::shoot_ajax_success();
* Trial start for anonymous users (AJAX callback).
* @author Vova Feldman (@svovaf)
function _start_trial_ajax_action() {
$this->_logger->entrance();
$this->check_ajax_referer( 'start_trial' );
if ( ! $this->is_user_admin() ) {
self::shoot_ajax_failure();
$trial_data = fs_request_get( 'trial' );
$next_page = $this->opt_in(
if ( is_object( $next_page ) && $this->is_api_error( $next_page ) ) {