first commit

This commit is contained in:
2025-02-24 22:33:42 +01:00
commit 737c037e85
18358 changed files with 5392983 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes;
use Essential_Addons_Elementor\Traits\Login_Registration;
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
class Bootstrap
{
use \Essential_Addons_Elementor\Pro\Traits\Library;
use \Essential_Addons_Elementor\Pro\Traits\Core;
use \Essential_Addons_Elementor\Pro\Traits\Extender;
use \Essential_Addons_Elementor\Pro\Traits\Enqueue;
use \Essential_Addons_Elementor\Pro\Traits\Helper;
use \Essential_Addons_Elementor\Pro\Traits\Instagram_Feed;
use Login_Registration;
// instance container
private static $instance = null;
/**
* Singleton instance
*
* @since 3.0.0
*/
public static function instance()
{
if (self::$instance == null) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Constructor of plugin class
*
* @since 3.0.0
*/
private function __construct()
{
// mark pro version is enabled
add_filter('eael/pro_enabled', '__return_true');
// injecting pro elements
add_filter('eael/registered_elements', array($this, 'inject_new_elements'));
add_filter('eael/registered_extensions', array($this, 'inject_new_extensions'));
add_filter('eael/post_args', [$this, 'eael_post_args']);
// register hooks
$this->register_hooks();
// license
$this->plugin_licensing();
}
public function register_hooks()
{
// Extender filters
add_filter('add_eael_progressbar_layout', [$this, 'add_progressbar_pro_layouts']);
add_filter('fancy_text_style_types', [$this, 'fancy_text_style_types']);
add_filter('eael_ticker_options', [$this, 'ticker_options']);
add_filter('eael_progressbar_rainbow_wrap_class', [$this, 'progress_bar_rainbow_class'], 10, 2);
add_filter('eael_progressbar_circle_fill_wrap_class', [$this, 'progress_bar_circle_fill_class'], 10, 2);
add_filter('eael_progressbar_half_circle_wrap_class', [$this, 'progressbar_half_circle_wrap_class'], 10, 2);
add_filter('eael_progressbar_general_style_condition', [$this, 'progressbar_general_style_condition']);
add_filter('eael_progressbar_line_fill_stripe_condition', [$this, 'progressbar_line_fill_stripe_condition']);
add_filter('eael_circle_style_general_condition', [$this, 'circle_style_general_condition']);
add_filter('eael_pricing_table_styles', [$this, 'add_pricing_table_styles']);
add_filter('pricing_table_subtitle_field_for', [$this, 'pricing_table_subtitle_field']);
add_filter('eael_pricing_table_icon_supported_style', [$this, 'pricing_table_icon_support']);
add_filter('eael_pricing_table_header_radius_supported_style', [$this, 'pricing_table_header_radius_support']);
add_filter('eael_pricing_table_header_bg_supported_style', [$this, 'pricing_table_header_background_support']);
add_filter('eael/advanced-data-table/table_html/integration/database', [$this, 'advanced_data_table_database_integration'], 10, 1);
add_filter('eael/advanced-data-table/table_html/integration/remote', [$this, 'advanced_data_table_remote_database_integration'], 10, 1);
add_filter('eael/advanced-data-table/table_html/integration/google', [$this, 'advanced_data_table_google_sheets_integration'], 10, 1);
add_filter('eael/advanced-data-table/table_html/integration/tablepress', [$this, 'advanced_data_table_tablepress_integration'], 10, 1);
add_filter('eael/event-calendar/integration', [$this, 'event_calendar_eventon_integration'], 10, 2);
add_filter('eael_team_member_style_presets_condition', [$this, 'team_member_presets_condition']);
//Extended actions
add_action('eael_section_data_table_enabled', [$this, 'data_table_sorting']);
add_action('eael_ticker_custom_content_controls', [$this, 'ticker_custom_contents']);
add_action('add_progress_bar_control', [$this, 'progress_bar_box_control'], 10, 3);
add_action('add_eael_progressbar_block', [$this, 'add_box_progress_bar_block'], 10, 3);
add_action('add_pricing_table_settings_control', [$this, 'pricing_table_header_image_control']);
add_action('pricing_table_currency_position', [$this, 'pricing_table_style_2_currency_position']);
add_action('add_pricing_table_style_block', [$this, 'add_pricing_table_pro_styles'], 10, 6);
add_action('eael_pricing_table_after_pricing_style', [$this, 'pricing_table_style_five_settings_control']);
add_action('eael_pricing_table_control_header_extra_layout', [$this, 'pricing_table_style_header_layout_two']);
add_action('add_admin_license_markup', [$this, 'add_admin_licnes_markup_html'], 10, 5);
add_action('eael_premium_support_link', [$this, 'add_eael_premium_support_link'], 10, 5);
add_action('eael_additional_support_links', [$this, 'add_eael_additional_support_links'], 10, 5);
add_action('eael_manage_license_action_link', [$this, 'add_manage_linces_action_link'], 10, 5);
add_action('eael_creative_button_pro_controls', [$this, 'add_creative_button_controls'], 10, 1);
add_action('eael_creative_button_style_pro_controls', [$this, 'add_creative_button_style_pro_controls'], 10, 5);
add_action('wp_ajax_eael_ajax_post_search', [$this, 'ajax_post_search']);
add_action('wp_ajax_nopriv_eael_ajax_post_search', [$this, 'ajax_post_search']);
add_action('eael/team_member_circle_controls', [$this, 'add_team_member_circle_presets']);
add_action('eael/team_member_social_botton_markup', [$this, 'add_team_member_social_bottom_markup'], 10, 2);
add_action('eael/team_member_social_right_markup', [$this, 'add_team_member_social_right_markup'], 10, 2);
add_action('eael/controls/advanced-data-table/source', [$this, 'advanced_data_table_source_control'], 10, 1);
add_action('eael/event-calendar/source/control', [$this, 'event_calendar_source_control'], 10, 1);
add_action('eael/event-calendar/activation-notice', [$this, 'event_calendar_activation_notice'], 10, 1);
add_filter('eael/woo-checkout/layout', [$this, 'eael_woo_checkout_layout']);
add_action('eael_add_woo_checkout_pro_layout', [$this, 'add_woo_checkout_pro_layout'], 10, 2);
add_action('eael_woo_checkout_pro_enabled_general_settings', [$this, 'add_woo_checkout_tabs_data']);
add_action('eael_woo_checkout_pro_enabled_tabs_styles', [$this, 'add_woo_checkout_tabs_styles']);
add_action('eael_woo_checkout_pro_enabled_tabs_styles', [$this, 'add_woo_checkout_section_styles']);
add_action('eael_woo_checkout_pro_enabled_steps_btn_styles', [$this, 'add_woo_checkout_steps_btn_styles']);
add_action('eael/login-register/after-general-controls', [$this, 'lr_init_content_ajax_controls']);
add_action('eael/login-register/after-init-login-button-style', [$this, 'lr_init_content_login_spinner_controls']);
add_action('eael/login-register/after-init-register-button-style', [$this, 'lr_init_content_register_spinner_controls']);
add_action('eael/login-register/after-login-controls-section', [$this, 'lr_init_content_social_login_controls']);
add_action('eael/login-register/after-login-footer', [$this, 'lr_print_social_login']);
add_action('eael/login-register/after-register-footer', [$this, 'lr_print_social_login_on_register']);
add_action('eael/login-register/after-style-controls', [$this, 'lr_init_style_social_controls']);
add_action('eael/login-register/after-style-controls', [$this, 'lr_init_style_pass_strength_controls']);
add_action('eael/login-register/mailchimp-integration', [$this, 'lr_init_mailchimp_integration_controls']);
add_action('eael/login-register/after-register-options-controls', [$this, 'lr_init_content_pass_strength_controls']);
add_action('eael/login-register/after-pass-visibility-controls', [$this, 'lr_init_content_icon_controls']);
add_filter('eael/login-register/scripts', [$this, 'lr_load_pro_scripts']);
add_filter('eael/login-register/styles', [$this, 'lr_load_pro_styles']);
add_action('eael/login-register/register-repeater', [$this, 'lr_add_register_fields_icons']);
add_action('eael/login-register/register-rf-default', [$this, 'lr_add_register_fields_default_icons']);
add_action('eael/login-register/after-password-field', [$this, 'lr_show_password_strength_meter']);
add_action('eael/login-register/mailchimp-integration-action', [$this, 'login_register_mailchimp_integration_subscribe'], 10, 3);
add_filter('eael/login-register/register-user-password-validation', [$this, 'lr_register_user_password_validation'], 10, 3);
// ajax
add_action('wp_ajax_woo_checkout_post_code_validate', [$this, 'eael_woo_checkout_post_code_validate']);
add_action('wp_ajax_nopriv_woo_checkout_post_code_validate', [$this, 'eael_woo_checkout_post_code_validate']);
add_action('wp_ajax_mailchimp_subscribe', [$this, 'mailchimp_subscribe_with_ajax']);
add_action('wp_ajax_nopriv_mailchimp_subscribe', [$this, 'mailchimp_subscribe_with_ajax']);
add_action('wp_ajax_instafeed_load_more', [$this, 'instafeed_render_items']);
add_action('wp_ajax_nopriv_instafeed_load_more', [$this, 'instafeed_render_items']);
add_action('wp_ajax_connect_remote_db', [$this, 'connect_remote_db']);
add_action('wp_ajax_eael-login-register-form', [$this, 'login_or_register_user']);
add_action('wp_ajax_nopriv_eael-login-register-form', [$this, 'login_or_register_user']);
add_action('eael/login-register/before-processing-login-register', [$this, 'lr_handle_social_login']);
//adv search
add_action('wp_ajax_fetch_search_result', array($this, 'fetch_search_result'));
add_action('wp_ajax_nopriv_fetch_search_result', array($this, 'fetch_search_result'));
// localize script
add_filter('eael/localize_objects', [$this, 'script_localizer']);
// pro scripts
add_action('eael/before_enqueue_scripts', [$this, 'before_enqueue_scripts']);
if ( is_admin() ) {
// Core
add_filter( 'plugin_action_links_' . EAEL_PRO_PLUGIN_BASENAME, array( $this, 'insert_plugin_links' ) );
}
}
// push pro widgets in lite
public function inject_new_elements($elements)
{
return array_merge_recursive($elements, $GLOBALS['eael_pro_config']['elements']);
}
// push pro extensions in lite
public function inject_new_extensions($extensions)
{
return array_merge_recursive($extensions, $GLOBALS['eael_pro_config']['extensions']);
}
}

View File

@@ -0,0 +1,452 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes;
use Elementor\Controls_Manager;
use Elementor\Plugin;
use Essential_Addons_Elementor\Classes\Helper as ClassesHelper;
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
class Helper extends \Essential_Addons_Elementor\Classes\Helper
{
use \Essential_Addons_Elementor\Pro\Traits\Dynamic_Filterable_Gallery;
const EAEL_PRO_ALLOWED_HTML_TAGS = [
'article',
'aside',
'div',
'footer',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'header',
'main',
'nav',
'p',
'section',
'span',
];
/**
* Get all product tags
*
* @return array
*/
public static function get_woo_product_tags()
{
if (!apply_filters('eael/is_plugin_active', 'woocommerce/woocommerce.php')) {
return [];
}
$options = [];
$tags = get_terms('product_tag', array('hide_empty' => true));
if (!empty($tags) && !is_wp_error($tags)) {
foreach ($tags as $tag) {
$options[$tag->term_id] = $tag->name;
}
}
return $options;
}
/**
* Get all product attributes
*
* @return array
*/
public static function get_woo_product_atts()
{
if ( ! apply_filters( 'eael/is_plugin_active', 'woocommerce/woocommerce.php' ) || ! function_exists( 'wc_get_attribute_taxonomies' ) ) {
return [];
}
$options = [];
$taxonomies = wc_get_attribute_taxonomies();
foreach ($taxonomies as $tax) {
$terms = get_terms('pa_' . $tax->attribute_name);
if (!empty($terms)) {
foreach ($terms as $term) {
$options[$term->term_id] = $tax->attribute_label . ': ' . $term->name;
}
}
}
return $options;
}
/**
* Get all registered menus.
*
* @return array of menus.
*/
public static function get_menus()
{
$menus = wp_get_nav_menus();
$options = [];
if (empty($menus)) {
return $options;
}
foreach ($menus as $menu) {
$options[$menu->term_id] = $menu->name;
}
return $options;
}
public static function user_roles()
{
global $wp_roles;
$all = $wp_roles->roles;
$all_roles = array();
if (!empty($all)) {
foreach ($all as $key => $value) {
$all_roles[$key] = $all[$key]['name'];
}
}
return $all_roles;
}
public static function get_page_template_options($type = '')
{
$page_templates = self::get_elementor_templates($type);
$options[-1] = __('Select', 'essential-addons-elementor');
if (count($page_templates)) {
foreach ($page_templates as $id => $name) {
$options[$id] = $name;
}
} else {
$options['no_template'] = __('No saved templates found!', 'essential-addons-elementor');
}
return $options;
}
// Get all WordPress registered widgets
public static function get_registered_sidebars()
{
global $wp_registered_sidebars;
$options = [];
if (!$wp_registered_sidebars) {
$options[''] = __('No sidebars were found', 'essential-addons-elementor');
} else {
$options['---'] = __('Choose Sidebar', 'essential-addons-elementor');
foreach ($wp_registered_sidebars as $sidebar_id => $sidebar) {
$options[$sidebar_id] = $sidebar['name'];
}
}
return $options;
}
// Get Mailchimp list
public static function mailchimp_lists( $element = 'mailchimp', $type_double_optin = false ) {
$lists = $lists_double_optin = [];
$api_key = get_option( 'eael_save_mailchimp_api' );
if ( $element === 'login-register-form' ) {
$api_key = get_option( 'eael_lr_mailchimp_api_key' );
}
if ( empty( $api_key ) ) {
return $lists;
}
$pattern = '/^[0-9a-z]{32}(-us)(0?[1-9]|[1-9][0-9])?$/';
if ( ! preg_match( $pattern, $api_key ) ) {
return $lists;
}
$response = wp_safe_remote_get( 'https://' . substr( $api_key,
strpos( $api_key, '-' ) + 1 ) . '.api.mailchimp.com/3.0/lists/?fields=lists.id,lists.name,lists.double_optin&count=1000', [
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Basic ' . base64_encode( 'user:' . $api_key ),
],
] );
if ( ! is_wp_error( $response ) ) {
$response = json_decode( wp_remote_retrieve_body( $response ) );
if ( ! empty( $response ) && ! empty( $response->lists ) ) {
$lists[''] = __( 'Select One', 'essential-addons-elementor' );
for ( $i = 0; $i < count( $response->lists ); $i ++ ) {
$lists[ $response->lists[ $i ]->id ] = $response->lists[ $i ]->name;
$lists[ $response->lists[ $i ]->id ] = $response->lists[ $i ]->name;
$lists_double_optin[ $response->lists[ $i ]->id ] = $response->lists[ $i ]->double_optin;
}
}
}
return $type_double_optin ? $lists_double_optin : $lists;
}
public static function list_db_tables()
{
global $wpdb;
$result = [];
$tables = $wpdb->get_results('show tables', ARRAY_N);
if ($tables) {
$tables = wp_list_pluck($tables, 0);
foreach ($tables as $table) {
$result[$table] = $table;
}
}
return $result;
}
public static function list_tablepress_tables() {
if ( empty( \TablePress::$model_table ) ) {
return [];
}
$result = [];
$tables = \TablePress::$model_table->load_all( true );
if ( $tables ) {
foreach ( $tables as $table ) {
$table = \TablePress::$model_table->load( $table, false, false );
$result[ $table['id'] ] = $table['name'];
}
}
return $result;
}
/**
* eael_pro_validate_html_tag
* @param $tag
* @return mixed|string
*/
public static function eael_pro_validate_html_tag( $tag ){
return in_array( strtolower( $tag ), self::EAEL_PRO_ALLOWED_HTML_TAGS ) ? $tag : 'div';
}
/**
* Get all dropdown options of elementor breakpoints.
*
* @return array of breakpoint options.
*/
public static function get_breakpoint_dropdown_options(){
$breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();
$dropdown_options = [];
$excluded_breakpoints = [
'laptop',
'widescreen',
];
foreach ( $breakpoints as $breakpoint_key => $breakpoint_instance ) {
// Do not include laptop and widscreen in the options since this feature is for mobile devices.
if ( in_array( $breakpoint_key, $excluded_breakpoints, true ) ) {
continue;
}
$dropdown_options[ $breakpoint_key ] = sprintf(
/* translators: 1: Breakpoint label, 2: `>` character, 3: Breakpoint value */
esc_html__( '%1$s (%2$s %3$dpx)', 'essential-addons-elementor' ),
$breakpoint_instance->get_label(),
'>',
$breakpoint_instance->get_value()
);
}
$dropdown_options['desktop'] = esc_html__( 'Desktop (> 2400px)', 'essential-addons-elementor' );
$dropdown_options['none'] = esc_html__( 'None', 'essential-addons-elementor' );
return $dropdown_options;
}
public static function validate_post_types( $post_types )
{
$allowed_post_types = self::get_post_types();
$validated_post_types = '';
if ( is_string( $post_types ) && array_key_exists( $post_types, $allowed_post_types ) ) {
$validated_post_types = $post_types;
} else {
if ( is_array( $post_types ) ) {
$validated_post_types = array_filter( $post_types, function ( $post_type ) use( $allowed_post_types ) {
return array_key_exists( $post_type, $allowed_post_types );
});
}
}
return $validated_post_types;
}
public static function get_allowed_taxonomies()
{
$taxonomies = get_taxonomies(['public' => true]);
$taxonomy_array = [];
foreach ($taxonomies as $taxonomy) {
$taxonomy_object = get_taxonomy($taxonomy);
$taxonomy_array[$taxonomy] = sanitize_text_field($taxonomy_object->labels->name);
}
return $taxonomy_array;
}
/**
* Query Controls for Dynamic Tags
*
*/
public static function query_dynamic_tags( $wb, $args )
{
$post_types = ClassesHelper::get_post_types();
$post_types = $args['post_types'] ?? $post_types;
$hide_controls = ! empty( $args['hide_controls'] ) ? $args['hide_controls'] : [];
if( ! isset( $args['post_types'] ) ) {
$post_types['by_id'] = __('Manual Selection', 'essential-addons-elementor');
}
$taxonomies = get_taxonomies([], 'objects');
$wb->add_control(
'post_type',
[
'label' => __('Source', 'essential-addons-elementor'),
'type' => in_array( 'post_type', $hide_controls ) ? Controls_Manager::HIDDEN : Controls_Manager::SELECT,
'options' => $post_types,
'default' => key($post_types),
]
);
$wb->add_control(
'posts_ids',
[
'label' => __('Search & Select', 'essential-addons-elementor'),
'type' => 'eael-select2',
'options' => ClassesHelper::get_post_list(),
'label_block' => true,
'multiple' => true,
'source_name' => 'post_type',
'source_type' => 'any',
'condition' => [
'post_type' => 'by_id',
],
]
);
$wb->add_control(
'authors', [
'label' => __('Author', 'essential-addons-elementor'),
'label_block' => true,
'type' => Controls_Manager::SELECT2,
'multiple' => true,
'default' => [],
'options' => ClassesHelper::get_authors_list(),
'condition' => [
'post_type!' => ['by_id', 'source_dynamic'],
],
]
);
foreach ($taxonomies as $taxonomy => $object) {
if (!isset($object->object_type[0]) || !in_array($object->object_type[0], array_keys($post_types))) {
continue;
}
if ( 'post_format' === $taxonomy || 'product_shipping_class' === $taxonomy || 'product_visibility' === $taxonomy ) {
continue;
}
$wb->add_control(
$taxonomy . '_ids',
[
'label' => $object->label,
'type' => in_array( $taxonomy . '_ids', $hide_controls ) ? Controls_Manager::HIDDEN : 'eael-select2',
'label_block' => true,
'multiple' => true,
'source_name' => 'taxonomy',
'source_type' => $taxonomy,
'condition' => [
'post_type' => $object->object_type,
],
]
);
}
$wb->add_control(
'post__not_in',
[
'label' => __( 'Exclude', 'essential-addons-elementor' ),
'type' => 'eael-select2',
'label_block' => true,
'multiple' => true,
'source_name' => 'post_type',
'source_type' => 'any',
'condition' => [
'post_type!' => [ 'by_id', 'source_dynamic' ],
],
]
);
$wb->add_control(
'posts_per_page',
[
'label' => __('Count', 'essential-addons-elementor'),
'type' => Controls_Manager::NUMBER,
'default' => '10',
'min' => '1',
]
);
$wb->add_control(
'offset',
[
'label' => __('Offset', 'essential-addons-elementor'),
'type' => Controls_Manager::NUMBER,
'default' => '0',
'condition' => [
'orderby!' => 'rand'
]
]
);
$wb->add_control(
'orderby',
[
'label' => __('Order By', 'essential-addons-elementor'),
'type' => Controls_Manager::SELECT,
'options' => ClassesHelper::get_post_orderby_options(),
'default' => 'date',
]
);
$wb->add_control(
'order',
[
'label' => __('Order', 'essential-addons-elementor'),
'type' => Controls_Manager::SELECT,
'options' => [
'asc' => 'Ascending',
'desc' => 'Descending',
],
'default' => 'desc',
]
);
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes\License;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Exception;
use Essential_Addons_Elementor\Pro\Classes\License\Contracts\ApiAdapter;
/**
* @property string $textdomain
* @property string $action_prefix
*/
#[\AllowDynamicProperties]
class AJAXApi extends ApiAdapter {
/**
* @throws Exception
*/
public function register() {
if ( ! isset( $this->action_prefix ) ) {
throw new Exception( "action_prefix needs to be set in ajax configuration" );
}
add_action( "wp_ajax_{$this->action_prefix}/license/activate", [ $this, 'activate' ] );
add_action( "wp_ajax_{$this->action_prefix}/license/deactivate", [ $this, 'deactivate' ] );
add_action( "wp_ajax_{$this->action_prefix}/license/submit-otp", [ $this, 'submit_otp' ] );
add_action( "wp_ajax_{$this->action_prefix}/license/resend-otp", [ $this, 'resend_otp' ] );
}
/**
* Get the API Config
* @return array
*/
public function get_api_config() {
return array_merge( parent::get_api_config(), [
'action' => $this->action_prefix,
'api_url' => esc_url( admin_url( 'admin-ajax.php' ) )
] );
}
public function error( $code, $message ) {
wp_send_json_error( [
'code' => $code,
'message' => $message
] );
}
private function nonce_permission_check( ) {
if ( ! isset( $_POST['_nonce'] ) || ! $this->verify_nonce( $_POST['_nonce'] ) ) {
$this->error( 'nonce_error', __( 'Nonce Verifications Failed.', $this->textdomain ) );
}
if ( ! $this->permission_check() ) {
$this->error( 'no_permission', __( 'You don\'t have permission to take this action.', $this->textdomain ) );
}
}
/**
* @param $request array
*
* @return void
*/
public function activate( $request = [] ) {
$this->nonce_permission_check();
$response = $this->license_manager->activate( [
'license_key' => sanitize_text_field( $_POST['license_key'] )
] );
if ( is_wp_error( $response ) ) {
$this->error( $response->get_error_code(), $response->get_error_message() );
}
wp_send_json_success( $response );
}
/**
* @param $request array
*
* @return void
*/
public function deactivate( $request = [] ) {
$response = $this->license_manager->deactivate();
if ( is_wp_error( $response ) ) {
$this->error( $response->get_error_code(), $response->get_error_message() );
}
wp_send_json_success( $response );
}
public function submit_otp( $request = [] ) {
$this->nonce_permission_check();
$args = [
'otp' => sanitize_text_field( $_POST['otp'] ),
'license_key' => sanitize_text_field( $_POST['license'] )
];
$response = $this->license_manager->submit_otp( $args );
if ( is_wp_error( $response ) ) {
$this->error( $response->get_error_code(), $response->get_error_message() );
}
wp_send_json_success( $response );
}
public function resend_otp( $request = [] ) {
$this->nonce_permission_check();
$args = [
'license_key' => sanitize_text_field( $_POST['license'] )
];
$response = $this->license_manager->resend_otp( $args );
if ( is_wp_error( $response ) ) {
$this->error( $response->get_error_code(), $response->get_error_message() );
}
wp_send_json_success( $response );
}
}

View File

@@ -0,0 +1,89 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes\License\Contracts;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Exception;
use Essential_Addons_Elementor\Pro\Classes\License\LicenseManager;
#[\AllowDynamicProperties]
abstract class ApiAdapter {
protected $config = null;
/**
* @var LicenseManager
*/
protected $license_manager;
public function __construct( $license_manager ) {
$this->license_manager = $license_manager;
$this->config = $this->license_manager->get_args( $this->license_manager->api );
$this->config['handle'] = $this->license_manager->get_args( 'scripts_handle' );
$this->config['screen_id'] = $this->license_manager->get_args( 'screen_id' );
$this->config['item_id'] = $this->license_manager->get_args( 'item_id' );
$this->register();
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ], 11 );
}
public function enqueue( $hook ) {
if ( is_array( $this->screen_id ) && ! in_array( $hook, $this->screen_id ) ) {
return;
}
if ( ! is_array( $this->screen_id ) && $this->screen_id !== $hook ) {
return;
}
wp_localize_script( $this->handle, 'wpdeveloperLicenseManagerConfig', $this->get_api_config() );
}
public function get_api_config() {
return [
'textdomain' => $this->license_manager->textdomain,
'apiType' => $this->license_manager->api,
'nonce' => wp_create_nonce( "wpdeveloper_sl_{$this->item_id}_nonce" )
];
}
/**
* @throws Exception
*/
public function __get( $name ) {
if ( isset( $this->config[ $name ] ) ) {
return $this->config[ $name ];
} elseif ( isset( $this->license_manager->{$name} ) ) {
return $this->license_manager->get_args( $name );
} else {
throw new Exception( "Please provide $name for api configuration." );
}
}
public function __isset( $name ) {
return isset( $this->config[ $name ] );
}
protected function verify_nonce( $nonce ) {
return wp_verify_nonce( $nonce, "wpdeveloper_sl_{$this->item_id}_nonce" );
}
/**
* This method is responsible for checking permissions.
* @return bool
*/
public function permission_check() {
return current_user_can( isset( $this->permission ) ? $this->permission : 'delete_users' );
}
abstract public function register();
abstract public function activate( $request );
abstract public function deactivate( $request );
}

View File

@@ -0,0 +1,358 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes\License;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Exception;
use WP_Error;
/**
* @property int $item_id
* @property string $version
* @property string $storeURL
* @property string $db_prefix
* @property string $textdomain
* @property string $item_name
*/
#[\AllowDynamicProperties]
class LicenseManager {
private static $_instance = null;
protected $license = '';
protected $license_data = null;
protected $args = [
'version' => '',
// 'author' => '',
// 'beta' => '',
'plugin_file' => '',
'item_id' => 0,
'item_name' => '',
'item_slug' => '',
'storeURL' => '',
'textdomain' => '',
'db_prefix' => '',
'scripts_handle' => '',
'screen_id' => '',
'page_slug' => '',
'api' => ''
];
public static function get_instance( $args ) {
if ( self::$_instance === null ) {
self::$_instance = new self( $args );
}
return self::$_instance;
}
/**
* @throws Exception
*/
public function __construct( $args ) {
foreach ( $this->args as $property => $value ) {
if ( ! array_key_exists( $property, $args ) ) {
throw new Exception( "$property is missing in licensing." );
}
}
$this->args = wp_parse_args( $args, $this->args );
$this->license_data = $this->get_license_data();
if ( ( empty( $this->license_data ) ) && current_user_can( 'activate_plugins' ) ) {
add_action( 'admin_notices', [ $this, 'admin_notices' ] );
add_action( 'eael_admin_notices', [ $this, 'admin_notices' ] );
}
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ], 11 );
if ( isset( $this->args['api'] ) ) {
switch ( strtolower( $this->args['api'] ) ) {
case 'rest':
if ( ! isset( $this->args['rest'] ) ) {
throw new Exception( "rest is missing in licensing." );
}
new RESTApi( $this );
break;
case 'ajax':
if ( ! isset( $this->args['ajax'] ) ) {
throw new Exception( "ajax is missing in licensing." );
}
new AJAXApi( $this );
break;
}
}
add_action( 'init', [ $this, 'plugin_updater' ] );
add_action( 'eael_licensing', array( $this, 'render_licenses_page' ) );
}
public function admin_notices() {
$message = sprintf( __( 'Please %1$sactivate your license%2$s key to enable updates for %3$s.', $this->textdomain ), '<a style="text-decoration: none;" href="' . admin_url( 'admin.php?page=' . $this->page_slug ) . '">', '</a>', '<strong>' . $this->item_name . '</strong>' );
$notice = sprintf( '<div style="padding: 10px;" class="%1$s-notice wpdeveloper-licensing-notice notice notice-error">%2$s</div>', $this->textdomain, $message );
echo wp_kses_post( $notice );
}
public function plugin_updater() {
$_license = get_option( "{$this->db_prefix}-license-key" );
new PluginUpdater( $this->storeURL, $this->plugin_file, [
'version' => $this->version, // current version number
'license' => $_license, // license key (used get_option above to retrieve from DB)
'item_id' => $this->item_id, // ID of the product
'author' => empty( $this->author ) ? 'WPDeveloper' : $this->author, // author of this plugin
'beta' => isset( $this->beta ) ? $this->beta : false
] );
}
public function get_args( $name = '' ) {
return empty( $name ) ? $this->args : $this->args[ $name ];
}
public function enqueue( $hook ) {
if ( is_array( $this->screen_id ) && ! in_array( $hook, $this->screen_id ) ) {
return;
}
if ( ! is_array( $this->screen_id ) && $this->screen_id !== $hook ) {
return;
}
wp_localize_script( $this->scripts_handle, 'wpdeveloperLicenseData', $this->get_license_data() );
}
public function get_license_data() {
$_license = get_option( "{$this->db_prefix}-license-key" );
$_license_status = get_option( "{$this->db_prefix}-license-status" );
$_license_data = get_transient( "{$this->db_prefix}-license_data" );
if ( $_license_data !== false ) {
$_license_data = (array) $_license_data;
}
if ( $_license_data == false || empty( $_license_data ) ) {
$response = $this->check();
if ( is_wp_error( $response ) ) {
return [];
}
$_license_data = (array) $response;
}
return array_merge( [
'license_key' => $_license,
'hidden_license_key' => $this->hide_license_key( $_license ),
'license_status' => $_license_status
], $_license_data );
}
public function hide_license_key( $_license ) {
$length = mb_strlen( $_license ) - 10;
$_license = substr_replace( $_license, mb_substr( preg_replace( '/\S/', '*', $_license ), 5, $length ), 5, $length );
return $_license;
}
public function activate( $args = [] ) {
$this->license = sanitize_text_field( isset( $args['license_key'] ) ? trim( $args['license_key'] ) : '' );
$response = $this->remote_post( 'activate_license' );
if ( is_wp_error( $response ) ) {
return $response;
}
/**
* Return if license required OTP to activate.
*/
if ( isset( $response->license ) && $response->license == 'required_otp' ) {
return $response;
}
update_option( "{$this->db_prefix}-license-key", $this->license, 'no' );
update_option( "{$this->db_prefix}-license-status", $response->license, 'no' );
set_transient( "{$this->db_prefix}-license_data", $response, MONTH_IN_SECONDS * 3 );
return $response;
}
public function deactivate( $args = [] ) {
$this->license = get_option( "{$this->db_prefix}-license-key", '' );
$response = $this->remote_post( 'deactivate_license' );
if ( is_wp_error( $response ) ) {
return $response;
}
delete_option( "{$this->db_prefix}-license-key" );
delete_option( "{$this->db_prefix}-license-status" );
delete_transient( "{$this->db_prefix}-license_data" );
return $response;
}
public function submit_otp( $args = [] ) {
$this->license = sanitize_text_field( isset( $args['license_key'] ) ? trim( $args['license_key'] ) : '' );
$response = $this->remote_post( 'activate_license_by_otp', $args );
if ( is_wp_error( $response ) ) {
return $response;
}
update_option( "{$this->db_prefix}-license-key", $this->license, 'no' );
update_option( "{$this->db_prefix}-license-status", $response->license, 'no' );
set_transient( "{$this->db_prefix}-license_data", $response, MONTH_IN_SECONDS * 3 );
return $response;
}
public function resend_otp( $args ) {
$this->license = sanitize_text_field( isset( $args['license_key'] ) ? trim( $args['license_key'] ) : '' );
return $this->remote_post( 'resend_otp_for_license', $args );
}
public function check( $args = [] ) {
$this->license = get_option( "{$this->db_prefix}-license-key", '' );
$_license_data = get_transient( "{$this->db_prefix}-license_data" );
if ( $_license_data !== false ) {
$_license_data = (array) $_license_data;
}
if ( ! empty( $_license_data ) ) {
return $_license_data;
}
$response = $this->remote_post( 'check_license' );
if ( is_wp_error( $response ) ) {
delete_transient( "{$this->db_prefix}-license_data" );
return $response;
}
set_transient( "{$this->db_prefix}-license_data", $response, MONTH_IN_SECONDS * 3 );
return $response;
}
/**
* 'activate_license'
*
* @param mixed $args
*
* @return mixed
*/
public function remote_post( $action, $args = [] ) {
if ( empty( $this->license ) ) {
return new WP_Error( 'empty_license', __( 'Please provide a valid license.', $this->textdomain ) );
}
$defaults = [
'edd_action' => $action,
'license' => $this->license,
'item_id' => $this->item_id,
'item_name' => rawurlencode( $this->item_name ), // the name of our product in EDD
'url' => home_url(),
'version' => $this->version,
'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production'
];
$args = wp_parse_args( $args, $defaults );
$response = wp_safe_remote_post( $this->storeURL, [
'timeout' => 15,
'sslverify' => false,
'body' => $args
] );
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
if ( is_wp_error( $response ) ) {
return $response;
}
return new WP_Error( 'unknown', __( 'An error occurred, please try again.', $this->textdomain ) );
}
$license_data = $this->maybe_error( json_decode( wp_remote_retrieve_body( $response ) ) );
if ( ! is_wp_error( $license_data ) ) {
$license_data->license_key = $this->hide_license_key( $this->license );
}
return $license_data;
}
private function maybe_error( $license_data ) {
if ( false === $license_data->success ) {
$message = '';
$error_code = isset($license_data->error) ? $license_data->error : 'unknown';
switch ( $error_code ) {
case 'expired':
$message = sprintf( /* translators: the license key expiration date */ __( 'Your license key expired on %s.', $this->textdomain ), date_i18n( get_option( 'date_format' ), $license_data->expires ) );
break;
case 'invalid_otp':
$message = __( 'Your license confirmation code is invalid.', $this->textdomain );
break;
case 'expired_otp':
$message = __( 'Your license confirmation code has been expired.', $this->textdomain );
break;
case 'disabled':
case 'revoked':
$message = __( 'Your license key has been disabled.', $this->textdomain );
break;
case 'missing':
$message = __( 'Invalid license.', $this->textdomain );
break;
case 'invalid':
case 'site_inactive':
$message = __( 'Your license is not active for this URL.', $this->textdomain );
break;
case 'item_name_mismatch':
/* translators: the plugin name */ $message = sprintf( __( 'This appears to be an invalid license key for %s.', $this->textdomain ), $this->item_name );
break;
case 'no_activations_left':
$message = __( 'Your license key has reached its activation limit.', $this->textdomain );
break;
default:
$message = __( 'An error occurred, please try again.', $this->textdomain );
break;
}
return new WP_Error( $error_code, wp_kses( $message, 'post' ) );
}
return $license_data;
}
public function __get( $name ) {
if ( isset( $this->args[ $name ] ) ) {
return $this->args[ $name ];
}
return null;
}
public function render_licenses_page() {
$hidden_license_key = $this->license_data['hidden_license_key'] ?? '';
$status = $this->license_data['license_status'] ?? '';
$title = sprintf( __( '%s License', $this->text_domain ), $this->product_name );
// if ( $status !== 'valid' ) {
// $this->set_license_key( '' );
// }
include_once __DIR__ . '/views/settings.php';
}
}

View File

@@ -0,0 +1,671 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes\License;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use stdClass;
/**
* Allows plugins to use their own update API.
*
* @author Easy Digital Downloads
* @version 1.9.2
*/
#[\AllowDynamicProperties]
class PluginUpdater {
private $api_url = '';
private $api_data = [];
private $plugin_file = '';
private $name = '';
private $slug = '';
private $version = '';
private $wp_override = false;
private $beta = false;
private $failed_request_cache_key;
/**
* Class constructor.
*
* @uses plugin_basename()
* @uses hook()
*
* @param string $_api_url The URL pointing to the custom API endpoint.
* @param string $_plugin_file Path to the plugin file.
* @param array $_api_data Optional data to send with API calls.
*/
public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
global $edd_plugin_data;
$this->api_url = trailingslashit( $_api_url );
$this->api_data = $_api_data;
$this->plugin_file = $_plugin_file;
$this->name = plugin_basename( $_plugin_file );
$this->slug = basename( $_plugin_file, '.php' );
$this->version = $_api_data['version'];
$this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
$this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
$this->failed_request_cache_key = 'edd_sl_failed_http_' . md5( $this->api_url );
$edd_plugin_data[$this->slug] = $this->api_data;
/**
* Fires after the $edd_plugin_data is setup.
*
* @since x.x.x
*
* @param array $edd_plugin_data Array of EDD SL plugin data.
*/
do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
// Set up hooks.
$this->init();
}
/**
* Set up WordPress filters to hook into WP's update process.
*
* @uses add_filter()
*
* @return void
*/
public function init() {
add_filter( 'pre_set_site_transient_update_plugins', [$this, 'check_update'] );
add_filter( 'plugins_api', [$this, 'plugins_api_filter'], 10, 3 );
add_action( 'after_plugin_row', [$this, 'show_update_notification'], 10, 2 );
add_action( 'admin_init', [$this, 'show_changelog'] );
}
/**
* Check for Updates at the defined API endpoint and modify the update array.
*
* This function dives into the update API just when WordPress creates its update array,
* then adds a custom API call and injects the custom plugin data retrieved from the API.
* It is reassembled from parts of the native WordPress plugin update code.
* See wp-includes/update.php line 121 for the original wp_update_plugins() function.
*
* @uses api_request()
*
* @param array $_transient_data Update array build by WordPress.
* @return array|object Modified update array with custom plugin data.
*/
public function check_update( $_transient_data ) {
global $pagenow;
if ( ! is_object( $_transient_data ) ) {
$_transient_data = new stdClass();
}
if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[$this->name] ) && false === $this->wp_override ) {
return $_transient_data;
}
$current = $this->get_repo_api_data();
if ( false !== $current && is_object( $current ) && isset( $current->new_version ) ) {
if ( version_compare( $this->version, $current->new_version, '<' ) ) {
$_transient_data->response[$this->name] = $current;
} else {
// Populating the no_update information is required to support auto-updates in WordPress 5.5.
$_transient_data->no_update[$this->name] = $current;
}
}
$_transient_data->last_checked = time();
$_transient_data->checked[$this->name] = $this->version;
return $_transient_data;
}
/**
* Get repo API data from store.
* Save to cache.
*
* @return stdClass|bool
*/
public function get_repo_api_data() {
$version_info = $this->get_cached_version_info();
if ( false === $version_info ) {
$version_info = $this->api_request(
'plugin_latest_version',
[
'slug' => $this->slug,
'beta' => $this->beta
]
);
if ( ! $version_info ) {
return false;
}
// This is required for your plugin to support auto-updates in WordPress 5.5.
$version_info->plugin = $this->name;
$version_info->id = $this->name;
$version_info->tested = $this->get_tested_version( $version_info );
$this->set_version_info_cache( $version_info );
}
return $version_info;
}
/**
* Gets the plugin's tested version.
*
* @since 1.9.2
* @param object $version_info
* @return null|string
*/
private function get_tested_version( $version_info ) {
// There is no tested version.
if ( empty( $version_info->tested ) ) {
return null;
}
// Strip off extra version data so the result is x.y or x.y.z.
list( $current_wp_version ) = explode( '-', get_bloginfo( 'version' ) );
// The tested version is greater than or equal to the current WP version, no need to do anything.
if ( version_compare( $version_info->tested, $current_wp_version, '>=' ) ) {
return $version_info->tested;
}
$current_version_parts = explode( '.', $current_wp_version );
$tested_parts = explode( '.', $version_info->tested );
// The current WordPress version is x.y.z, so update the tested version to match it.
if ( isset( $current_version_parts[2] ) && $current_version_parts[0] === $tested_parts[0] && $current_version_parts[1] === $tested_parts[1] ) {
$tested_parts[2] = $current_version_parts[2];
}
return implode( '.', $tested_parts );
}
/**
* Show the update notification on multisite subsites.
*
* @param string $file
* @param array $plugin
*/
public function show_update_notification( $file, $plugin ) {
// Return early if in the network admin, or if this is not a multisite install.
if ( is_network_admin() || ! is_multisite() ) {
return;
}
// Allow single site admins to see that an update is available.
if ( ! current_user_can( 'activate_plugins' ) ) {
return;
}
if ( $this->name !== $file ) {
return;
}
// Do not print any message if update does not exist.
$update_cache = get_site_transient( 'update_plugins' );
if ( ! isset( $update_cache->response[$this->name] ) ) {
if ( ! is_object( $update_cache ) ) {
$update_cache = new stdClass();
}
$update_cache->response[$this->name] = $this->get_repo_api_data();
}
// Return early if this plugin isn't in the transient->response or if the site is running the current or newer version of the plugin.
if ( empty( $update_cache->response[$this->name] ) || version_compare( $this->version, $update_cache->response[$this->name]->new_version, '>=' ) ) {
return;
}
printf(
'<tr class="plugin-update-tr %3$s" id="%1$s-update" data-slug="%1$s" data-plugin="%2$s">',
$this->slug,
$file,
in_array( $this->name, $this->get_active_plugins(), true ) ? 'active' : 'inactive'
);
echo '<td colspan="3" class="plugin-update colspanchange">';
echo '<div class="update-message notice inline notice-warning notice-alt"><p>';
$changelog_link = '';
if ( ! empty( $update_cache->response[$this->name]->sections->changelog ) ) {
$changelog_link = add_query_arg(
[
'edd_sl_action' => 'view_plugin_changelog',
'plugin' => urlencode( $this->name ),
'slug' => urlencode( $this->slug ),
'TB_iframe' => 'true',
'width' => 77,
'height' => 911
],
self_admin_url( 'index.php' )
);
}
$update_link = add_query_arg(
[
'action' => 'upgrade-plugin',
'plugin' => urlencode( $this->name )
],
self_admin_url( 'update.php' )
);
printf(
/* translators: the plugin name. */
esc_html__( 'There is a new version of %1$s available.', 'easy-digital-downloads' ),
esc_html( $plugin['Name'] )
);
if ( ! current_user_can( 'update_plugins' ) ) {
echo ' ';
esc_html_e( 'Contact your network administrator to install the update.', 'easy-digital-downloads' );
} elseif ( empty( $update_cache->response[$this->name]->package ) && ! empty( $changelog_link ) ) {
echo ' ';
printf(
/* translators: 1. opening anchor tag, do not translate 2. the new plugin version 3. closing anchor tag, do not translate. */
__( '%1$sView version %2$s details%3$s.', 'easy-digital-downloads' ),
'<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
esc_html( $update_cache->response[$this->name]->new_version ),
'</a>'
);
} elseif ( ! empty( $changelog_link ) ) {
echo ' ';
printf(
__( '%1$sView version %2$s details%3$s or %4$supdate now%5$s.', 'easy-digital-downloads' ),
'<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
esc_html( $update_cache->response[$this->name]->new_version ),
'</a>',
'<a target="_blank" class="update-link" href="' . esc_url( wp_nonce_url( $update_link, 'upgrade-plugin_' . $file ) ) . '">',
'</a>'
);
} else {
printf(
' %1$s%2$s%3$s',
'<a target="_blank" class="update-link" href="' . esc_url( wp_nonce_url( $update_link, 'upgrade-plugin_' . $file ) ) . '">',
esc_html__( 'Update now.', 'easy-digital-downloads' ),
'</a>'
);
}
do_action( "in_plugin_update_message-{$file}", $plugin, $plugin );
echo '</p></div></td></tr>';
}
/**
* Gets the plugins active in a multisite network.
*
* @return array
*/
private function get_active_plugins() {
$active_plugins = (array) get_option( 'active_plugins' );
$active_network_plugins = (array) get_site_option( 'active_sitewide_plugins' );
return array_merge( $active_plugins, array_keys( $active_network_plugins ) );
}
/**
* Updates information on the "View version x.x details" page with custom data.
*
* @uses api_request()
*
* @param mixed $_data
* @param string $_action
* @param object $_args
* @return object $_data
*/
public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
if ( 'plugin_information' !== $_action ) {
return $_data;
}
if ( ! isset( $_args->slug ) || ( $_args->slug !== $this->slug ) ) {
return $_data;
}
$to_send = [
'slug' => $this->slug,
'is_ssl' => is_ssl(),
'fields' => [
'banners' => [],
'reviews' => false,
'icons' => []
]
];
// Get the transient where we store the api request for this plugin for 24 hours
$edd_api_request_transient = $this->get_cached_version_info();
//If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
if ( empty( $edd_api_request_transient ) ) {
$api_response = $this->api_request( 'plugin_information', $to_send );
// Expires in 3 hours
$this->set_version_info_cache( $api_response );
if ( false !== $api_response ) {
$_data = $api_response;
}
} else {
$_data = $edd_api_request_transient;
}
// Convert sections into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
$_data->sections = $this->convert_object_to_array( $_data->sections );
}
// Convert banners into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
$_data->banners = $this->convert_object_to_array( $_data->banners );
}
// Convert icons into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
$_data->icons = $this->convert_object_to_array( $_data->icons );
}
// Convert contributors into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->contributors ) && ! is_array( $_data->contributors ) ) {
$_data->contributors = $this->convert_object_to_array( $_data->contributors );
}
if ( ! isset( $_data->plugin ) ) {
$_data->plugin = $this->name;
}
return $_data;
}
/**
* Convert some objects to arrays when injecting data into the update API
*
* Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
* decoding, they are objects. This method allows us to pass in the object and return an associative array.
*
* @since 3.6.5
*
* @param stdClass $data
*
* @return array
*/
private function convert_object_to_array( $data ) {
if ( ! is_array( $data ) && ! is_object( $data ) ) {
return [];
}
$new_data = [];
foreach ( $data as $key => $value ) {
$new_data[$key] = is_object( $value ) ? $this->convert_object_to_array( $value ) : $value;
}
return $new_data;
}
/**
* Disable SSL verification in order to prevent download update failures
*
* @param array $args
* @param string $url
* @return array $array
*/
public function http_request_args( $args, $url ) {
if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
$args['sslverify'] = $this->verify_ssl();
}
return $args;
}
/**
* Calls the API and, if successfull, returns the object delivered by the API.
*
* @uses get_bloginfo()
* @uses wp_remote_post()
* @uses is_wp_error()
*
* @param string $_action The requested action.
* @param array $_data Parameters for the API action.
* @return false|object|void
*/
private function api_request( $_action, $_data ) {
$data = array_merge( $this->api_data, $_data );
if ( $data['slug'] !== $this->slug ) {
return;
}
// Don't allow a plugin to ping itself
if ( trailingslashit( home_url() ) === $this->api_url ) {
return false;
}
if ( $this->request_recently_failed() ) {
return false;
}
return $this->get_version_from_remote();
}
/**
* Determines if a request has recently failed.
*
* @since 1.9.1
*
* @return bool
*/
private function request_recently_failed() {
$failed_request_details = get_option( $this->failed_request_cache_key );
// Request has never failed.
if ( empty( $failed_request_details ) || ! is_numeric( $failed_request_details ) ) {
return false;
}
/*
* Request previously failed, but the timeout has expired.
* This means we're allowed to try again.
*/
if ( time() > $failed_request_details ) {
delete_option( $this->failed_request_cache_key );
return false;
}
return true;
}
/**
* Logs a failed HTTP request for this API URL.
* We set a timestamp for 1 hour from now. This prevents future API requests from being
* made to this domain for 1 hour. Once the timestamp is in the past, API requests
* will be allowed again. This way if the site is down for some reason we don't bombard
* it with failed API requests.
*
* @see EDD_SL_Plugin_Updater::request_recently_failed
*
* @since 1.9.1
*/
private function log_failed_request() {
update_option( $this->failed_request_cache_key, strtotime( '+1 hour' ) );
}
/**
* If available, show the changelog for sites in a multisite install.
*/
public function show_changelog() {
if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' !== $_REQUEST['edd_sl_action'] ) {
return;
}
if ( empty( $_REQUEST['plugin'] ) ) {
return;
}
if ( empty( $_REQUEST['slug'] ) || $this->slug !== $_REQUEST['slug'] ) {
return;
}
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die( esc_html__( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), esc_html__( 'Error', 'easy-digital-downloads' ), ['response' => 403] );
}
$version_info = $this->get_repo_api_data();
if ( isset( $version_info->sections ) ) {
$sections = $this->convert_object_to_array( $version_info->sections );
if ( ! empty( $sections['changelog'] ) ) {
echo '<div style="background:#fff;padding:10px;">' . wp_kses_post( $sections['changelog'] ) . '</div>';
}
}
exit;
}
/**
* Gets the current version information from the remote site.
*
* @return array|false
*/
private function get_version_from_remote() {
$api_params = [
'edd_action' => 'get_version',
'license' => ! empty( $this->api_data['license'] ) ? $this->api_data['license'] : '',
'item_name' => isset( $this->api_data['item_name'] ) ? $this->api_data['item_name'] : false,
'item_id' => isset( $this->api_data['item_id'] ) ? $this->api_data['item_id'] : false,
'version' => isset( $this->api_data['version'] ) ? $this->api_data['version'] : false,
'slug' => $this->slug,
'author' => $this->api_data['author'],
'url' => home_url(),
'beta' => $this->beta,
'php_version' => phpversion(),
'wp_version' => get_bloginfo( 'version' )
];
/**
* Filters the parameters sent in the API request.
*
* @param array $api_params The array of data sent in the request.
* @param array $this->api_data The array of data set up in the class constructor.
* @param string $this->plugin_file The full path and filename of the file.
*/
$api_params = apply_filters( 'edd_sl_plugin_updater_api_params', $api_params, $this->api_data, $this->plugin_file );
$request = wp_remote_post(
$this->api_url,
[
'timeout' => 15,
'sslverify' => $this->verify_ssl(),
'body' => $api_params
]
);
if ( is_wp_error( $request ) || ( 200 !== wp_remote_retrieve_response_code( $request ) ) ) {
$this->log_failed_request();
return false;
}
$request = json_decode( wp_remote_retrieve_body( $request ) );
if ( $request && isset( $request->sections ) ) {
$request->sections = maybe_unserialize( $request->sections );
} else {
$request = false;
}
if ( $request && isset( $request->banners ) ) {
$request->banners = maybe_unserialize( $request->banners );
}
if ( $request && isset( $request->icons ) ) {
$request->icons = maybe_unserialize( $request->icons );
}
if ( ! empty( $request->sections ) ) {
foreach ( $request->sections as $key => $section ) {
$request->$key = (array) $section;
}
}
return $request;
}
/**
* Get the version info from the cache, if it exists.
*
* @param string $cache_key
* @return mixed
*/
public function get_cached_version_info( $cache_key = '' ) {
if ( empty( $cache_key ) ) {
$cache_key = $this->get_cache_key();
}
$cache = get_option( $cache_key );
// Cache is expired
if ( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
return false;
}
// We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
$cache['value'] = json_decode( $cache['value'] );
if ( ! empty( $cache['value']->icons ) ) {
$cache['value']->icons = (array) $cache['value']->icons;
}
return $cache['value'];
}
/**
* Adds the plugin version information to the database.
*
* @param string $value
* @param string $cache_key
*/
public function set_version_info_cache( $value = '', $cache_key = '' ) {
if ( empty( $cache_key ) ) {
$cache_key = $this->get_cache_key();
}
$data = [
'timeout' => strtotime( '+3 hours', time() ),
'value' => wp_json_encode( $value )
];
update_option( $cache_key, $data, 'no' );
// Delete the duplicate option
delete_option( 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) ) );
}
/**
* Returns if the SSL of the store should be verified.
*
* @since 1.6.13
* @return bool
*/
private function verify_ssl() {
return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
}
/**
* Gets the unique key (option name) for a plugin.
*
* @since 1.9.0
* @return string
*/
private function get_cache_key() {
$string = $this->slug . $this->api_data['license'] . $this->beta;
return 'edd_sl_' . md5( serialize( $string ) );
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes\License;
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use Exception;
use WP_REST_Server;
use Essential_Addons_Elementor\Pro\Classes\License\Contracts\ApiAdapter;
#[\AllowDynamicProperties]
class RESTApi extends ApiAdapter {
private $version = 'v1';
public function register() {
if ( ! isset( $this->namespace ) ) {
throw new Exception( "namespace is missing in your rest configuration." );
}
add_action( 'rest_api_init', [$this, 'routes'] );
}
public function get_api_config() {
return array_merge( parent::get_api_config(), [
'api_url' => esc_url( trailingslashit( rest_url( $this->get_namespace() ) ) )
] );
}
public function routes() {
$this->route( '/license/activate', [$this, 'activate'], $this->args() );
$this->route( '/license/deactivate', [$this, 'deactivate'] );
$this->route( '/license/submit-otp', [$this, 'submit_otp'], $this->args([
'otp' => [
'required' => true,
'validate_callback' => function ( $param, $request, $key ) {
return is_string( $param ) && ! empty( $param );
}
]
]) );
$this->route( '/license/resend-otp', [$this, 'resend_otp'], $this->args() );
$this->route( '/license/get-license', [$this, 'get_license'] );
}
public function activate( $request ) {
return $this->license_manager->activate( [
'license_key' => sanitize_text_field( $request->get_param( 'license_key' ) )
] );
}
public function deactivate( $request ) {
return $this->license_manager->deactivate();
}
/**
* Handles OTP submission request.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_Error|WP_REST_Response
*/
public function submit_otp( $request ) {
$args = [
'otp' => sanitize_text_field( $request->get_param( 'otp') ),
'license_key' => sanitize_text_field( $request->get_param( 'license_key') )
];
return $this->license_manager->submit_otp( $args );
}
/**
* Handles OTP resend request.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_Error|WP_REST_Response
*/
public function resend_otp( $request ) {
$args = [
'license_key' => sanitize_text_field( $request->get_param( 'license_key') )
];
return $this->license_manager->resend_otp( $args );
}
/**
* Retrieves the license details.
*
* This method uses the LicenseManager to get the license data, hide the license key, and format the title.
* It then returns an array with the title, hidden license key, and license status.
*
* @return array An array containing the title, hidden license key, and license status.
*/
public function get_license(){
$license_data = $this->license_manager->get_license_data();
$license_key = $this->license_manager->hide_license_key($license_data['license_key']);
$status = $license_data['license_status'];
$title = sprintf(__('%s License', $this->license_manager->textdomain), $this->license_manager->item_name);
return ['title' => $title, 'key' => $license_key, 'status' => $status];
}
protected function args($args = []) {
return wp_parse_args($args, [
'license_key' => [
'required' => true,
'validate_callback' => function ( $param, $request, $key ) {
return is_string( $param ) && ! empty( $param );
}
]
]);
}
private function get_namespace() {
return $this->namespace . '/' . $this->version;
}
protected function route( $endpoint, $callback, $args = [] ) {
return register_rest_route( $this->get_namespace(), $endpoint, [
'methods' => WP_REST_Server::CREATABLE,
'callback' => $callback,
'permission_callback' => [$this, 'permission_check'],
'args' => $args
] );
}
}

View File

@@ -0,0 +1,83 @@
<div class="eael-block p45 eael-activate__license__block --activation-form" style="display: <?php echo ( $status === false || $status !== 'valid' ) ? 'block' : 'none'; ?>">
<div class="eael__flex eael__flex--wrap align__center mb30">
<h3>Just one more step to go!</h3>
<img src="<?php echo esc_url( EAEL_PLUGIN_URL . 'assets/admin/images/steps.svg' ); ?>" alt="">
</div>
<p><?php _e( 'Enter your license key here, to activate <strong>Essential Addons for Elementor</strong>, and get automatic updates and premium support.', $this->text_domain ); ?></p>
<p><?php printf( __( 'Visit the <a href="%s" target="_blank">Validation Guide</a> for help.', $this->text_domain ), 'https://essential-addons.com/elementor/docs/getting-started/validating-license/' ); ?></p>
<ol>
<li>
<p><?php printf( __( 'Log in to <a href="%s" target="_blank">your account</a> to get your license key.', $this->text_domain ), 'https://wpdeveloper.com/account/' ); ?></p>
</li>
<li>
<p><?php printf( __( 'If you don\'t yet have a license key, get <a href="%s" target="_blank">Essential Addons for Elementor now</a>.', $this->text_domain ), 'https://wpdeveloper.com/in/upgrade-essential-addons-elementor' ); ?></p>
</li>
<li><?php _e( __( 'Copy the license key from your account and paste it below.', $this->text_domain ) ); ?></li>
<li><?php _e( __( 'Click on <strong>"Activate License"</strong> button.', $this->text_domain ) ); ?></li>
</ol>
<div class="license__form__block">
<div class="eael-license-form-block">
<form method="post" action="#">
<?php wp_nonce_field( $this->args['item_slug'] . '_license_nonce', $this->args['item_slug'] . '_license_nonce' ); ?>
<input id="<?php echo $this->args['item_slug']; ?>-license-key" type="text" class="eael-form__control" placeholder="Place Your License Key & Activate">
<button type="submit" class="eael-button button__themeColor" name="license_activate">Activate</button>
</form>
</div>
</div>
<div class="eael-verification-msg" style="display: none;">
<p>License Verification code has been sent to this <span class="eael-customer-email"></span>. Please check your email for the code &amp; insert it below 👇</p>
<div class="short-description">
<b style="font-weight: 700;">Note: </b> Check out this <a href="https://essential-addons.com/docs/verify-essential-addons-pro-license-key/" target="_blank">guide</a> to
verify your license key. If you need any assistance with retrieving your License Verification Key, please <a href="https://wpdeveloper.com/support/"
target="_blank">contact support</a>.
</div>
<div class="eael-verification-input-container license__form__block">
<div class="eael-license-form-block">
<input type="text" id="<?php echo $this->args['item_slug']; ?>-license-otp" class="eael-form__control" placeholder="Enter Your Verification Code">
<button type="submit" class="eael-button button__themeColor">Verify</button>
</div>
<p>Havent received an email? Please hit this <a href="#" class="eael-otp-resend">"Resend"</a> to retry. Please note that this verification code will
expire after 15 minutes.</p>
</div>
</div>
<p class="eael-license-error-msg error-message" style="display: none;"></p>
</div>
<div class="eael-block p45 eael-activate__license__block --deactivation-form" style="display: <?php echo ( $status !== false && $status === 'valid' ) ? 'block' : 'none'; ?>">
<div class="eael-grid">
<div class="eael-col-md-6">
<ul class="eael-feature__list ls-none">
<li class="feature__item">
<span class="icon">
<img src="<?php echo EAEL_PRO_PLUGIN_URL . 'assets/admin/images/icon-auto-update.svg'; ?>" alt="essential-addons-auto-update">
</span>
<div class="content">
<h4>Premium Support</h4>
<p>Supported by professional and courteous staff.</p>
</div>
</li>
<li class="feature__item">
<span class="icon">
<img src="<?php echo EAEL_PRO_PLUGIN_URL . 'assets/admin/images/icon-auto-update.svg'; ?>" alt="essential-addons-auto-update">
</span>
<div class="content">
<h4>Auto Update</h4>
<p>Update the plugin right from your WordPress Dashboard.</p>
</div>
</li>
</ul>
</div>
<div class="eael-col-md-6">
<div class="license__form__block">
<div class="eael-license-form-block">
<form method="post" action="#">
<input class="eael-form__control regular-text" disabled type="text" value="<?php echo esc_attr( $hidden_license_key ); ?>"
placeholder="Place Your License Key and Activate"/>
<button type="submit" class="eael-button button__danger" name="license_deactivate">Deactivate</button>
</form>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,129 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes;
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
use \Essential_Addons_Elementor\Pro\Classes\Plugin_Updater;
class Migration
{
use \Essential_Addons_Elementor\Pro\Traits\Library;
use \Essential_Addons_Elementor\Pro\Traits\Core;
/**
* Plugin activation hook
*
* @since 3.0.0
*/
public function plugin_activation_hook()
{
// remove old cache files
if (defined('EAEL_ASSET_PATH')) {
$this->empty_dir(EAEL_ASSET_PATH);
}
// save default options value
$this->set_default_values();
// make lite version available
set_transient('eael_install_lite', true, 1800);
}
/**
* Plugin deactivation hook
*
* @since 3.0.0
*/
public function plugin_deactivation_hook()
{
// remove old cache files
if (defined('EAEL_ASSET_PATH')) {
$this->empty_dir(EAEL_ASSET_PATH);
}
}
/**
* Plugin upgrade hook
*
* @since 3.0.0
*/
public function plugin_upgrade_hook($upgrader_object, $options)
{
if ($options['action'] == 'update' && $options['type'] == 'plugin') {
if (isset($options['plugins'][EAEL_PRO_PLUGIN_BASENAME])) {
// remove old cache files
if (defined('EAEL_ASSET_PATH')) {
$this->empty_dir(EAEL_ASSET_PATH);
}
}
}
}
/**
* Plugin upgrader
*
* @since v1.0.0
*/
public function plugin_updater()
{
// Disable SSL verification
add_filter('edd_sl_api_request_verify_ssl', '__return_false');
// Setup the updater
$license = get_option(EAEL_SL_ITEM_SLUG . '-license-key');
$updater = new Plugin_Updater(
EAEL_STORE_URL,
EAEL_PRO_PLUGIN_BASENAME,
[
'version' => EAEL_PRO_PLUGIN_VERSION,
'license' => $license,
'item_id' => EAEL_SL_ITEM_ID,
'author' => 'WPDeveloper',
]
);
}
/**
* Plugin migrator
*
* @since 3.0.0
*/
public function migrator()
{
// migration trick
if (get_option('eael_pro_version') != EAEL_PRO_PLUGIN_VERSION) {
// set current version to db
update_option('eael_pro_version', EAEL_PRO_PLUGIN_VERSION);
/**
* Tricky update here
*
* @since 3.0.4
*/
// make lite version available
if(function_exists('wp_get_environment_type')){
if (wp_get_environment_type() !== 'development') {
set_transient('eael_install_lite', true, 1800);
}
}
}
// check for lite version
if ((boolean) get_transient('eael_install_lite') === true) {
// install lite version
$this->make_lite_available();
// disabled temporarily
// if ($this->make_lite_available()) {
// // redirect to plugin dashboard
// die(wp_redirect("admin.php?page=eael-settings"));
// }
}
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes;
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
class Notice
{
use \Essential_Addons_Elementor\Pro\Traits\Library;
/**
* This notice will appear if Elementor is not installed or activated or both
*/
public function failed_to_load()
{
if (!current_user_can('activate_plugins')) {
return;
}
if (did_action('eael/before_init')) {
return;
}
if (get_transient('eael_install_lite')) {
return;
}
$plugin = 'essential-addons-for-elementor-lite/essential_adons_elementor.php';
if ($this->is_plugin_installed($plugin) && !$this->is_plugin_active($plugin)) {
$activation_url = wp_nonce_url('plugins.php?action=activate&amp;plugin=' . $plugin . '&amp;plugin_status=all&amp;paged=1&amp;s', 'activate-plugin_' . $plugin);
$message = __('<strong>Essential Addons for Elementor - Pro</strong> requires <strong>Essential Addons for Elementor</strong> plugin to be active. Please activate Essential Addons for Elementor to continue.', 'essential-addons-elementor');
$button_text = __('Activate Essential Addons for Elementor', 'essential-addons-elementor');
} else if(!$this->is_plugin_installed($plugin)) {
$activation_url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=essential-addons-for-elementor-lite'), 'install-plugin_essential-addons-for-elementor-lite');
$message = sprintf(__('<strong>Essential Addons for Elementor - Pro</strong> requires <strong>Essential Addons for Elementor</strong> plugin to be installed and activated. Please install Essential Addons for Elementor to continue.', 'essential-addons-elementor'), '<strong>', '</strong>');
$button_text = __('Install Essential Addons for Elementor', 'essential-addons-elementor');
}
if(!empty($activation_url)){
$button = '<p><a href="' . $activation_url . '" class="button-primary">' . $button_text . '</a></p>';
printf('<div class="error"><p>%1$s</p>%2$s</div>', __($message), $button);
}
}
}

View File

@@ -0,0 +1,469 @@
<?php
namespace Essential_Addons_Elementor\Pro\Classes;
// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}
/**
* Allows plugins to use their own update API.
*
* @author Easy Digital Downloads
* @version 1.6.15
*/
class Plugin_Updater
{
private $api_url = '';
private $api_data = array();
private $name = '';
private $slug = '';
private $version = '';
private $wp_override = false;
private $cache_key = '';
private $beta;
/**
* Class constructor.
*
* @uses plugin_basename()
* @uses hook()
*
* @param string $_api_url The URL pointing to the custom API endpoint.
* @param string $_plugin_file Path to the plugin file.
* @param array $_api_data Optional data to send with API calls.
*/
public function __construct($_api_url, $_plugin_file, $_api_data = null)
{
global $edd_plugin_data;
$this->api_url = trailingslashit($_api_url);
$this->api_data = $_api_data;
$this->name = plugin_basename($_plugin_file);
$this->slug = basename($_plugin_file, '.php');
$this->version = $_api_data['version'];
$this->wp_override = isset($_api_data['wp_override']) ? (bool) $_api_data['wp_override'] : false;
$this->beta = !empty($this->api_data['beta']) ? true : false;
$this->cache_key = 'edd_sl_' . md5(serialize($this->slug . $this->api_data['license'] . $this->beta));
$edd_plugin_data[$this->slug] = $this->api_data;
// Set up hooks.
$this->init();
}
/**
* Set up WordPress filters to hook into WP's update process.
*
* @uses add_filter()
*
* @return void
*/
public function init()
{
add_filter('pre_set_site_transient_update_plugins', array($this, 'check_update'));
add_filter('plugins_api', array($this, 'plugins_api_filter'), 10, 3);
remove_action('after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10);
add_action('after_plugin_row_' . $this->name, array($this, 'show_update_notification'), 10, 2);
add_action('admin_init', array($this, 'show_changelog'));
}
/**
* Check for Updates at the defined API endpoint and modify the update array.
*
* This function dives into the update API just when WordPress creates its update array,
* then adds a custom API call and injects the custom plugin data retrieved from the API.
* It is reassembled from parts of the native WordPress plugin update code.
* See wp-includes/update.php line 121 for the original wp_update_plugins() function.
*
* @uses api_request()
*
* @param array $_transient_data Update array build by WordPress.
* @return array Modified update array with custom plugin data.
*/
public function check_update($_transient_data)
{
global $pagenow;
if (!is_object($_transient_data)) {
$_transient_data = new \stdClass();
}
if ('plugins.php' == $pagenow && is_multisite()) {
return $_transient_data;
}
if (!empty($_transient_data->response) && !empty($_transient_data->response[$this->name]) && false === $this->wp_override) {
return $_transient_data;
}
$version_info = $this->get_cached_version_info();
if (false === $version_info) {
$version_info = $this->api_request('plugin_latest_version', array('slug' => $this->slug, 'beta' => $this->beta));
$this->set_version_info_cache($version_info);
}
if (false !== $version_info && is_object($version_info) && isset($version_info->new_version)) {
if (version_compare($this->version, $version_info->new_version, '<')) {
$_transient_data->response[$this->name] = $version_info;
}
$_transient_data->last_checked = current_time('timestamp');
$_transient_data->checked[$this->name] = $this->version;
}
return $_transient_data;
}
/**
* show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
*
* @param string $file
* @param array $plugin
*/
public function show_update_notification($file, $plugin)
{
if (is_network_admin()) {
return;
}
if (!current_user_can('update_plugins')) {
return;
}
if (!is_multisite()) {
return;
}
if ($this->name != $file) {
return;
}
// Remove our filter on the site transient
remove_filter('pre_set_site_transient_update_plugins', array($this, 'check_update'), 10);
$update_cache = get_site_transient('update_plugins');
$update_cache = is_object($update_cache) ? $update_cache : new \stdClass();
if (empty($update_cache->response) || empty($update_cache->response[$this->name])) {
$version_info = $this->get_cached_version_info();
if (false === $version_info) {
$version_info = $this->api_request('plugin_latest_version', array('slug' => $this->slug, 'beta' => $this->beta));
$this->set_version_info_cache($version_info);
}
if (!is_object($version_info)) {
return;
}
if (version_compare($this->version, $version_info->new_version, '<')) {
$update_cache->response[$this->name] = $version_info;
}
$update_cache->last_checked = current_time('timestamp');
$update_cache->checked[$this->name] = $this->version;
set_site_transient('update_plugins', $update_cache);
} else {
$version_info = $update_cache->response[$this->name];
}
// Restore our filter
add_filter('pre_set_site_transient_update_plugins', array($this, 'check_update'));
if (!empty($update_cache->response[$this->name]) && version_compare($this->version, $version_info->new_version, '<')) {
// build a plugin list row, with update notification
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
# <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
echo '<td colspan="3" class="plugin-update colspanchange">';
echo '<div class="update-message notice inline notice-warning notice-alt">';
$changelog_link = self_admin_url('index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911');
if (empty($version_info->download_link)) {
printf(
__('There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads'),
esc_html($version_info->name),
'<a target="_blank" class="thickbox" href="' . esc_url($changelog_link) . '">',
esc_html($version_info->new_version),
'</a>'
);
} else {
printf(
__('There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads'),
esc_html($version_info->name),
'<a target="_blank" class="thickbox" href="' . esc_url($changelog_link) . '">',
esc_html($version_info->new_version),
'</a>',
'<a href="' . esc_url(wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&plugin=') . $this->name, 'upgrade-plugin_' . $this->name)) . '">',
'</a>'
);
}
do_action("in_plugin_update_message-{$file}", $plugin, $version_info);
echo '</div></td></tr>';
}
}
/**
* Updates information on the "View version x.x details" page with custom data.
*
* @uses api_request()
*
* @param mixed $_data
* @param string $_action
* @param object $_args
* @return object $_data
*/
public function plugins_api_filter($_data, $_action = '', $_args = null)
{
if ($_action != 'plugin_information') {
return $_data;
}
if (!isset($_args->slug) || ($_args->slug != $this->slug)) {
return $_data;
}
$to_send = array(
'slug' => $this->slug,
'is_ssl' => is_ssl(),
'fields' => array(
'banners' => array(),
'reviews' => false,
),
);
$cache_key = 'edd_api_request_' . md5(serialize($this->slug . $this->api_data['license'] . $this->beta));
// Get the transient where we store the api request for this plugin for 24 hours
$edd_api_request_transient = $this->get_cached_version_info($cache_key);
//If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
if (empty($edd_api_request_transient)) {
$api_response = $this->api_request('plugin_information', $to_send);
// Expires in 3 hours
$this->set_version_info_cache($api_response, $cache_key);
if (false !== $api_response) {
$_data = $api_response;
}
} else {
$_data = $edd_api_request_transient;
}
// Convert sections into an associative array, since we're getting an object, but Core expects an array.
if (isset($_data->sections) && !is_array($_data->sections)) {
$new_sections = array();
foreach ($_data->sections as $key => $value) {
$new_sections[$key] = $value;
}
$_data->sections = $new_sections;
}
// Convert banners into an associative array, since we're getting an object, but Core expects an array.
if (isset($_data->banners) && !is_array($_data->banners)) {
$new_banners = array();
foreach ($_data->banners as $key => $value) {
$new_banners[$key] = $value;
}
$_data->banners = $new_banners;
}
return $_data;
}
/**
* Disable SSL verification in order to prevent download update failures
*
* @param array $args
* @param string $url
* @return object $array
*/
public function http_request_args($args, $url)
{
$verify_ssl = $this->verify_ssl();
if (strpos($url, 'https://') !== false && strpos($url, 'edd_action=package_download')) {
$args['sslverify'] = $verify_ssl;
}
return $args;
}
/**
* Calls the API and, if successfull, returns the object delivered by the API.
*
* @uses get_bloginfo()
* @uses wp_remote_post()
* @uses is_wp_error()
*
* @param string $_action The requested action.
* @param array $_data Parameters for the API action.
* @return false|object
*/
private function api_request($_action, $_data)
{
global $wp_version;
$data = array_merge($this->api_data, $_data);
if ($data['slug'] != $this->slug) {
return;
}
if ($this->api_url == trailingslashit(home_url())) {
return false; // Don't allow a plugin to ping itself
}
$api_params = array(
'edd_action' => 'get_version',
'license' => !empty($data['license']) ? $data['license'] : '',
'item_name' => isset($data['item_name']) ? $data['item_name'] : false,
'item_id' => isset($data['item_id']) ? $data['item_id'] : false,
'version' => isset($data['version']) ? $data['version'] : false,
'slug' => $data['slug'],
'author' => $data['author'],
'url' => home_url(),
'beta' => !empty($data['beta']),
);
$verify_ssl = $this->verify_ssl();
$request = wp_remote_post($this->api_url, array('timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params));
if (!is_wp_error($request)) {
$request = json_decode(wp_remote_retrieve_body($request));
}
if ($request && isset($request->sections)) {
$request->sections = maybe_unserialize($request->sections);
} else {
$request = false;
}
if ($request && isset($request->banners)) {
$request->banners = maybe_unserialize($request->banners);
}
if (!empty($request->sections)) {
foreach ($request->sections as $key => $section) {
$request->$key = (array) $section;
}
}
return $request;
}
public function show_changelog() {
global $edd_plugin_data;
if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' !== $_REQUEST['edd_sl_action'] ) {
return;
}
if ( empty( $_REQUEST['plugin'] ) || EAEL_PRO_PLUGIN_BASENAME !== $_REQUEST['plugin'] ) {
return;
}
if ( empty( $_REQUEST['slug'] ) ) {
return;
}
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
}
$data = $edd_plugin_data[ $_REQUEST['slug'] ];
$beta = ! empty( $data['beta'] ) ? true : false;
$cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $beta . '_version_info' );
$version_info = $this->get_cached_version_info( $cache_key );
if ( false === $version_info ) {
$api_params = array(
'edd_action' => 'get_version',
'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
'slug' => $_REQUEST['slug'],
'author' => $data['author'],
'url' => home_url(),
'beta' => ! empty( $data['beta'] ),
);
$verify_ssl = $this->verify_ssl();
$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
if ( ! is_wp_error( $request ) ) {
$version_info = json_decode( wp_remote_retrieve_body( $request ) );
}
if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
$version_info->sections = maybe_unserialize( $version_info->sections );
} else {
$version_info = false;
}
if ( ! empty( $version_info ) ) {
foreach ( $version_info->sections as $key => $section ) {
$version_info->$key = (array) $section;
}
}
$this->set_version_info_cache( $version_info, $cache_key );
}
if ( ! empty( $version_info ) && isset( $version_info->sections->changelog ) ) {
echo '<div style="background:#fff;padding:10px;">' . $version_info->sections->changelog . '</div>';
}
exit;
}
public function get_cached_version_info($cache_key = '')
{
if (empty($cache_key)) {
$cache_key = $this->cache_key;
}
$cache = get_option($cache_key);
if (empty($cache['timeout']) || current_time('timestamp') > $cache['timeout']) {
return false; // Cache is expired
}
return json_decode($cache['value']);
}
public function set_version_info_cache($value = '', $cache_key = '')
{
if (empty($cache_key)) {
$cache_key = $this->cache_key;
}
$data = array(
'timeout' => strtotime('+3 hours', current_time('timestamp')),
'value' => json_encode($value),
);
update_option($cache_key, $data, 'no');
}
/**
* Returns if the SSL of the store should be verified.
*
* @since 1.6.13
* @return bool
*/
private function verify_ssl()
{
return (bool) apply_filters('edd_sl_api_request_verify_ssl', true, $this);
}
}