: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$registration_date = null;
if ( is_null( $site ) ) {
$url = self::get_unfiltered_site_url();
$name = get_bloginfo( 'name' );
$blog_id = self::get_site_blog_id( $site );
if ( get_current_blog_id() != $blog_id ) {
switch_to_blog( $blog_id );
if ( $site instanceof WP_Site ) {
$registration_date = $site->registered;
$url = self::get_unfiltered_site_url( $blog_id );
$name = get_bloginfo( 'name' );
if ( empty( $registration_date ) && $load_registration ) {
$blog_details = get_blog_details( $blog_id, false );
if ( is_object( $blog_details ) && isset( $blog_details->registered ) ) {
$registration_date = $blog_details->registered;
'uid' => $this->get_anonymous_id( $blog_id ),
// Add these diagnostic information only if user allowed to track.
if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) {
$info = array_merge( $info, array(
'language' => self::get_sanitized_language(),
if ( is_numeric( $blog_id ) ) {
$info['blog_id'] = $blog_id;
if ( ! empty( $registration_date ) ) {
$info[ 'registration_date' ] = $registration_date;
* Load the module's install based on the blog ID.
* @author Vova Feldman (@svovaf)
* @param int|null $blog_id
function get_install_by_blog_id( $blog_id = null ) {
$installs = self::get_all_sites( $this->_module_type, $blog_id );
$install = isset( $installs[ $this->_slug ] ) ? $installs[ $this->_slug ] : null;
if ( is_object( $install ) &&
is_numeric( $install->id ) &&
is_numeric( $install->user_id ) &&
FS_Plugin_Plan::is_valid_id( $install->plan_id )
$install = clone $install;
* Check if module is installed on a specified site.
* @author Vova Feldman (@svovaf)
* @param int|null $blog_id
function is_installed_on_site( $blog_id = null ) {
$installs = self::get_all_sites( $this->_module_type, $blog_id );
$install = isset( $installs[ $this->_slug ] ) ? $installs[ $this->_slug ] : null;
is_numeric( $install->id ) &&
is_numeric( $install->user_id ) &&
FS_Plugin_Plan::is_valid_id( $install->plan_id )
* Check if super-admin connected at least one site via the network opt-in.
* @author Vova Feldman (@svovaf)
function is_network_registered() {
if ( ! $this->_is_network_active ) {
return FS_User::is_valid_id( $this->_storage->network_user_id );
* Returns the main user associated with the network.
* @author Vova Feldman (@svovaf)
function get_network_user() {
if ( ! $this->_is_network_active ) {
return FS_User::is_valid_id( $this->_storage->network_user_id ) ?
self::_get_user_by_id( $this->_storage->network_user_id ) :
* Returns the current context user or the network's main user.
* @author Vova Feldman (@svovaf)
function get_current_or_network_user() {
return ( $this->_user instanceof FS_User ) ?
$this->get_network_user();
* Returns the main install associated with the network.
* @author Vova Feldman (@svovaf)
function get_network_install() {
if ( ! $this->_is_network_active ) {
return FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ?
$this->get_install_by_blog_id( $this->_storage->network_install_blog_id ) :
* Returns the blog ID that is associated with the main install.
* @author Leo Fajardo (@leorw)
function get_network_install_blog_id() {
if ( ! $this->_is_network_active ) {
return FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ?
$this->_storage->network_install_blog_id :
* Returns the current context install or the network's main install.
* @author Vova Feldman (@svovaf)
function get_current_or_network_install() {
return ( $this->_site instanceof FS_Site ) ?
$this->get_network_install();
* Check if executing a site level action from the network level admin.
* @author Vova Feldman (@svovaf)
* @return false|int If yes, return the requested blog ID.
private function is_network_level_site_specific_action() {
if ( ! $this->_is_network_active ) {
if ( ! fs_is_network_admin() ) {
$blog_id = fs_request_get( 'blog_id', '' );
return is_numeric( $blog_id ) ? $blog_id : false;
* Check if executing an action from the network level admin.
* @author Vova Feldman (@svovaf)
private function is_network_level_action() {
return ( $this->_is_network_active && fs_is_network_admin() );
* Needs to be executed after site deactivation, archive, deletion, or flag as spam.
* The logic updates the network level user and blog, and reschedule the crons if the cron executing site matching the site that is no longer publicly active.
* @author Vova Feldman (@svovaf)
* @param int $context_blog_id
private function update_multisite_data_after_site_deactivation( $context_blog_id = 0 ) {
$this->_logger->entrance();
if ( $this->_is_network_active ) {
if ( $context_blog_id == $this->_storage->network_install_blog_id ) {
$installs_map = $this->get_blog_install_map();
foreach ( $installs_map as $blog_id => $install ) {
if ( $context_blog_id == $blog_id ) {
if ( $install->user_id != $this->_storage->network_user_id ) {
// Switch reference to a blog that is opted-in and belong to the same super-admin.
$this->_storage->network_install_blog_id = $blog_id;
if ( ! $this->is_registered() ) {
if ( $this->is_sync_cron_scheduled() &&
$context_blog_id == $this->get_sync_cron_blog_id()
$this->schedule_sync_cron( WP_FS__SCRIPT_START_TIME, true, $context_blog_id );
if ( $this->is_install_sync_scheduled() &&
$context_blog_id == $this->get_install_sync_cron_blog_id()
$this->schedule_install_sync( $context_blog_id );
* Executed after site deactivation, archive, or flag as spam.
* @author Vova Feldman (@svovaf)
* @param int $context_blog_id
public function _after_site_deactivated_callback( $context_blog_id = 0 ) {
$this->_logger->entrance();
$install = $this->get_install_by_blog_id( $context_blog_id );
if ( ! is_object( $install ) ) {
$this->update_multisite_data_after_site_deactivation( $context_blog_id );
if ( ! $this->is_registered() ) {
$current_blog_id = get_current_blog_id();
$this->switch_to_blog( $context_blog_id );
// Send deactivation event.
$this->sync_install( array(
$this->switch_to_blog( $current_blog_id );
* Executed after site deletion.
* @author Vova Feldman (@svovaf)
* @param int $context_blog_id
* @param bool $drop True if site's database tables should be dropped. Default is false.
public function _after_site_deleted_callback( $context_blog_id = 0, $drop = false ) {
$this->_logger->entrance();
$install = $this->get_install_by_blog_id( $context_blog_id );
if ( ! is_object( $install ) ) {
$this->update_multisite_data_after_site_deactivation( $context_blog_id );
if ( ! $this->is_registered() ) {
$current_blog_id = get_current_blog_id();
$this->switch_to_blog( $context_blog_id );
// Delete install if dropping site DB.
$this->delete_account_event();
// Send deactivation event.
$this->sync_install( array(
$this->switch_to_blog( $current_blog_id );
* Executed after site deletion, called from wp_delete_site
* @author Dario Curvino (@dudo)
* @param WP_Site $old_site
public function _after_wpsite_deleted_callback( WP_Site $old_site ) {
$this->_logger->entrance();
$this->_after_site_deleted_callback( $old_site->blog_id, true );
* Executed after site re-activation.
* @author Vova Feldman (@svovaf)
* @param int $context_blog_id
public function _after_site_reactivated_callback( $context_blog_id = 0 ) {
$this->_logger->entrance();
$install = $this->get_install_by_blog_id( $context_blog_id );
if ( ! is_object( $install ) ) {
if ( ! self::is_site_active( $context_blog_id ) ) {
// Site not yet active (can be in spam mode, archived, deleted...).
$current_blog_id = get_current_blog_id();
$this->switch_to_blog( $context_blog_id );
// Send re-activation event.
$this->sync_install( array(
$this->switch_to_blog( $current_blog_id );
* @author Leo Fajardo (@leorw)
private function admin_url( $path = '', $scheme = 'admin', $network = true ) {
return ( $this->_is_network_active && $network ) ?
network_admin_url( $path, $scheme ) :
admin_url( $path, $scheme );
* Check if currently in a specified admin page.
* @author Vova Feldman (@svovaf)
function is_admin_page( $page ) {
return ( $this->_menu->get_slug( $page ) === fs_request_get( 'page', '', 'get' ) );
* Check if currently in the product's main admin page.
* @author Vova Feldman (@svovaf)
function is_main_admin_page() {
return $this->is_admin_page( '' );
* Get module's main admin setting page URL.
* @author Vova Feldman (@svovaf)
function main_menu_url() {
return $this->_menu->main_menu_url();
* Check if currently on the theme's setting page or
* on any of the Freemius added pages (via tabs).
* @author Vova Feldman (@svovaf)
* @deprecated Please use is_product_settings_page() instead;
function is_theme_settings_page() {
return $this->is_product_settings_page();
* Check if currently on the product's main setting page or on any of the Freemius added pages (via tabs).
* @author Vova Feldman (@svovaf)
function is_product_settings_page() {
$page = fs_request_get( 'page', '', 'get' );