false), 403); } $mode = isset($_POST['mode']) ? sanitize_key(wp_unslash($_POST['mode'])) : ''; if ('grant' === $mode) { if (!class_exists('AIEO_DMM_Module_Base') || !AIEO_DMM_Module_Base::is_aieo_pro_user()) { wp_send_json_error(array('pro' => false), 403); } self::grant_consent(); wp_send_json_success(array('collecting' => self::is_collecting())); } if ('revoke' === $mode) { self::revoke_consent(); wp_send_json_success(array('collecting' => false)); } wp_send_json_error(array('mode' => false), 400); } public static function ajax_help() { check_ajax_referer('aieo_action_help', 'nonce'); if (!current_user_can('manage_woocommerce') && !current_user_can('manage_options')) { wp_send_json_error(array('cap' => false), 403); } $id = isset($_GET['id']) ? sanitize_text_field(wp_unslash($_GET['id'])) : ''; $tab = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : ''; if ($id === '') { wp_send_json_error(array('id' => false), 400); } $row = class_exists('AIEO_Capability_Registry') ? AIEO_Capability_Registry::action($id) : null; $doc = class_exists('AIEO_Docs_Registry') ? AIEO_Docs_Registry::for_action($id, $tab, self::doc_lang()) : null; wp_send_json_success(array( 'id' => $id, 'label' => $row && !empty($row['label']) ? (string) $row['label'] : '', 'description' => $row && !empty($row['description']) ? (string) $row['description'] : '', 'informs_customer' => $row ? !empty($row['informs_customer']) : false, 'confirm' => $row && !empty($row['confirm']) ? (string) $row['confirm'] : '', 'url' => $doc && !empty($doc['url']) ? (string) $doc['url'] : '', 'matched' => $doc && !empty($doc['matched']) ? (string) $doc['matched'] : '', )); } private static function doc_lang() { $locale = function_exists('get_user_locale') ? get_user_locale() : get_locale(); $lang = strtolower(substr((string) $locale, 0, 2)); return $lang !== '' ? $lang : 'en'; } public static function is_collecting() { if (!class_exists('AIEO_DMM_Module_Base') || !AIEO_DMM_Module_Base::is_aieo_pro_user()) { return false; } $consent = get_option(self::OPT_CONSENT); if (!is_array($consent) || empty($consent['at'])) { return false; } return (bool) apply_filters('aieo_collect_action_usage', true); } public static function grant_consent($user_id = 0) { $user_id = $user_id ? (int) $user_id : get_current_user_id(); update_option(self::OPT_CONSENT, array( 'user' => $user_id, 'at' => gmdate('Y-m-d H:i:s') . ' UTC', 'version' => defined('AIEO_VERSION') ? AIEO_VERSION : '', ), false); } public static function revoke_consent() { delete_option(self::OPT_CONSENT); delete_option(self::OPT_COUNTS); } public static function script_config($page_id = '') { $on = self::is_collecting(); return array( 'page' => (string) $page_id, 'collect' => $on, 'endpoint' => $on ? admin_url('admin-ajax.php') : '', 'nonce' => $on ? wp_create_nonce('aieo_action_telemetry') : '', 'debug' => (defined('WP_DEBUG') && WP_DEBUG), 'help' => admin_url('admin-ajax.php'), 'helpNonce' => wp_create_nonce('aieo_action_help'), 'i18n' => array( 'help' => __('What does this do?', 'ai-eshop-optimizer'), 'emails' => __('This emails the customer.', 'ai-eshop-optimizer'), 'asks' => __('Asks first:', 'ai-eshop-optimizer'), 'manual' => __('Read the manual', 'ai-eshop-optimizer'), 'nothing' => __('This control is not documented yet.', 'ai-eshop-optimizer'), ), ); } public static function ajax_collect() { if (!self::is_collecting()) { wp_send_json_error(array('gated' => true), 403); } check_ajax_referer('aieo_action_telemetry', 'nonce'); if (!current_user_can('manage_woocommerce') && !current_user_can('manage_options')) { wp_send_json_error(array('cap' => false), 403); } $raw = isset($_POST['events']) ? wp_unslash($_POST['events']) : ''; $events = json_decode((string) $raw, true); if (!is_array($events)) { wp_send_json_error(array('parse' => false), 400); } $counts = get_option(self::OPT_COUNTS); if (!is_array($counts)) { $counts = array(); } $today = gmdate('Y-m-d'); $n = 0; foreach ($events as $ev) { if (!is_array($ev) || empty($ev['id'])) { continue; } $id = sanitize_text_field((string) $ev['id']); if ($id === '' || strlen($id) > 96) { continue; } if (!empty($ev['variant'])) { $v = sanitize_key((string) $ev['variant']); if ($v !== '') { $id .= ':' . $v; } } if (!isset($counts[$id]) && count($counts) >= self::MAX_IDS) { continue; } if (!isset($counts[$id])) { $counts[$id] = array('n' => 0, 'last' => ''); } $counts[$id]['n']++; $counts[$id]['last'] = $today; $n++; if ($n >= 200) { break; } } update_option(self::OPT_COUNTS, $counts, false); wp_send_json_success(array('recorded' => $n)); } public static function usage_report() { $counts = get_option(self::OPT_COUNTS); if (!is_array($counts)) { $counts = array(); } $all = array(); $rows = array(); if (class_exists('AIEO_Capability_Registry') && is_callable(array('AIEO_Capability_Registry', 'actions_index'))) { $rows = AIEO_Capability_Registry::actions_index(); } else { $root = defined('AIEO_PLUGIN_DIR') ? AIEO_PLUGIN_DIR : dirname(dirname(__DIR__)) . '/'; foreach (array('includes/dmm/data/actions-index.json', 'docs/actions-index.json') as $rel) { $path = rtrim((string) $root, '/\\') . '/' . $rel; if (!is_readable($path)) { continue; } $raw = json_decode((string) file_get_contents($path), true); if (isset($raw['actions']) && is_array($raw['actions'])) { $rows = $raw['actions']; break; } } } foreach ((array) $rows as $row) { if (!empty($row['id'])) { $all[(string) $row['id']] = $row; } } $used = $never = array(); foreach ($all as $id => $row) { $hits = 0; foreach ($counts as $key => $c) { if ($key === $id || strpos($key, $id . ':') === 0) { $hits += (int) $c['n']; } } if ($hits > 0) { $used[$id] = $hits; } else { $never[] = $id; } } arsort($used); return array('used' => $used, 'never' => $never, 'total' => count($all)); } }