'wp-rocket/wp-rocket.php', 'rank-math' => 'seo-by-rank-math-pro/rank-math-pro.php', ); const ADDONS_SLUGS = array( 'wp-rocket' => 'WP_ROCKET', 'rank-math' => 'RANK_MATH' ); const PLUGIN_SLUGS_NAME = array( 'wp-rocket' => 'WP Rocket', 'rank-math' => 'Rank Math PRO' ); CONST ITEM_CATEGORY = array( 'wp-rocket' => 'performance', 'rank-math' => 'seo' ); CONST PLUGIN_SLUGS = array( 'wp-rocket' => 'wp-rocket', 'rank-math' => 'seo-by-rank-math-pro' ); public array $contact_support_links = array( 'en' => 'https://help.one.com/hc/en-us/requests/new', 'da' => 'https://help.one.com/hc/da/requests/new', 'de' => 'https://help.one.com/hc/de/requests/new', 'es' => 'https://help.one.com/hc/es/requests/new', 'fr' => 'https://help.one.com/hc/fr/requests/new', 'fi' => 'https://help.one.com/hc/fi/requests/new', 'it' => 'https://help.one.com/hc/it/requests/new', 'nl' => 'https://help.one.com/hc/nl/requests/new', 'no' => 'https://help.one.com/hc/no/requests/new', 'pt' => 'https://help.one.com/hc/pt/requests/new', 'sv' => 'https://help.one.com/hc/sv/requests/new' ); /** * Constructor is intentionally empty. Initialization is handled via init(). * @note This class is designed for use with WordPress hooks and AJAX actions, so no setup is required here. */ public function __construct() { } // Initialize actions public function init(): void { add_action('admin_enqueue_scripts', [$this, 'enqueueScripts']); add_action('wp_ajax_marketplace_plugin_activate', [$this, 'onclickPluginActivate']); add_action('wp_ajax_marketplace_plugin_activate_reload', [$this, 'onReloadPluginActivateCheck']); add_action('wp_ajax_marketplace_addon_purchase_check', [$this, 'addonStatusCheck']); add_action('wp_ajax_marketplace_addon_purchase_check_onload', [$this, 'addonStatusCheckOnLoad']); //Check addon activation banner on products page reload add_action('wp_ajax_marketplace_check_activate_banner', [$this, 'checkActivateBannerOnReload']); //Can use in marketplace service also to check addon purchase status add_action('wp_ajax_get_addon_purchase_status', [$this, 'isAddonPurchased']); //disable activation banner on plugin deactivation add_action('deactivated_plugin', [$this, 'pluginDeactivated'], 10, 2); } // Load scripts on relevant admin pages public function enqueueScripts($hook_suffix): void { $allowed_pages = [ 'one-com_page_' . MARKETPLACE_PAGE_SLUG, 'one-com_page_' . MARKETPLACE_PRODUCTS_PAGE_SLUG, ]; if (!in_array($hook_suffix, $allowed_pages)) { return; } wp_enqueue_style('oc_mp_style', ONECOM_WP_URL . 'modules/marketplace/assets/css/marketplace.css', [], ONECOM_WP_VERSION); wp_enqueue_script('oc_mp_script', ONECOM_WP_URL . 'modules/marketplace/assets/js/marketplace.js', ['jquery'], ONECOM_WP_VERSION, true); // Localize JS with config wp_localize_script( 'oc_mp_script', 'mp_config', [ 'ajaxURL' => admin_url( 'admin-ajax.php' ), 'mp_asset_url' => ONECOM_WP_URL . 'modules/marketplace/assets/images/', 'wp_rocket_buy_url' => OC_WPR_BUY_URL, 'rank_math_buy_url' => OC_RM_PRO_BUY_URL, 'wp_rocket_manage_url' => admin_url('options-general.php?page=wprocket'), 'rank_math_manage_url' => admin_url('admin.php?page=rank-math&view=modules'), 'marketplace_page_slug' => MARKETPLACE_PAGE_SLUG, 'marketplace_products_page_slug' => MARKETPLACE_PRODUCTS_PAGE_SLUG, 'mp_labels'=> array( 'install' => __('ui.notifications.installing', 'onecom-wp'), 'error_installing' => __("Couldn’t install plugin.", 'onecom-wp'), 'deactivate' => __('Deactivate', 'onecom-wp'), 'install_success' => __('Plugin installed successfully.', 'onecom-wp'), 'wp_rocket' => __('WP Rocket', 'onecom-wp'), 'rank_math' => __('Rank Math PRO', 'onecom-wp'), 'active' => __('Active', 'onecom-wp'), 'rank-math' => 'seo-by-rank-math-pro', 'wp-rocket' => 'wp-rocket', 'plugin_activated' => array( 'title' => __('Plugin was activated', 'onecom-wp'), 'description' => __('You can start using it.', 'onecom-wp'), 'btn_text' => __('Manage', 'onecom-wp'), 'wp-rocket_link' => $this->getNoticePluginUrl('wp-rocket'), 'rank-math_link' => $this->getNoticePluginUrl('rank-math'), ), 'plugin_installed' => array( 'title' => __('Plugin was installed.', 'onecom-wp'), 'description' => __('Activate it now to start using it.', 'onecom-wp'), 'btn_text' => __('Activate', 'onecom-wp'), 'wp-rocket_link' => $this->getNoticePluginUrl('wp-rocket'), 'rank-math_link' => $this->getNoticePluginUrl('rank-math'), ), ), ] ); } /** * Retrieves the admin URL for the settings page of a specific plugin based on the provided addon slug. * * @param string $addon_slug The identifier slug of the addon/plugin to retrieve the URL for. * @return string|null The admin URL for the plugin settings page, or null if the slug does not match a known plugin. */ public function getNoticePluginUrl(string $addon_slug): ?string { $url = ''; if($addon_slug === 'wp-rocket'){ $url = admin_url('options-general.php?page=wprocket'); } if($addon_slug === 'rank-math'){ $url = admin_url('admin.php?page=rank-math&view=modules'); } return $url; } /** * Generates and returns HTML for a success notice indicating that a plugin was activated. * * @param string $addon_slug The slug of the add-on/plugin that was activated. * @return string The HTML for the success notice, including a message, manage button, and close button. */ public function getActivatedNotice(string $addon_slug): string { $manageUrl = $this->getNoticePluginUrl($addon_slug); $pluginName = self::PLUGIN_SLUGS_NAME[$addon_slug] ?? ''; $page = isset($_POST['page']) ? sanitize_text_field($_POST['page']) : ''; $hiddenClass = ''; //Below is for onecom-marketplace-products page success banner if($page === 'onecom-marketplace-products'){ $title = __('{name} is active', 'onecom-wp'); $notice_title = str_replace('{name}', $pluginName, $title); $description = __('{name} was successfully activated on this installation.', 'onecom-wp'); $notice_description = str_replace('{name}', $pluginName, $description); $button_key = __('Go to {name}', 'onecom-wp'); $button_text = str_replace('{name}', $pluginName, $button_key); $button_event = 'ocwp_ocmp_go_to_' . str_replace('-', '_', $addon_slug). '_clicked_event'; $hiddenClass = 'class="gv-hidden"'; } else { $title = __('ui.notifications.pluginActivated', 'onecom-wp'); $notice_title = str_replace('{0}', $pluginName, $title); $description = __('ui.notifications.manageInMyProducts', 'onecom-wp'); $notice_description = str_replace('{0}', $pluginName, $description); $button_text = __('Get started', 'onecom-wp'); $button_event = 'ocwp_ocmp_get_started_' . str_replace('-', '_', $addon_slug). '_clicked_event'; } ob_start(); ?>
<?php echo __('Success', 'onecom-wp'); ?>

alt=""/>
<?php echo __('ui.labels.manage', 'onecom-wp'); ?>
activateWpPlugin($plugin_slug); } /** * Addon status check on the button click * @return void */ public function addonStatusCheck(): void { $plugin_slug = sanitize_text_field($_POST['plugin_slug']); $transient_key = "{$plugin_slug}_select_button_clicked_at"; set_site_transient($transient_key, current_time('timestamp'), self::EXPIRATION_TIME_IN_MINUTES * MINUTE_IN_SECONDS); $this->checkAddonPurchaseStatus($plugin_slug); } /** * Check addon status on page load * @return void */ public function addonStatusCheckOnLoad(): void { $plugin_slug = sanitize_text_field($_POST['plugin_slug']); $this->checkAddonPurchaseStatus($plugin_slug); } /** * Check if activate banner should be shown on products page reload * This checks if addon is purchased but activation is not in progress * @return void */ public function checkActivateBannerOnReload(): void { $plugin_slug = sanitize_text_field($_POST['plugin_slug']); //override for seo-by-rank-math-pro activation if needed if($plugin_slug === 'seo-by-rank-math-pro'){ $plugin_slug = 'rank-math'; } $option_name = 'plugin_deactivated_' . sanitize_key($plugin_slug); //Return if plugin already deactivated manually if(get_option($option_name)){ wp_send_json([ 'status' => 'plugin_deactivated_manually', 'addon_slug' => $plugin_slug, 'show_banner' => false ]); } $plugin_handle = self::PLUGIN_HANDLE[$plugin_slug] ?? ''; // Check if plugin is already active if ($plugin_handle && function_exists('is_plugin_active') && is_plugin_active($plugin_handle)) { wp_send_json([ 'status' => 'plugin_already_active', 'addon_slug' => $plugin_slug, 'show_banner' => false ]); } // Check if activation is in progress $activation_button_clicked = get_site_transient("{$plugin_slug}_activation_button_clicked_at"); $activation_start_at = get_site_transient("{$plugin_slug}_activation_start_at"); $pp_activation_start = get_site_transient("{$plugin_slug}-pp-activation-start-at"); $activation_in_progress = $activation_button_clicked || $activation_start_at || $pp_activation_start; if ($activation_in_progress) { error_log("[MP_ONECOM_PLUGIN] Activation in progress for {$plugin_slug}, not showing activate banner"); wp_send_json([ 'status' => 'activation_in_progress', 'addon_slug' => $plugin_slug, 'show_banner' => false ]); } // Get addon purchase status and createdAt $addonStatus = $this->isAddonPurchased($plugin_slug, true); // Check if addon is purchased if ($addonStatus['is_active']) { $createdAt = $addonStatus['addon_info']['data']['createdAt'] ?? null; if ($createdAt) { $createdAtTimestamp = strtotime($createdAt); $currentTimestamp = current_time('timestamp'); $daysSincePurchase = ($currentTimestamp - $createdAtTimestamp) / DAY_IN_SECONDS; // Only show banner if purchased within last 30 days if ($daysSincePurchase > 30) { error_log("[MP_ONECOM_PLUGIN] Addon purchased more than 30 days ago for {$plugin_slug}, not showing activate banner"); wp_send_json([ 'status' => 'purchase_too_old', 'addon_slug' => $plugin_slug, 'show_banner' => false, 'createdAt' => $createdAt ]); } //If createdAt is less than 1 month from today, show activate banner error_log("[MP_ONECOM_PLUGIN] Addon purchased but not activated for {$plugin_slug}, showing activate banner"); wp_send_json([ 'status' => 'show_activate_banner', 'addon_slug' => $plugin_slug, 'show_banner' => true, 'banner_html' => $this->getActivateBanner($plugin_slug), 'createdAt' => $createdAt ]); } } // Default case - don't show banner wp_send_json([ 'status' => 'addon_not_purchased', 'addon_slug' => $plugin_slug, 'show_banner' => false ]); } /** * Check plugin activation on reload * @return void */ public function onReloadPluginActivateCheck(): void { $plugin_slug = sanitize_text_field($_POST['plugin_slug']); //override for seo-by-rank-math-pro activation if needed if($plugin_slug === 'seo-by-rank-math-pro'){ $plugin_slug = 'rank-math'; } $this->activateWpPlugin($plugin_slug); } /** * Call WP API Provisioner for plugin install/activation (generic for any plugin slug) */ public function callWpApiProvisioner($plugin_slug): string { if (!$this->isAddonPurchased($plugin_slug)) { error_log('[MP_ONECOM_PLUGIN] addon_not_subscribed, skipping WP API Provisioner call from marketplace: ' . $plugin_slug); return 'addon_not_subscribed'; } error_log("[MP_ONECOM_PLUGIN] Request plugin activation from marketplace: $plugin_slug"); $pp_start_at = "$plugin_slug-pp-activation-start-at"; $start_time = get_site_transient($pp_start_at); if ($start_time) { error_log("[MP_ONECOM_PLUGIN] The provisioning request has already been sent; skipping the re-request: " . $plugin_slug); return 'already_in_queue'; } $subdomain = OCPushStats::get_subdomain(); $domain = OCPushStats::get_domain(); error_log("[MP_ONECOM_PLUGIN] Calling WP API Provisioner for plugin from marketplace ".MIDDLEWARE_URL.": $subdomain.$domain" . $plugin_slug); if (function_exists('is_cluster_domain') && is_cluster_domain()) { error_log("[MP_ONECOM_PLUGIN] Calling WP API Provisioner for cluster domain"); $url = MIDDLEWARE_URL . '/plugin-provisioner/cluster'; } else { error_log("[MP_ONECOM_PLUGIN] Calling WP API Provisioner for legacy domain"); $url = function_exists('onecom_query_check') ? onecom_query_check(MIDDLEWARE_URL . '/plugin-provisioner') : MIDDLEWARE_URL . '/plugin-provisioner'; } add_filter('http_request_args', 'oc_add_http_headers', 10, 2); wp_remote_post( $url, array( 'body' => json_encode(array( 'subdomain' => $subdomain, 'domain' => $domain, 'addon_slug' => $plugin_slug )) ) ); remove_filter('http_request_args', 'oc_add_http_headers'); set_site_transient($pp_start_at, current_time('timestamp'), self::EXPIRATION_TIME_IN_MINUTES * MINUTE_IN_SECONDS); return 'added_to_queue'; } /** * Validate addon purchase status * @param $addon_info * @param $addon_const * @return bool */ public function validateAddonPurchase($addon_info, $addon_const): bool { return is_array($addon_info) && array_key_exists('success', $addon_info) && $addon_info['success'] && array_key_exists('data', $addon_info) && array_key_exists('source', $addon_info['data']) && $addon_info['data']['source'] === 'PURCHASED' && array_key_exists('product', $addon_info['data']) && $addon_info['data']['product'] === $addon_const ; } /** * Check if addon is purchased for any plugin slug * @param string $plugin_slug * @return bool */ public function isAddonPurchased(string $plugin_slug, $getAddonInfo = false): bool | array { // Allow override via AJAX request $isMPCall = false; //Added handle for ajax call to check addon purchase status from marketplace service if(isset($_POST['addon_purchase_check']) && $_POST['addon_purchase_check'] === 'true' && isset($_POST['addon_slug'])){ $plugin_slug = sanitize_text_field($_POST['addon_slug']); //override for seo-by-rank-math-pro activation if needed if($plugin_slug === 'seo-by-rank-math-pro'){ $plugin_slug = 'rank-math'; } //Ensure plugin slug should be valid $isMPCall = true; } // Fetch info for the given plugin slug $addon_const = self::ADDONS_SLUGS[$plugin_slug] ?? ''; $addon_info = $this->getAddonInfo($plugin_slug, true); //Send ajax response if called from marketplace service if ($isMPCall) { wp_send_json([ 'is_purchased' => $this->validateAddonPurchase($addon_info, $addon_const), 'addon_slug' => $plugin_slug ]); } if($getAddonInfo){ return [ 'is_active' => $this->validateAddonPurchase($addon_info, $addon_const), 'addon_info' => $addon_info ]; } return $this->validateAddonPurchase($addon_info, $addon_const); } /** * Get addon info for a plugin slug (should be implemented to fetch actual info) * @param string $plugin_slug * @param bool $force * @param string $domain * @return array */ public function getAddonInfo(string $plugin_slug, $force = false, $domain = '' ) { $addon_slug = self::ADDONS_SLUGS[$plugin_slug] ?? ''; // check transient $addon_info_transient_key = "{$plugin_slug}_onecom_addon_info"; $addon_info = get_site_transient( $addon_info_transient_key); if ( ! empty( $addon_info ) && false === $force ) { return $addon_info; } if ( ! $domain ) { $domain = isset( $_SERVER['ONECOM_DOMAIN_NAME'] ) ? $_SERVER['ONECOM_DOMAIN_NAME'] : false; } if ( ! $domain ) { return array( 'data' => null, 'error' => 'Empty domain', 'success' => false, ); } return $this->callWPApiForAddon($addon_slug, $domain, $addon_info_transient_key); } /** * Call WP API for addon info * @param $addon_slug * @param $domain * @param $addon_info_transient_key * @return array|mixed */ public function callWPApiForAddon($addon_slug, $domain, $addon_info_transient_key): mixed { $totp = oc_generate_totp(); // headers and api url based on cluster domain or not if ( is_cluster_domain() ) { //create a header for a cluster model $curl_url = MIDDLEWARE_URL . "/features/addon/$addon_slug/status/cluster"; $http_header = array( 'Cache-Control: no-cache', 'X-Onecom-Client-Domain: ' . $domain, 'X-TOTP: ' . $totp, 'cache-control: no-cache', ); $http_header[] = 'X-ONECOM-CLUSTER-ID: ' . OC_CLUSTER_ID; $http_header[] = 'X-ONECOM-WEBCONFIG-NAME: ' . $_SERVER['HTTP_X_GROUPONE_WEBCONFIG_NAME']; } else { //prepare headers for a domain model $curl_url = MIDDLEWARE_URL . "/features/addon/$addon_slug/status"; $http_header = array( 'Cache-Control: no-cache', 'X-Onecom-Client-Domain: ' . $domain, //need to use from wp-config if available otherwise use domain parse 'X-TOTP: ' . $totp, 'cache-control: no-cache', ); } $curl = curl_init(); curl_setopt_array( $curl, array( CURLOPT_URL => $curl_url, CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => $http_header ) ); $response = curl_exec( $curl ); $response = json_decode( $response, true ); $err = curl_error( $curl ); curl_close( $curl ); if ( $err ) { return array( 'data' => null, 'error' => __( 'Some error occurred, please reload the page and try again.', 'validator' ), 'success' => false, ); } else { // save transient for next calls, & return latest response set_site_transient( $addon_info_transient_key, $response, 12 * HOUR_IN_SECONDS ); return $response; } } /** * Activate plugin via WP API Provisioner * @param $plugin_slug * @return void */ public function activateWpPlugin($plugin_slug): void { $start_time_key = "{$plugin_slug}_activation_start_at"; $btn_transient_key = "{$plugin_slug}_activation_button_clicked_at"; $timeout_limit = self::EXPIRATION_TIME_IN_MINUTES * MINUTE_IN_SECONDS; $current_time = current_time('timestamp'); $plugin_handle = self::PLUGIN_HANDLE[$plugin_slug] ?? ''; $install_stats_key = "mp_{$plugin_slug}_install_logged"; //Check if the activation button was clicked if (!get_site_transient($btn_transient_key)) { error_log('[MP_ONECOM_PLUGIN] Activation button not clicked, normal reload for plugin: ' . $plugin_slug); wp_send_json(['status' => 'normal_reload', 'addon_slug' => $plugin_slug]); } $send_success = function() use ($install_stats_key, $plugin_slug) { error_log("[MP_ONECOM_PLUGIN] Plugin activated successfully from Marketplace: {$plugin_slug}"); delete_site_transient( $install_stats_key ); //Success activation stats log ( class_exists( OCPUSHSTATS ) ? \OCPushStats::push_stats_event_themes_and_plugins('activate', self::ITEM_CATEGORY[$plugin_slug], self::PLUGIN_SLUGS[$plugin_slug], 'onecom-marketplace') : '' ); $this->clearActivationQueue($plugin_slug); wp_send_json([ 'status' => 'activated', 'url' => admin_url('plugins.php'), 'btn_text' => __('Go to plugin', 'onecom-wp'), 'addon_slug' => $plugin_slug, 'notice_html' => $this->getActivatedNotice($plugin_slug) ]); }; //Add only single install stats log if ( $this->isPluginInstalled($plugin_slug) && false === get_site_transient($install_stats_key) && set_site_transient($install_stats_key, 1, 5 * MINUTE_IN_SECONDS) ){ ( class_exists( OCPUSHSTATS ) ? \OCPushStats::push_stats_event_themes_and_plugins('install', self::ITEM_CATEGORY[$plugin_slug], self::PLUGIN_SLUGS[$plugin_slug], 'onecom-marketplace') : '' ); error_log("[MP_ONECOM_PLUGIN] Install stats logged for: {$plugin_slug}"); } //More shield check before activation if ( $plugin_handle && function_exists( 'is_plugin_active' ) && is_plugin_active( $plugin_handle ) ) { $send_success(); } $start_time = get_site_transient($start_time_key); if (!$start_time) { error_log('[MP_ONECOM_PLUGIN] Starting plugin activation process from marketplace: ' . $plugin_slug); set_site_transient($start_time_key, $current_time, $timeout_limit); if ($this->isPluginInstalled($plugin_slug)) { error_log('[MP_ONECOM_PLUGIN] Plugin was installed activating only from wp-admin'.$plugin_handle .', Slug:'. $plugin_slug); $result = activate_plugin($plugin_handle); if (is_wp_error($result)) { error_log("[MP_ONECOM_PLUGIN] Plugin activation failed from Marketplace: {$plugin_slug}"); $this->clearActivationQueue($plugin_slug); //Delete install stats transient to allow re-log on next attempt delete_site_transient( $install_stats_key ); wp_send_json_error([ 'status' => 'activation_failed', 'message' => $result->get_error_message(), 'addon_slug' => $plugin_slug, 'try_again_banner' => $this->getTryAgainBanner($plugin_slug) ]); } $send_success(); } //First call to WP API Provisioner for installation/activation if (!is_plugin_active($plugin_handle)) { $status = $this->callWpApiProvisioner($plugin_slug); error_log('[MP_ONECOM_PLUGIN] Provisioner status: ' . $status); wp_send_json(['status' => $status, 'addon_slug' => $plugin_slug]); } } //Check status every interval if (($current_time - (int)$start_time) >= $timeout_limit) { if (is_plugin_active($plugin_handle)) { $send_success(); } error_log("[MP_ONECOM_PLUGIN] Plugin not activated and timed out from marketplace: {$plugin_slug}"); $this->clearActivationQueue($plugin_slug); //Delete install stats transient to allow re-log on next attempt delete_site_transient( $install_stats_key ); wp_send_json(['status' => 'expired_queue', 'addon_slug' => $plugin_slug, 'try_again_banner' => $this->getTryAgainBanner($plugin_slug)]); } error_log("[MP_ONECOM_PLUGIN] Plugin activation in progress: {$plugin_slug}"); wp_send_json(['status' => 'already_in_queue', 'addon_slug' => $plugin_slug]); } /** * Check addon purchase status * @param $plugin_slug * @return void */ public function checkAddonPurchaseStatus($plugin_slug): void { $start_time_key = "{$plugin_slug}_purchase_button_start_at"; $btn_transient_key = "{$plugin_slug}_select_button_clicked_at"; $timeout_limit = self::EXPIRATION_TIME_IN_MINUTES * MINUTE_IN_SECONDS; $current_time = current_time('timestamp'); $plugin_handle = self::PLUGIN_HANDLE[$plugin_slug] ?? ''; if (!get_site_transient($btn_transient_key)) { wp_send_json(['status' => 'normal_reload', 'addon_slug' => $plugin_slug]); } $send_success = function() use ($plugin_slug) { error_log("[MP_ONECOM_PLUGIN] Addon purchased from Marketplace: {$plugin_slug}"); //Success activation stats log ( class_exists( OCPUSHSTATS ) ? \OCPushStats::push_stats_event_themes_and_plugins('addon_purchased', self::ITEM_CATEGORY[$plugin_slug], self::PLUGIN_SLUGS[$plugin_slug], 'onecom-marketplace') : '' ); $this->clearAddonStatusQueue($plugin_slug); $this->setTransientForAddonActivation($plugin_slug); wp_send_json(['status' => 'addon_purchased', 'addon_slug' => $plugin_slug]); }; //Check if the plugin is already active, a rare case but possible if (is_plugin_active($plugin_handle)) { error_log("[MP_ONECOM_PLUGIN] Plugin active during addon status check: {$plugin_slug}, skipping purchase check"); $send_success(); } $start_time = get_site_transient($start_time_key); // Case 1: First time select click attempt for purchase if (!$start_time) { set_site_transient($start_time_key, $current_time, $timeout_limit); wp_send_json(['status' => 'added_in_queue', 'addon_slug' => $plugin_slug]); } //get addon purchase status, force refresh feature endpoint //call feature endpoint to get latest addon status $addon_info = $this->getAddonInfo($plugin_slug,true); $addon_const = self::ADDONS_SLUGS[$plugin_slug] ?? ''; $addon_purchased = $this->validateAddonPurchase($addon_info, $addon_const); if ($addon_purchased) { $send_success(); } $elapsed_time = $current_time - (int)$start_time; $time_left = $timeout_limit - $elapsed_time; // Case 2: Stop polling early if less than 30 seconds left if ($time_left <= 30) { if ($addon_purchased) { $send_success(); } error_log("[MP_ONECOM_PLUGIN] Polling stopped early (time left: {$time_left}s) for {$plugin_slug}"); $this->clearAddonStatusQueue($plugin_slug); wp_send_json(['status' => 'expired_queue', 'addon_slug' => $plugin_slug]); } // Case 3: Queue expired after timeout if ($elapsed_time >= $timeout_limit) { if ($addon_purchased) { $send_success(); } error_log("[MP_ONECOM_PLUGIN] Addon not purchased and timed out: {$plugin_slug}"); $this->clearAddonStatusQueue($plugin_slug); wp_send_json(['status' => 'expired_queue', 'addon_slug' => $plugin_slug]); } // Case 4: Queue still in progress error_log("[MP_ONECOM_PLUGIN] Addon purchase in progress: {$plugin_slug}"); wp_send_json(['status' => 'already_in_queue', 'addon_slug' => $plugin_slug]); } /** * Set transient for addon activation * @param $plugin_slug * @return void */ public function setTransientForAddonActivation($plugin_slug): void { $activation_button_clicked_at = "{$plugin_slug}_activation_button_clicked_at"; $pp_activation_start_at = "{$plugin_slug}-pp-activation-start-at"; $activation_start_at = "{$plugin_slug}_activation_start_at"; $timeout_limit = self::EXPIRATION_TIME_IN_MINUTES * MINUTE_IN_SECONDS; $current_time = current_time('timestamp'); set_site_transient($activation_start_at, $current_time, $timeout_limit); set_site_transient($activation_button_clicked_at, $current_time, $timeout_limit); set_site_transient($pp_activation_start_at, $current_time, $timeout_limit); } /** * Clears the activation queue for a specified plugin. * * @param string $plugin_slug The slug of the plugin for which the activation queue should be cleared. * @return void */ public function clearActivationQueue(string $plugin_slug): void { delete_site_transient("{$plugin_slug}_activation_start_at"); delete_site_transient("{$plugin_slug}_activation_button_clicked_at"); delete_site_transient("{$plugin_slug}-pp-activation-start-at"); if (function_exists('wp_cache_flush')) { wp_cache_flush(); } } /** * Clears the addon status queue by removing associated transients for a given plugin and flushing cache if available. * * @param string $plugin_slug The slug of the plugin whose addon status queue should be cleared. * @return void */ public function clearAddonStatusQueue(string $plugin_slug): void { delete_site_transient("{$plugin_slug}_purchase_button_start_at"); delete_site_transient("{$plugin_slug}_select_button_clicked_at"); if (function_exists('wp_cache_flush')) { wp_cache_flush(); } } public function getTryAgainBanner($plugin_slug): string { $notice_title = __('ui.notifications.activationFailedTitle','onecom-wp'); $notice_title = str_replace('{plugin name}', self::PLUGIN_SLUGS_NAME[$plugin_slug] ?? '', $notice_title); $support_link = $this->get_contact_support_link(); $notice_desc = __('ui.notifications.activationFailedText', 'onecom-wp'); $notice_desc = str_replace('{plugin name}', self::PLUGIN_SLUGS_NAME[$plugin_slug] ?? '', $notice_desc); $message = sprintf($notice_desc, '', '' ); ob_start(); ?>

contact_support_links ) ) { $locale = 'en'; } return $this->contact_support_links[ $locale ]; } public function getActivateBanner($addon_slug): string{ $domain = OCPushStats::get_domain() ?? 'localhost'; $domainBold = "$domain"; $title = str_replace('{name}', self::PLUGIN_SLUGS_NAME[$addon_slug], __('Activate {name}', 'onecom-wp')); if($addon_slug == 'wp-rocket') { $desc = str_replace( ['{name}', '{domain.one}'], [self::PLUGIN_SLUGS_NAME[$addon_slug], $domainBold], __("You have a {name} subscription for {domain.one}, but you still need to activate it for the installation on {domain.one}. Activate the plugin to boost your site's performance.", 'onecom-wp') ); } if($addon_slug == 'rank-math') { $desc = str_replace( ['{name}', '{domain}'], [self::PLUGIN_SLUGS_NAME[$addon_slug], $domainBold], __("You have a {name} subscription for {domain}, but you still need to activate it for the installation on {domain}. Activate the plugin to start improving your site's SEO.", 'onecom-wp') ); } // Set button classes based on addon slug $button_class = 'oc-activate-' . $addon_slug . '-btn'; $event_class = 'ocwp_ocmp_activate_' . str_replace('-', '_', $addon_slug) . '_clicked_event'; ob_start(); ?>

$plugin_file) { if ($plugin !== $plugin_file) { continue; } $option_name = 'plugin_deactivated_' . sanitize_key($handle); update_option($option_name, [ 'time' => time(), 'network' => (bool) $network_deactivating, ]); break; } } }