: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
self::shoot_ajax_failure(
isset( $next_page->error ) ?
$next_page->error->message :
var_export( $next_page, true )
$this->shoot_ajax_success( array(
'next_page' => $next_page,
* @author Leo Fajardo (@leorw)
function _resend_license_key_ajax_action() {
$this->_logger->entrance();
$this->check_ajax_referer( 'resend_license_key' );
$email_address = sanitize_email( trim( fs_request_get( 'email', '', 'post' ) ) );
if ( empty( $email_address ) ) {
$api = $this->get_api_plugin_scope();
$result = $api->call( '/licenses/resend.json', 'post',
'email' => $email_address,
if ( is_object( $result ) && isset( $result->error ) ) {
if ( in_array( $error->code, array( 'invalid_email', 'no_user' ) ) ) {
$error = $this->get_text_inline( "We couldn't find your email address in the system, are you sure it's the right address?", 'email-not-found' );
} else if ( 'no_license' === $error->code ) {
$error = $this->get_text_inline( "We can't see any active licenses associated with that email address, are you sure it's the right address?", 'no-active-licenses' );
$error = $error->message;
'success' => ( false === $error )
if ( false !== $error ) {
$licenses['error'] = sprintf( '%s... %s', $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ), strtolower( $error ) );
echo json_encode( $licenses );
* @author Vova Feldman (@svovaf)
private static $_pagenow;
* Get current page or the referer if executing a WP AJAX request.
* @author Vova Feldman (@svovaf)
static function get_current_page() {
if ( ! isset( self::$_pagenow ) ) {
if ( empty( $pagenow ) && is_admin() && is_multisite() ) {
* It appears that `$pagenow` is not yet initialized in some network admin pages when this method
* is called, so initialize it here using some pieces of code from `wp-includes/vars.php`.
* @author Leo Fajardo (@leorw)
if ( is_network_admin() ) {
preg_match( '#/wp-admin/network/?(.*?)$#i', $_SERVER['PHP_SELF'], $self_matches );
} else if ( is_user_admin() ) {
preg_match( '#/wp-admin/user/?(.*?)$#i', $_SERVER['PHP_SELF'], $self_matches );
preg_match( '#/wp-admin/?(.*?)$#i', $_SERVER['PHP_SELF'], $self_matches );
$pagenow = $self_matches[1];
$pagenow = trim( $pagenow, '/' );
$pagenow = preg_replace( '#\?.*?$#', '', $pagenow );
if ( '' === $pagenow || 'index' === $pagenow || 'index.php' === $pagenow ) {
preg_match( '#(.*?)(/|$)#', $pagenow, $self_matches );
$pagenow = strtolower( $self_matches[1] );
if ( '.php' !== substr($pagenow, -4, 4) )
$pagenow .= '.php'; // for Options +Multiviews: /wp-admin/themes/index.php (themes.php is queried)
self::$_pagenow = $pagenow;
'admin-ajax.php' === $pagenow
$referer = fs_get_raw_referer();
if ( is_string( $referer ) ) {
$parts = explode( '?', $referer );
self::$_pagenow = basename( $parts[0] );
* Helper method to check if user in the plugins page.
* @author Vova Feldman (@svovaf)
static function is_plugins_page() {
return ( 'plugins.php' === self::get_current_page() );
* @author Leo Fajardo (@leorw)
static function is_plugin_install_page() {
return ( 'plugin-install.php' === self::get_current_page() );
* @author Leo Fajardo (@leorw)
static function is_updates_page() {
return ( 'update-core.php' === self::get_current_page() );
* Helper method to check if user in the themes page.
* @author Vova Feldman (@svovaf)
static function is_themes_page() {
return ( 'themes.php' === self::get_current_page() );
#----------------------------------------------------------------------------------
#----------------------------------------------------------------------------------
* @author Leo Fajardo (@leorw)
function has_affiliate_program() {
if ( ! is_object( $this->_plugin ) ) {
return $this->_plugin->has_affiliate_program();
* Get Plugin ID under which we will track affiliate application.
* This could either be the Bundle ID or the main plugin ID.
* @return number Bundle ID if developer has provided one, else the main plugin ID.
private function get_plugin_id_for_affiliate_terms() {
return $this->has_bundle_context() ?
* @author Leo Fajardo (@leorw)
private function fetch_affiliate_terms() {
if ( ! is_object( $this->plugin_affiliate_terms ) ) {
* In case we have a bundle set in SDK configuration, we would like to use that for affiliates, not the main plugin.
$plugins_api = $this->has_bundle_context() ?
$this->get_api_bundle_scope() :
$this->get_api_plugin_scope();
$affiliate_terms = $plugins_api->get( '/aff.json?type=affiliation', false );
* At this point, we intentionally don't fallback to the main plugin, because the developer has chosen to use bundle. So it makes sense the affiliate program should be in context to the bundle too.
if ( ! $this->is_api_result_entity( $affiliate_terms ) ) {
$this->plugin_affiliate_terms = new FS_AffiliateTerms( $affiliate_terms );
* @author Leo Fajardo (@leorw)
private function fetch_affiliate_and_custom_terms() {
if ( ! empty( $this->_storage->affiliate_application_data ) ) {
$application_data = $this->_storage->affiliate_application_data;
$flush = ( ! isset( $application_data['status'] ) || 'pending' === $application_data['status'] );
$plugin_id_for_affiliate = $this->get_plugin_id_for_affiliate_terms();
$users_api = $this->get_api_user_scope();
$result = $users_api->get( "/plugins/{$plugin_id_for_affiliate}/aff/{$this->plugin_affiliate_terms->id}/affiliates.json", $flush );
if ( $this->is_api_result_object( $result, 'affiliates' ) ) {
if ( ! empty( $result->affiliates ) ) {
$affiliate = new FS_Affiliate( $result->affiliates[0] );
if ( ! isset( $application_data['status'] ) || $application_data['status'] !== $affiliate->status ) {
$application_data['status'] = $affiliate->status;
$this->_storage->affiliate_application_data = $application_data;
if ( $affiliate->is_using_custom_terms ) {
$affiliate_terms = $users_api->get( "/plugins/{$this->_plugin->id}/affiliates/{$affiliate->id}/aff/{$affiliate->custom_affiliate_terms_id}.json", $flush );
if ( $this->is_api_result_entity( $affiliate_terms ) ) {
$this->custom_affiliate_terms = new FS_AffiliateTerms( $affiliate_terms );
$this->affiliate = $affiliate;
* @author Leo Fajardo (@leorw)
private function fetch_affiliate_and_terms() {
$this->_logger->entrance();
$this->fetch_affiliate_terms();
$this->fetch_affiliate_and_custom_terms();
* @author Leo Fajardo (@leorw)
function get_affiliate() {
* @author Leo Fajardo (@leorw)
* @return FS_AffiliateTerms
function get_affiliate_terms() {
return is_object( $this->custom_affiliate_terms ) ?
$this->custom_affiliate_terms :
$this->plugin_affiliate_terms;
* @author Leo Fajardo (@leorw)
function _submit_affiliate_application() {
$this->_logger->entrance();
$this->check_ajax_referer( 'submit_affiliate_application' );
if ( ! $this->is_user_admin() ) {
self::shoot_ajax_failure();
$affiliate = fs_request_get( 'affiliate' );
if ( empty( $affiliate['promotion_methods'] ) ) {
unset( $affiliate['promotion_methods'] );
if ( ! empty( $affiliate['additional_domains'] ) ) {
$affiliate['additional_domains'] = array_unique( $affiliate['additional_domains'] );
if ( ! $this->is_registered() ) {
$email_address = isset( $affiliate['email'] ) ? $affiliate['email'] : '';
if ( ! is_email( $email_address ) ) {
self::shoot_ajax_failure('Invalid email address.');
// Opt in but don't track usage.
$next_page = $this->opt_in(
if ( is_object( $next_page ) && $this->is_api_error( $next_page ) ) {
self::shoot_ajax_failure(
isset( $next_page->error ) ?
$next_page->error->message :
var_export( $next_page, true )
} else if ( $this->is_pending_activation() ) {
self::shoot_ajax_failure( $this->get_text_inline( 'Account is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.', 'account-is-pending-activation' ) );
$this->fetch_affiliate_terms();
$plugin_id_for_affiliate = $this->get_plugin_id_for_affiliate_terms();
$api = $this->get_api_user_scope();
( "/plugins/{$plugin_id_for_affiliate}/aff/{$this->plugin_affiliate_terms->id}/affiliates.json" ),
if ( $this->is_api_error( $result ) ) {
self::shoot_ajax_failure(
isset( $result->error ) ?
$result->error->message :
var_export( $result, true )
if ( $this->_admin_notices->has_sticky( 'affiliate_program' ) ) {
$this->_admin_notices->remove_sticky( 'affiliate_program' );
$affiliate_application_data = array(
'stats_description' => $affiliate['stats_description'],
'promotion_method_description' => $affiliate['promotion_method_description'],
if ( ! empty( $affiliate['promotion_methods'] ) ) {
$affiliate_application_data['promotion_methods'] = $affiliate['promotion_methods'];
if ( ! empty( $affiliate['domain'] ) ) {
$affiliate_application_data['domain'] = $affiliate['domain'];
if ( ! empty( $affiliate['additional_domains'] ) ) {
$affiliate_application_data['additional_domains'] = $affiliate['additional_domains'];
$this->_storage->affiliate_application_data = $affiliate_application_data;
// Purge cached affiliate.
$api->purge_cache( 'affiliate.json' );
self::shoot_ajax_success( $result );
* @author Leo Fajardo (@leorw)
function get_affiliate_application_data() {
if ( empty( $this->_storage->affiliate_application_data ) ) {
return $this->_storage->affiliate_application_data;
#endregion Affiliation ------------------------------------------------------------
#----------------------------------------------------------------------------------
#----------------------------------------------------------------------------------
* Alias to pricing_url().
* @author Vova Feldman (@svovaf)
* @param string $period Billing cycle
function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) {
return $this->pricing_url( $period, $is_trial );
* @author Vova Feldman (@svovaf)
* @uses get_upgrade_url()
function get_trial_url() {
return $this->get_upgrade_url( WP_FS__PERIOD_ANNUALLY, true );
* @author Leo Fajardo (@leorw)
* @param string $new_version
function version_upgrade_checkout_link( $new_version ) {
if ( ! is_object( $this->_license ) ) {
$url = $this->pricing_url();
$purchase_license_text = $this->get_text_inline( 'Buy a license now', 'buy-license-now' );
$subscription = $this->_get_subscription( $this->_license->id );
$url = $this->checkout_url(
is_object( $subscription ) ?
( 1 == $subscription->billing_cycle ? WP_FS__PERIOD_MONTHLY : WP_FS__PERIOD_ANNUALLY ) :
array( 'licenses' => $this->_license->quota )
$purchase_license_text = $this->get_text_inline( 'Renew your license now', 'renew-license-now' );
$this->get_text_inline( '%s to access version %s security & feature updates, and support.', 'x-for-updates-and-support' ),
$this->apply_filters( 'update_notice_checkout_url', $url ),
* @author Vova Feldman (@svovaf)
* @param string $billing_cycle Billing cycle
function pricing_url( $billing_cycle = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) {