: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Extension License Handler
* @copyright Copyright (c) 2023, Code Atlantic LLC
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
* License handler for Popup Maker
* This class should simplify the process of adding license information to new Popup Maker extensions.
* Note for wordpress.org admins. This is not called in the free hosted version and is simply used for hooking in addons to one update system rather than including it in each plugin.
class PUM_Extension_License {
private $api_url = 'https://wppopupmaker.com/edd-sl-api/';
* @param string $_item_name
* @param string $_version
* @param string $_optname
* @param string $_api_url
function __construct( $_file, $_item_name, $_version, $_author, $_optname = null, $_api_url = null, $_item_id = null ) {
$this->item_name = $_item_name;
if ( is_numeric( $_item_id ) ) {
$this->item_id = absint( $_item_id );
$this->item_shortname = 'popmake_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) );
$this->version = $_version;
$this->license = trim( PUM_Utils_Options::get( $this->item_shortname . '_license_key', '' ) );
$this->author = $_author;
$this->api_url = is_null( $_api_url ) ? $this->api_url : $_api_url;
* Allows for backwards compatibility with old license options,
* i.e. if the plugins had license key fields previously, the license
* handler will automatically pick these up and use those in lieu of the
* user having to reactive their license.
if ( ! empty( $_optname ) ) {
$opt = PUM_Utils_Options::get( $_optname );
if ( isset( $opt ) && empty( $this->license ) ) {
$this->license = trim( $opt );
* Include the updater class
private function includes() {
private function hooks() {
add_filter( 'pum_settings_fields', [ $this, 'settings' ], 1 );
// Activate license key on settings save
add_action( 'admin_init', [ $this, 'activate_license' ] );
// Deactivate license key
add_action( 'admin_init', [ $this, 'deactivate_license' ] );
// Check that license is valid once per week
add_action( 'popmake_weekly_scheduled_events', [ $this, 'weekly_license_check' ] );
// For testing license notices, uncomment this line to force checks on every page load
// add_action( 'admin_init', array( $this, 'weekly_license_check' ) );
add_action( 'admin_init', [ $this, 'auto_updater' ], 0 );
// Display notices to admins
// add_action( 'admin_notices', array( $this, 'notices' ) );
// Display notices to admins
add_filter( 'pum_alert_list', [ $this, 'alerts' ] );
add_action( 'in_plugin_update_message-' . plugin_basename( $this->file ), [ $this, 'plugin_row_license_missing' ], 10, 2 );
// Register plugins for beta support
add_filter( 'pum_beta_enabled_extensions', [ $this, 'register_beta_support' ] );
public function auto_updater() {
'version' => $this->version,
'license' => $this->license,
'author' => $this->author,
'beta' => PUM_Admin_Tools::extension_has_beta_support( $this->item_shortname ),
if ( ! empty( $this->item_id ) ) {
$args['item_id'] = $this->item_id;
$args['item_name'] = $this->item_name;
$popmake_updater = new PUM_Extension_Updater( $this->api_url, $this->file, $args );
* Add license field to settings
public function settings( $tabs = [] ) {
static $license_help_text = false;
if ( ! $license_help_text && ! isset( $tabs['licenses']['main']['license_help_text'] ) ) {
$license_help_text = true;
$tabs['licenses']['main']['license_help_text'] = [
'content' => '<p><strong>' . sprintf( __( 'Enter your extension license keys here to receive updates for purchased extensions. If your license key has expired, please %1$srenew your license%2$s.', 'popup-maker' ), '<a href="https://docs.wppopupmaker.com/article/177-license-renewal?utm_medium=license-help-text&utm_campaign=Licensing&utm_source=plugin-settings-page-licenses-tab" target="_blank">', '</a>' ) . '</strong></p>',
$tabs['licenses']['main'][ $this->item_shortname . '_license_key' ] = [
'label' => sprintf( __( '%1$s', 'popup-maker' ), $this->item_name ),
'is_valid_license_option' => $this->item_shortname . '_license_active',
'activation_callback' => [ $this, 'activate_license' ],
* Activate the license key
public function activate_license() {
if ( ! isset( $_POST['pum_settings'] ) ) {
if ( ! isset( $_POST['pum_settings'][ $this->item_shortname . '_license_key' ] ) ) {
// Don't activate a key when deactivating a different key
if ( ! empty( $_POST['pum_license_deactivate'] ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
$details = get_option( $this->item_shortname . '_license_active' );
if ( is_object( $details ) && 'valid' === $details->license ) {
$license = sanitize_text_field( $_POST['pum_settings'][ $this->item_shortname . '_license_key' ] );
if ( empty( $license ) && empty( $_POST['pum_license_activate'][ $this->item_shortname . '_license_key' ] ) ) {
// Data to send to the API
'edd_action' => 'activate_license',
'item_id' => $this->item_id,
'item_name' => rawurlencode( $this->item_name ),
'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
$response = wp_remote_get(
// Make sure there are no errors
if ( is_wp_error( $response ) ) {
// Tell WordPress to look for updates
set_site_transient( 'update_plugins', null );
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
update_option( $this->item_shortname . '_license_active', $license_data );
* Deactivate the license key
public function deactivate_license() {
if ( ! isset( $_POST['pum_settings'] ) ) {
if ( ! isset( $_POST['pum_settings'][ $this->item_shortname . '_license_key' ] ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
// Run on deactivate button press
if ( isset( $_POST['pum_license_deactivate'][ $this->item_shortname . '_license_key' ] ) ) {
// Data to send to the API
'edd_action' => 'deactivate_license',
'license' => $this->license,
'item_id' => $this->item_id,
'item_name' => rawurlencode( $this->item_name ),
'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
$response = wp_remote_get(
// Make sure there are no errors
if ( is_wp_error( $response ) ) {
// Decode the license data
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
delete_option( $this->item_shortname . '_license_active' );
* Check if license key is valid once per week
public function weekly_license_check() {
if ( ! empty( $_POST['popmake_settings'] ) ) {
return; // Don't fire when saving settings
if ( empty( $this->license ) ) {
// data to send in our API request
'edd_action' => 'check_license',
'license' => $this->license,
'item_id' => $this->item_id,
'item_name' => rawurlencode( $this->item_name ),
'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
$response = wp_remote_get(
// make sure the response came back okay
if ( is_wp_error( $response ) ) {
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
update_option( $this->item_shortname . '_license_active', $license_data );
* Adds an alert to the Popup Maker notification area when the license is invalid, expired, or empty
* @param array $alerts The existing alerts from the pum_alert_list filter
* @return array Our modified array of alerts
public function alerts( $alerts = [] ) {
static $showed_invalid_message;
// If user can't manage it, or we already showed this alert abort.
if ( ! current_user_can( 'manage_options' ) || $showed_invalid_message ) {
// If this alert is already in the list of alerts, abort.
foreach ( $alerts as $alert ) {
if ( 'license_not_valid' === $alert['code'] ) {
// If this license key is not empty, check if it's valid.
if ( ! empty( $this->license ) ) {
$license = get_option( $this->item_shortname . '_license_active' );
if ( ! is_object( $license ) || 'valid' === $license->license ) {
$showed_invalid_message = true;
if ( empty( $this->license ) ) {
'code' => 'license_not_valid',
'message' => sprintf( __( 'One or more of your extensions are missing license keys. You will not be able to receive updates until the extension has a valid license key entered. Please go to the %1$sLicenses page%2$s to add your license keys.', 'popup-maker' ), '<a href="' . admin_url( 'edit.php?post_type=popup&page=pum-settings&tab=licenses' ) . '">', '</a>' ),
'dismissible' => '4 weeks',
'code' => 'license_not_valid',
'message' => sprintf( __( 'You have invalid or expired license keys for Popup Maker. Please go to the %1$sLicenses page%2$s to correct this issue.', 'popup-maker' ), '<a href="' . admin_url( 'edit.php?post_type=popup&page=pum-settings&tab=licenses' ) . '">', '</a>' ),
'dismissible' => '4 weeks',
* Admin notices for errors
public function notices() {
static $showed_invalid_message;
if ( empty( $this->license ) ) {
if ( ! current_user_can( 'manage_options' ) || $showed_invalid_message ) {
$license = get_option( $this->item_shortname . '_license_active' );
if ( is_object( $license ) && 'valid' !== $license->license ) {
if ( empty( $_GET['tab'] ) || 'licenses' !== $_GET['tab'] ) {
$messages[] = sprintf( __( 'You have invalid or expired license keys for Popup Maker. Please go to the %1$sLicenses page%2$s to correct this issue.', 'popup-maker' ), '<a href="' . admin_url( 'edit.php?post_type=popup&page=pum-settings&tab=licenses' ) . '">', '</a>' );
$showed_invalid_message = true;
if ( ! empty( $messages ) ) {
foreach ( $messages as $message ) {
echo '<div class="error">';
echo '<p>' . esc_html( $message ) . '</p>';