menu = $this->clean( $custom_menu );
$this->inactive_notice = $inactive_notice;
$this->no_product_id = empty( $product_id );
$this->plugin_or_theme = esc_attr( strtolower( $plugin_or_theme ) );
if ( $this->no_product_id ) {
$this->identifier = $this->plugin_or_theme == 'plugin' ? dirname( untrailingslashit( plugin_basename( $file ) ) ) : basename( dirname( plugin_basename( $file ) ) );
$product_id = strtolower( str_ireplace( array(
' ',
'_',
'&',
'?',
'-'
), '_', $this->identifier ) );
$this->wc_am_product_id = 'wc_am_product_id_' . $product_id;
$this->product_id_chosen = get_option( $this->wc_am_product_id );
} else {
/**
* Preserve the value of $product_id to use for API requests. Pre 2.0 product_id is a string, and >= 2.0 is an integer.
*/
if ( is_int( $product_id ) ) {
$this->product_id = absint( $product_id );
} else {
$this->product_id = esc_attr( $product_id );
}
}
// If the product_id was not provided, but was saved by the customer, used the saved product_id.
if ( empty( $this->product_id ) && ! empty( $this->product_id_chosen ) ) {
$this->product_id = $this->product_id_chosen;
}
$this->file = $file;
$this->software_title = esc_attr( $software_title );
$this->software_version = esc_attr( $software_version );
$this->api_url = esc_url( $api_url );
$this->text_domain = esc_attr( $text_domain );
/**
* If the product_id is a pre 2.0 string, format it to be used as an option key, otherwise it will be an integer if >= 2.0.
*/
$this->data_key = 'wc_am_client_' . strtolower( str_ireplace( array(
' ',
'_',
'&',
'?',
'-'
), '_', $product_id ) );
$this->wc_am_activated_key = $this->data_key . '_activated';
if ( is_admin() ) {
if ( ! empty( $this->plugin_or_theme ) && $this->plugin_or_theme == 'theme' ) {
add_action( 'admin_init', array( $this, 'activation' ) );
}
if ( ! empty( $this->plugin_or_theme ) && $this->plugin_or_theme == 'plugin' ) {
register_activation_hook( $this->file, array( $this, 'activation' ) );
}
add_action( 'admin_menu', array( $this, 'register_menu' ) );
add_action( 'admin_init', array( $this, 'load_settings' ) );
// Check for external connection blocking
add_action( 'admin_notices', array( $this, 'check_external_blocking' ) );
/**
* Set all data defaults here
*/
$this->wc_am_api_key_key = $this->data_key . '_api_key';
$this->wc_am_instance_key = $this->data_key . '_instance';
/**
* Set all admin menu data
*/
$this->wc_am_deactivate_checkbox_key = $this->data_key . '_deactivate_checkbox';
$this->wc_am_activation_tab_key = $this->data_key . '_dashboard';
$this->wc_am_deactivation_tab_key = $this->data_key . '_deactivation';
$this->wc_am_auto_update_key = $this->data_key . '_auto_update';
$this->wc_am_settings_title = sprintf( __( '%s', $this->text_domain ), ! empty( $this->menu[ 'page_title' ] ) ? $this->menu[ 'page_title' ] : $this->software_title . ' API Key Activation', $this->text_domain );
$this->wc_am_settings_menu_title = sprintf( __( '%s', $this->text_domain ), ! empty( $this->menu[ 'menu_title' ] ) ? $this->menu[ 'menu_title' ] : $this->software_title . ' Activation', $this->text_domain );
$this->wc_am_menu_tab_activation_title = esc_html__( 'API Key Activation', $this->text_domain );
$this->wc_am_menu_tab_deactivation_title = esc_html__( 'API Key Deactivation', $this->text_domain );
/**
* Set all software update data here
*/
$this->data = get_option( $this->data_key );
$this->wc_am_plugin_name = $this->plugin_or_theme == 'plugin' ? untrailingslashit( plugin_basename( $this->file ) ) : basename( dirname( plugin_basename( $file ) ) ); // same as plugin slug. if a theme use a theme name like 'twentyeleven'
$this->wc_am_renew_license_url = $this->api_url . 'my-account'; // URL to renew an API Key. Trailing slash in the upgrade_url is required.
$this->wc_am_instance_id = get_option( $this->wc_am_instance_key ); // Instance ID (unique to each blog activation)
/**
* Some web hosts have security policies that block the : (colon) and // (slashes) in http://,
* so only the host portion of the URL can be sent. For example the host portion might be
* www.example.com or example.com. http://www.example.com includes the scheme http,
* and the host www.example.com.
* Sending only the host also eliminates issues when a client site changes from http to https,
* but their activation still uses the original scheme.
* To send only the host, use a line like the one below:
*
* $this->wc_am_domain = str_ireplace( array( 'http://', 'https://' ), '', home_url() ); // blog domain name
*/
$this->wc_am_domain = str_ireplace( array(
'http://',
'https://'
), '', home_url() ); // blog domain name
$this->wc_am_software_version = $this->software_version; // The software version
/**
* Check for software updates
*/
$this->check_for_update();
if ( $this->inactive_notice ) {
if ( ! empty( $this->wc_am_activated_key ) && get_option( $this->wc_am_activated_key ) != 'Activated' ) {
add_action( 'admin_notices', array( $this, 'inactive_notice' ) );
}
}
/**
* Makes auto updates available if WP >= 5.5.
*
* @since 2.8
*/
$this->try_automatic_updates();
if ( $this->plugin_or_theme == 'plugin' ) {
//add_action( 'wp_ajax_update_auto_update_setting', array( $this, 'update_auto_update_setting' ) );
add_filter( 'plugin_auto_update_setting_html', array( $this, 'auto_update_message' ), 10, 3 );
}
}
/**
* Deletes all data if plugin deactivated
*/ //if ( $this->plugin_or_theme == 'plugin' ) {
// register_deactivation_hook( $this->file, array( $this, 'uninstall' ) );
//}
//
//if ( $this->plugin_or_theme == 'theme' ) {
// add_action( 'switch_theme', array( $this, 'uninstall' ) );
//}
}
/**
* Clean variables using sanitize_text_field. Arrays are cleaned recursively.
* Non-scalar values are ignored.
*
* @since 2.9
*
* @param string|array $var Data to sanitize.
*
* @return string|array
*/
private function clean( $var ) {
if ( is_array( $var ) ) {
return array_map( array( $this, 'clean' ), $var );
} else {
return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
}
}
/**
* Register a menu or submenu specific to this product.
*
* @updated 2.9
*/
public function register_menu() {
$page_title = $this->wc_am_settings_title;
$menu_title = $this->wc_am_settings_menu_title;
$capability = ! empty( $this->menu[ 'capability' ] ) ? $this->menu[ 'capability' ] : 'manage_options';
$menu_slug = ! empty( $this->menu[ 'menu_slug' ] ) ? $this->menu[ 'menu_slug' ] : $this->wc_am_activation_tab_key;
$callback = ! empty( $this->menu[ 'callback' ] ) ? $this->menu[ 'callback' ] : array(
$this,
'config_page'
);
$icon_url = ! empty( $this->menu[ 'icon_url' ] ) ? $this->menu[ 'icon_url' ] : '';
$position = ! empty( $this->menu[ 'position' ] ) ? $this->menu[ 'position' ] : null;
if ( is_array( $this->menu ) && ! empty( $this->menu[ 'menu_type' ] ) ) {
if ( $this->menu[ 'menu_type' ] == 'add_submenu_page' ) {
// add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null )
add_submenu_page( $this->menu[ 'parent_slug' ], $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
} elseif ( $this->menu[ 'menu_type' ] == 'add_options_page' ) {
// add_options_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null )
add_options_page( $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
} elseif ( $this->menu[ 'menu_type' ] == 'add_menu_page' ) {
// add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null )
add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback, $icon_url, $position );
}
} else {
// add_options_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null )
add_options_page( sprintf( __( '%s', $this->text_domain ), $this->wc_am_settings_menu_title ), sprintf( __( '%s', $this->text_domain ), $this->wc_am_settings_menu_title ), 'manage_options', $this->wc_am_activation_tab_key, array(
$this,
'config_page'
) );
}
}
/**
* Tries auto updates.
*
* @since 2.8
*/
public function try_automatic_updates() {
global $wp_version;
if ( version_compare( $wp_version, '5.5', '>=' ) ) {
//if ( empty( get_option( $this->wc_am_auto_update_key ) ) ) {
// update_option( $this->wc_am_auto_update_key, 'on' );
//}
if ( $this->plugin_or_theme == 'plugin' ) {
add_filter( 'auto_update_plugin', array( $this, 'maybe_auto_update' ), 10, 2 );
} elseif ( $this->plugin_or_theme == 'theme' ) {
add_filter( 'auto_update_theme', array( $this, 'maybe_auto_update' ), 10, 2 );
}
}
}
/**
* Tries to set auto updates.
*
* @since 2.8
*
* @param bool|null $update
* @param object $item
*
* @return bool
*/
public function maybe_auto_update( $update, $item ) {
if ( strpos( $this->wc_am_plugin_name, '.php' ) !== 0 ) {
$slug = dirname( $this->wc_am_plugin_name );
} else {
$slug = $this->wc_am_plugin_name;
}
if ( isset( $item->slug ) && $item->slug == $slug ) {
if ( $this->is_auto_update_disabled() ) {
return false;
}
if ( ! $this->get_api_key_status() || ! $this->get_api_key_status( true ) ) {
return false;
}
return true;
}
return $update;
}
/**
* Checks if auto updates are disabled.
*
* @since 2.8
*
* @return bool
*/
public function is_auto_update_disabled() {
/*
* WordPress will not offer to update if background updates are disabled.
* WordPress background updates are disabled if file changes are not allowed.
*/
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
return true;
}
if ( defined( 'WP_INSTALLING' ) ) {
return true;
}
$wp_updates_disabled = defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED;
/**
* Overrides the WordPress AUTOMATIC_UPDATER_DISABLED constant.
*
* @param bool $wp_updates_disabled true if disables. false otherwise.
*/
$wp_updates_disabled = apply_filters( 'automatic_updater_disabled', $wp_updates_disabled );
if ( $wp_updates_disabled ) {
return true;
}
// Return true if this plugin or theme background update is disabled.
// return get_option( $this->wc_am_auto_update_key ) !== 'on';
return false;
}
/**
* Filter the auto-update message on the plugins page.
*
* Plugin updates stored in 'auto_update_plugins' array.
*
* @see 'wp-admin/includes/class-wp-plugins-list-table.php'
*
* @since 2.8
*
* @param string $html HTML of the auto-update message.
* @param string $plugin_file Plugin file.
* @param array $plugin_data Plugin details.
*
* @return mixed|string
*/
public function auto_update_message( $html, $plugin_file, $plugin_data ) {
if ( $this->wc_am_plugin_name == $plugin_file ) {
global $status, $page;
// if ( ! $this->get_api_key_status( true ) || get_option( $this->wc_am_auto_update_key ) !== 'on' ) {
if ( ! $this->get_api_key_status() || ! $this->get_api_key_status( true ) ) {
return esc_html__( 'Auto-updates unavailable.', $this->text_domain );
}
$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
$html = array();
if ( ! empty( $plugin_data[ 'auto-update-forced' ] ) ) {
if ( $plugin_data[ 'auto-update-forced' ] ) {
// Forced on.
$text = __( 'Auto-updates enabled' );
} else {
$text = __( 'Auto-updates disabled' );
}
$action = 'unavailable';
$time_class = ' hidden';
} elseif ( in_array( $plugin_file, $auto_updates, true ) ) {
$text = __( 'Disable auto-updates' );
$action = 'disable';
$time_class = '';
} else {
$text = __( 'Enable auto-updates' );
$action = 'enable';
$time_class = ' hidden';
}
$query_args = array(
'action' => "{$action}-auto-update",
'plugin' => $plugin_file,
'paged' => $page,
'plugin_status' => $status,
);
$url = add_query_arg( $query_args, 'plugins.php' );
if ( 'unavailable' === $action ) {
$html[] = '' . $text . '';
} else {
$html[] = sprintf( '', wp_nonce_url( $url, 'updates' ), $action );
$html[] = '';
$html[] = '' . $text . '';
$html[] = '';
}
if ( ! empty( $plugin_data[ 'update' ] ) ) {
$html[] = sprintf( '
%s
', $time_class, wp_get_auto_update_message() );
}
$html = implode( '', $html );
}
return $html;
}
/**
* Generate the default data.
*/
public function activation() {
$instance_exists = get_option( $this->wc_am_instance_key );
if ( get_option( $this->data_key ) === false || $instance_exists === false ) {
if ( $instance_exists === false ) {
$this->wc_am_instance_id = wp_generate_password( 12, false );
update_option( $this->wc_am_instance_key, $this->wc_am_instance_id );
}
update_option( $this->wc_am_deactivate_checkbox_key, 'on' );
update_option( $this->wc_am_activated_key, 'Deactivated' );
}
}
/**
* Deletes all data if plugin deactivated
*/
public function uninstall() {
/**
* @since 2.5.1
*
* Filter wc_am_client_uninstall_disable
* If set to false uninstall() method will be disabled.
*/
if ( apply_filters( 'wc_am_client_uninstall_disable', true ) ) {
global $blog_id;
$this->license_key_deactivation();
// Remove options pre API Manager 2.0
if ( is_multisite() ) {
switch_to_blog( $blog_id );
foreach (
array(
$this->wc_am_instance_key,
$this->wc_am_deactivate_checkbox_key,
$this->wc_am_activated_key,
) as $option
) {
delete_option( $option );
}
restore_current_blog();
} else {
foreach (
array(
$this->wc_am_instance_key,
$this->wc_am_deactivate_checkbox_key,
$this->wc_am_activated_key
) as $option
) {
delete_option( $option );
}
}
}
}
/**
* Deactivates the license on the API server
*/
public function license_key_deactivation() {
$activation_status = get_option( $this->wc_am_activated_key );
$api_key = ! empty( $this->data[ $this->wc_am_api_key_key ] ) ? $this->data[ $this->wc_am_api_key_key ] : '';
$args = array(
'api_key' => $api_key,
);
if ( ! empty( $api_key ) && $activation_status == 'Activated' ) {
if ( empty( $this->deactivate( $args ) ) ) {
add_settings_error( 'not_deactivated_text', 'not_deactivated_error', esc_html__( 'The API Key could not be deactivated. Use the API Key Deactivation tab to manually deactivate the API Key before activating a new API Key. If all else fails, go to Plugins, then deactivate and reactivate this plugin, or if a theme change themes, then change back to this theme, then go to the Settings for this plugin/theme and enter the API Key information again to activate it. Also check the My Account dashboard to see if the API Key for this site was still active before the error message was displayed.', $this->text_domain ), 'updated' );
}
}
}
/**
* Displays an inactive notice when the software is inactive.
*/
public function inactive_notice() { ?>
wc_am_activation_tab_key == $_GET[ 'page' ] ) {
return;
} ?>
%s API Key has not been activated, so the %s is inactive! %sClick here%s to activate %s.', $this->text_domain ), esc_attr( $this->software_title ), esc_attr( $this->plugin_or_theme ), '', '', esc_attr( $this->software_title ) ); ?>
Warning! You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->text_domain ), $this->software_title, '' . $host . '', 'WP_ACCESSIBLE_HOSTS' ); ?>