: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( $this->apply_filters( 'has_paid_plan_account', $this->has_paid_plan() ) ) {
switch ( $plan_change ) {
if ( ! $background && is_admin() ) {
$plan = $this->is_trial() ?
$this->get_trial_plan() :
if ( $plan->is_free() ) {
$this->_admin_notices->add(
$this->get_text_inline( 'It looks like you are still on the %s plan. If you did upgrade or change your plan, it\'s probably an issue on our side - sorry.', 'plan-did-not-change-message' ),
'<i><b>' . $plan->title . ( $this->is_trial() ? ' ' . $this->get_text_x_inline( 'Trial', 'trial period', 'trial' ) : '' ) . '</b></i>'
sprintf( $this->get_text_inline( 'I have upgraded my account but when I try to Sync the License, the plan remains %s.', 'plan-did-not-change-email-message' ),
strtoupper( $plan->name )
$this->get_text_inline( 'Please contact us here', 'contact-us-here' )
$this->add_after_plan_activation_or_upgrade_instructions_notice( 'upgraded' === $plan_change );
$this->_admin_notices->remove_sticky( array(
$this->_admin_notices->add_sticky(
$this->get_text_inline( 'Your plan was successfully changed to %s.', 'plan-changed-to-x-message' ),
$this->_admin_notices->remove_sticky( array(
$this->_admin_notices->add_sticky(
($this->has_free_plan() ?
sprintf( $this->get_text_inline( 'Your license has expired. You can still continue using the free %s forever.', 'license-expired-blocking-message' ), $this->_module_type ) :
/* translators: %1$s: product title; %2$s, %3$s: wrapping HTML anchor element; %4$s: 'plugin', 'theme', or 'add-on'. */
sprintf( $this->get_text_inline( 'Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.', 'license-expired-blocking-message_premium-only' ), sprintf('<a href="%s">', $this->pricing_url()), '</a>', $this->get_module_label(true) ) ),
$this->_admin_notices->remove_sticky( 'plan_upgraded' );
$this->_admin_notices->add(
$this->get_text_inline( 'Your license has been cancelled. If you think it\'s a mistake, please contact support.', 'license-cancelled' ) . ' ' .
$this->contact_url( 'bug' ),
$this->get_text_inline( 'Please contact us here', 'contact-us-here' )
$this->_admin_notices->remove_sticky( 'plan_upgraded' );
$this->_admin_notices->add_sticky(
sprintf( $this->get_text_inline( 'Your license has expired. You can still continue using all the %s features, but you\'ll need to renew your license to continue getting updates and support.', 'license-expired-non-blocking-message' ), $this->get_plan()->title ),
$this->_storage->expired_license_notice_shown = WP_FS__SCRIPT_START_TIME;
$this->_admin_notices->remove_sticky( 'plan_upgraded' );
$this->add_complete_upgrade_instructions_notice(
$this->get_text_inline( 'Your trial has been successfully started.', 'trial-started-message' ),
'<i>' . $this->get_plugin_name() . '</i>'
$this->get_trial_plan()->title
$this->_admin_notices->remove_sticky( array(
$this->_admin_notices->add_sticky(
($this->has_free_plan() ?
$this->get_text_inline( 'Your free trial has expired. You can still continue using all our free features.', 'trial-expired-message' ) :
/* translators: %1$s: product title; %2$s, %3$s: wrapping HTML anchor element; %4$s: 'plugin', 'theme', or 'add-on'. */
sprintf( $this->get_text_inline( 'Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.', 'trial-expired-message_premium-only' ), sprintf('<a href="%s">', $this->pricing_url()), '</a>', $this->get_module_label(true))),
$this->_admin_notices->remove_sticky( array(
if ( 'none' !== $plan_change ) {
! is_object( $this->_license ) ||
! $this->_license->is_whitelabeled
$this->_admin_notices->remove_sticky( 'license_whitelabeled' );
$this->do_action( 'after_license_change', $plan_change, $this->get_plan() );
* @author Leo Fajardo (@leorw)
private function generate_api_blocked_notice_message_from_result( $result ) {
$api_domains = $this->apply_filters( 'api_domains', array(
$api_domains_list_items = '';
foreach( $api_domains as $api_domain ) {
$api_domains_list_items .= "<li>{$api_domain}</li>";
$error_message = sprintf(
$this->get_text_inline( 'Your server is blocking the access to Freemius\' API, which is crucial for %1$s synchronization. Please contact your host to whitelist the following domains:%2$s', 'server-blocking-access' ),
$this->get_plugin_name(),
"<ol>{$api_domains_list_items}</ol><a href='#' class='fs-api-request-error-show-details-link'>" . $this->get_text_inline( 'Show error details', 'show-error-details' ) . " <span class='dashicons dashicons-arrow-down-alt2'></span></a>"
"<div>{$error_message}</div>" .
'<div class="fs-api-request-error-details" style="display: none">' .
'<strong>' . $this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . '</strong><br>' .
$result->error->message .
* Include the required JS at the footer of the admin to trigger the license activation dialog box.
* @author Vova Feldman (@svovaf)
public function _open_license_activation_dialog_box() {
$vars = array( 'license_id' => $this->_site->license_id );
fs_require_once_template( 'js/open-license-activation.php', $vars );
* @author Vova Feldman (@svovaf)
* @param bool $background
* @param FS_Plugin_License|null $premium_license
protected function _activate_license( $background = false, $premium_license = null ) {
$this->_logger->entrance();
if ( is_null( $premium_license ) ) {
$license_id = fs_request_get( 'license_id' );
if ( is_object( $this->_site ) &&
FS_Plugin_License::is_valid_id( $license_id ) &&
$license_id == $this->_site->license_id
// License is already activated.
$premium_license = FS_Plugin_License::is_valid_id( $license_id ) ?
$this->_get_license_by_id( $license_id ) :
$this->_get_available_premium_license();
if ( ! is_object( $premium_license ) ) {
if ( ! is_object( $this->_site ) ) {
$user = $this->get_current_or_network_user();
if ( ! is_object( $user ) ) {
$user = self::_get_user_by_id( $premium_license->user_id );
if ( is_object( $user ) ) {
$this->install_with_user( $user, $premium_license->secret_key, false, false, false );
$premium_license->secret_key
* If the premium license is already associated with the install, just
* update the license reference (activation is not required).
if ( $premium_license->id == $this->_site->license_id ) {
// License is already activated.
$this->_update_site_license( $premium_license );
if ( $this->_site->user_id != $premium_license->user_id ) {
$api_request_params = array( 'license_key' => $premium_license->secret_key );
$api_request_params = array();
$api = $this->get_api_site_scope();
$license = $api->call( "/licenses/{$premium_license->id}.json?is_enriched=true", 'put', $api_request_params );
if ( ! $this->is_api_result_entity( $license ) ) {
$this->_admin_notices->add( sprintf(
$this->get_text_inline( 'It looks like the license could not be activated.', 'license-activation-failed-message' ),
( is_object( $license ) && isset( $license->error ) ?
$license->error->message :
sprintf( '%s<br><code>%s</code>',
$this->get_text_inline( 'Error received from the server:', 'server-error-message' ),
var_export( $license, true )
$this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...',
$premium_license = new FS_Plugin_License( $license );
$site = $this->get_api_site_scope()->get( '/', true );
if ( $this->is_api_result_entity( $site ) ) {
$this->_site = new FS_Site( $site );
$this->_update_site_license( $premium_license );
if ( $this->is_addon() || $this->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)
$this->purge_valid_user_licenses_cache();
$this->add_complete_upgrade_instructions_notice(
$this->get_text_inline( 'Your license was successfully activated.', 'license-activated-message' ),
$this->_admin_notices->remove_sticky( array(
* @author Vova Feldman (@svovaf)
* @param bool $show_notice
protected function _deactivate_license( $show_notice = true ) {
$this->_logger->entrance();
$hmm_text = $this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...';
if ( ! FS_Plugin_License::is_valid_id( $this->_site->license_id ) ) {
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'It looks like your site currently doesn\'t have an active license.', 'no-active-license-message' ), $this->get_plan_title() ),
$api = $this->get_api_site_scope();
$license = $api->call( "/licenses/{$this->_site->license_id}.json", 'delete' );
$this->handle_license_deactivation_result( $license, $hmm_text, $show_notice );
* @author Leo Fajardo (@leorw)
* @param FS_Plugin_License $license
* @param bool|string $hmm_text
* @param bool $show_notice
private function handle_license_deactivation_result( $license, $hmm_text = false, $show_notice = true ) {
if ( isset( $license->error ) ) {
$this->_admin_notices->add(
$this->get_text_inline( 'It looks like the license deactivation failed.', 'license-deactivation-failed-message' ) . '<br> ' .
$this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . ' ' . var_export( $license->error, true ),
if ( is_array( $this->_licenses ) ) {
for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) {
if ( $license->id == $this->_licenses[ $i ]->id ) {
$this->_licenses[ $i ] = new FS_Plugin_License( $license );
// Update site plan to default.
$this->_site->plan_id = $this->_plans[0]->id;
// Unlink license from site.
$this->_update_site_license( null );
$this->_admin_notices->add(
sprintf( $this->is_only_premium() ?
$this->get_text_inline( 'Your %s license was successfully deactivated.', 'license-deactivation-message_premium-only' ) :
$this->get_text_inline( 'Your license was successfully deactivated, you are back to the %s plan.', 'license-deactivation-message' ),
$this->get_text_inline( 'O.K', 'ok' )
$this->_admin_notices->remove_sticky( array(
* @author Vova Feldman (@svovaf)
private function _downgrade_site() {
$this->_logger->entrance();
$deactivate_license = fs_request_get_bool( 'deactivate_license' );
$api = $this->get_api_site_scope();
$site = $api->call( 'downgrade.json', 'put', array( 'deactivate_license' => $deactivate_license ) );
$plan_downgraded = false;
if ( $this->is_api_result_entity( $site ) ) {
$prev_plan_id = $this->_site->plan_id;
// Update new site plan id.
$this->_site->plan_id = $site->plan_id;
$plan = $this->get_plan();
$subscription = $this->_sync_site_subscription( $this->_license );
// Plan downgraded if plan was changed or subscription was cancelled.
$plan_downgraded = ( $plan instanceof FS_Plugin_Plan && $prev_plan_id != $plan->id ) ||
( is_object( $subscription ) && ! isset( $subscription->error ) && ! $subscription->is_active() );
// handle different error cases.
$this->handle_license_deactivation_result(
$this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...'
if ( ! $plan_downgraded ) {
'error' => (object) array(
'message' => $this->get_text_inline( 'Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.', 'subscription-cancellation-failure-message' )
// Remove previous sticky message about upgrade (if exist).
$this->_admin_notices->remove_sticky( 'plan_upgraded' );
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'Your subscription was successfully cancelled. Your %s plan license will expire in %s.', 'plan-x-downgraded-message' ),
human_time_diff( time(), strtotime( $this->_license->expiration ) )
if ( $deactivate_license &&
! FS_Plugin_License::is_valid_id( $site->license_id )
if ( $this->_site->is_localhost() ) {
$this->_license->activated_local = max( 0, $this->_license->activated_local - 1 );
$this->_license->activated = max( 0, $this->_license->activated - 1 );
// Handle successful license deactivation result.
$this->handle_license_deactivation_result( $this->_license );
* @author Vova Feldman (@svovaf)
* @param bool|string $plan_name
* @return bool If trial was successfully started.
function start_trial( $plan_name = false ) {
$this->_logger->entrance();
$oops_text = $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...';
if ( $this->is_trial() ) {
// Already in trial mode.
$this->_admin_notices->add(
sprintf( $this->get_text_inline( 'You are already running the %s in a trial mode.', 'in-trial-mode' ), $this->_module_type ),
if ( $this->_site->is_trial_utilized() ) {
// Trial was already utilized.
$this->_admin_notices->add(
$this->get_text_inline( 'You already utilized a trial before.', 'trial-utilized' ),