current_product(); } public static function enqueue($hook_suffix) { if (!self::is_our_screen() || !current_user_can(self::cap())) { return; } $css = AIEO_DIR . 'assets/css/aieo-feedback.css'; $js = AIEO_DIR . 'assets/js/aieo-forms.js'; wp_enqueue_style('aieo-feedback', AIEO_URI . 'assets/css/aieo-feedback.css', array(), file_exists($css) ? (string) filemtime($css) : AIEO_VERSION); wp_enqueue_script('aieo-forms', AIEO_URI . 'assets/js/aieo-forms.js', array(), file_exists($js) ? (string) filemtime($js) : AIEO_VERSION, true); wp_localize_script('aieo-forms', 'aieoForms', array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'submit' => self::AJAX_SUBMIT, 'dismiss' => self::AJAX_DISMISS, 'html' => self::AJAX_HTML, 'nonce' => wp_create_nonce(self::AJAX_SUBMIT), 'i18n' => array( 'failed' => __('Could not send. Please try again.', 'ai-eshop-optimizer'), ), )); if (class_exists('AIEO_Wizard')) { AIEO_Wizard::enqueue_styles(); AIEO_Wizard::enqueue_modal_script(); } } public static function render() { if (!self::is_our_screen()) { return; } $form = self::current_form(); if (!$form) { return; } $defs = self::definitions(); $user_id = get_current_user_id(); $meta_key = self::META_OFFERED . $form['code']; $preview = !empty($form['preview']); $autoopen = false; $folded = !empty($form['collapse_questions']); $on_demand = !empty($form['on_demand']); $blocked = $on_demand && !empty($form['blocked']) ? $form['blocked'] : ''; if ($on_demand) { $autoopen = true; } elseif (!$preview && !get_user_meta($user_id, $meta_key, true)) { $autoopen = true; update_user_meta($user_id, $meta_key, time()); } $show_questions = ('' === $blocked); ?>
hidden>
array(), 'forms' => array()); } if (function_exists('is_textdomain_loaded') && is_textdomain_loaded('ai-eshop-optimizer')) { set_transient($key, $defs, self::CACHE_TTL); } $memo[$locale] = $defs; return $defs; } private static function answered() { $a = get_option(self::OPT_ANSWERED, array()); return is_array($a) ? $a : array(); } private static function audience_ok($form, $user_id = 0) { $rules = isset($form['audience']) && is_array($form['audience']) ? $form['audience'] : array(); $user_id = $user_id ? (int) $user_id : get_current_user_id(); foreach ($rules as $rule => $value) { switch ($rule) { case 'min_days': $first = (int) get_option('aieo_first_activated_at', 0); if (!$first || (time() - $first) < ((int) $value) * DAY_IN_SECONDS) { return false; } break; case 'not_answered': if (get_user_meta($user_id, self::META_ANSWERED . $value, true)) { return false; } break; case 'not_used_page': if (self::has_used_page((string) $value)) { return false; } break; default: return false; } } return true; } private static function has_used_page($page) { $counts = get_option('aieo_action_telemetry_counts'); if (!is_array($counts) || '' === $page) { return false; } foreach ($counts as $id => $row) { if (0 === strpos((string) $id, $page . '.')) { return true; } } return false; } public static function preview_code() { if (!current_user_can(self::cap())) { return ''; } return isset($_GET['aieo_form_preview']) ? sanitize_key(wp_unslash($_GET['aieo_form_preview'])) : ''; } public static function reopenable() { return array('welcome', 'checkin'); } public static function open_code() { if (!current_user_can(self::cap())) { return ''; } $code = isset($_GET['aieo_form_open']) ? sanitize_key(wp_unslash($_GET['aieo_form_open'])) : ''; return in_array($code, self::reopenable(), true) ? $code : ''; } private static function blocked_reason($form, $user_id) { if (get_user_meta($user_id, self::META_ANSWERED . $form['code'], true)) { return 'answered'; } $min = isset($form['audience']['min_days']) ? (int) $form['audience']['min_days'] : 0; if ($min > 0) { $first = (int) get_option('aieo_first_activated_at', 0); $days = $first ? (int) floor((time() - $first) / DAY_IN_SECONDS) : 0; if ($days < $min) { return 'early'; } } return ''; } private static function days_installed() { $first = (int) get_option('aieo_first_activated_at', 0); return $first ? max(0, (int) floor((time() - $first) / DAY_IN_SECONDS)) : 0; } public static function current_form($user_id = 0) { $user_id = $user_id ? (int) $user_id : get_current_user_id(); if (!$user_id || !current_user_can(self::cap())) { return null; } $defs = self::definitions(); $preview = self::preview_code(); if ('' !== $preview && isset($defs['forms'][$preview])) { $form = $defs['forms'][$preview]; $form['code'] = $preview; $form['version'] = isset($form['version']) ? (string) $form['version'] : '1'; $form['preview'] = true; return $form; } $open = self::open_code(); if ('' !== $open && isset($defs['forms'][$open])) { $form = $defs['forms'][$open]; $form['code'] = $open; $form['version'] = isset($form['version']) ? (string) $form['version'] : '1'; $form['on_demand'] = true; $form['blocked'] = self::blocked_reason($form, $user_id); return $form; } $answered = self::answered(); $active = get_option(self::OPT_ACTIVE, null); foreach ($defs['forms'] as $code => $form) { $version = isset($form['version']) ? (string) $form['version'] : '1'; if (is_array($active) && !in_array($code, $active, true)) { continue; } if (get_user_meta($user_id, self::META_ANSWERED . $code, true)) { continue; } if (get_user_meta($user_id, self::META_DISMISSED . $code, true)) { continue; } if (!self::audience_ok($form, $user_id)) { continue; } $form['code'] = $code; $form['version'] = $version; return $form; } return null; } private static function collect($form, $posted) { $defs = self::definitions(); $out = array(); foreach ((array) $form['questions'] as $qcode) { if (!isset($defs['questions'][$qcode])) { $out[] = array('q' => $qcode, 'd' => 'not_shown'); continue; } $q = $defs['questions'][$qcode]; $type = isset($q['type']) ? $q['type'] : 'single'; $given = isset($posted[$qcode]) ? $posted[$qcode] : null; $entry = array('q' => $qcode, 'd' => 'answered'); if ('multi' === $type) { $codes = array_values(array_filter(array_map('sanitize_key', (array) $given))); $codes = array_values(array_intersect($codes, array_keys((array) $q['choices']))); if (empty($codes)) { $entry['d'] = 'skipped'; } else { $entry['c'] = $codes; } } elseif ('single' === $type) { $code = sanitize_key((string) $given); if ('' === $code || !isset($q['choices'][$code])) { $entry['d'] = 'skipped'; } else { $entry['c'] = array($code); } } elseif ('rating' === $type) { $n = (int) $given; if ($n < 1 || $n > 5) { $entry['d'] = 'skipped'; } else { $entry['n'] = $n; } } else { $txt = trim((string) $given); if ('' === $txt) { $entry['d'] = 'skipped'; } else { $max = isset($q['max_len']) ? (int) $q['max_len'] : 1000; $entry['t'] = mb_substr(wp_check_invalid_utf8($txt), 0, $max); } } if (!empty($q['other_choice']) && isset($entry['c']) && in_array($q['other_choice'], $entry['c'], true)) { $other = isset($posted[$qcode . '__other']) ? trim((string) $posted[$qcode . '__other']) : ''; if ('' !== $other) { $max = isset($q['max_len']) ? (int) $q['max_len'] : 200; $entry['t'] = mb_substr(wp_check_invalid_utf8($other), 0, $max); $entry['tc'] = (string) $q['other_choice']; } } $out[] = $entry; } return $out; } private static function manifest($form) { $defs = self::definitions(); $qs = array(); foreach ((array) $form['questions'] as $qcode) { if (!isset($defs['questions'][$qcode])) { continue; } $q = $defs['questions'][$qcode]; $qs[] = array( 'code' => $qcode, 'label' => isset($q['label']) ? (string) $q['label'] : $qcode, 'choices' => isset($q['choices']) ? array_map('strval', (array) $q['choices']) : array(), ); } return array('questions' => $qs); } public static function ajax_submit() { check_ajax_referer(self::AJAX_SUBMIT, 'nonce'); if (!current_user_can(self::cap())) { wp_send_json_error(array('message' => __('Unauthorized', 'ai-eshop-optimizer')), 403); } $code = isset($_POST['form_code']) ? sanitize_key(wp_unslash($_POST['form_code'])) : ''; $defs = self::definitions(); if ('' === $code || !isset($defs['forms'][$code])) { wp_send_json_error(array('message' => __('Unknown form.', 'ai-eshop-optimizer'))); } $form = $defs['forms'][$code]; $form['code'] = $code; $form['version'] = isset($form['version']) ? (string) $form['version'] : '1'; $posted = isset($_POST['answers']) && is_array($_POST['answers']) ? wp_unslash($_POST['answers']) : array(); $answers = self::collect($form, $posted); $has_answer = false; foreach ($answers as $entry) { if (isset($entry['d']) && 'answered' === $entry['d']) { $has_answer = true; break; } } if (!$has_answer) { update_user_meta(get_current_user_id(), self::META_DISMISSED . $form['code'], 1); wp_send_json_success(array('dismissed' => true)); } if (class_exists('AIEO_Personas')) { foreach ($answers as $entry) { if ('role' === ($entry['q'] ?? '') && 'answered' === ($entry['d'] ?? '') && !empty($entry['c'][0])) { AIEO_Personas::record_survey_role(get_current_user_id(), (string) $entry['c'][0]); } } } $anon = !empty($_POST['anonymous']); $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : ''; if ($anon || !is_email($email)) { $email = ''; } if (class_exists('AIEO_Portal_Client')) { AIEO_Portal_Client::submit('form', array( 'form_code' => $form['code'], 'form_version' => $form['version'], 'answers' => $answers, 'manifest' => self::manifest($form), 'contact_email' => $email, 'respondent' => substr(hash_hmac('sha256', (string) get_current_user_id(), wp_salt('auth')), 0, 16), 'plugin_version' => defined('AIEO_VERSION') ? AIEO_VERSION : '', 'locale' => get_user_locale(), 'environment_type' => wp_get_environment_type(), 'screen' => 'form:' . $form['code'], 'profile' => class_exists('AIEO_Wizard') ? AIEO_Wizard::profile(get_current_user_id()) : null, )); } update_user_meta(get_current_user_id(), self::META_ANSWERED . $form['code'], time()); $answered = self::answered(); $answered[] = $form['code'] . ':' . $form['version']; update_option(self::OPT_ANSWERED, array_values(array_unique($answered)), false); wp_send_json_success(array('message' => __('Thank you', 'ai-eshop-optimizer'))); } public static function ajax_html() { check_ajax_referer(self::AJAX_SUBMIT, 'nonce'); if (!current_user_can(self::cap())) { wp_send_json_error(null, 403); } $code = isset($_GET['form_code']) ? sanitize_key(wp_unslash($_GET['form_code'])) : ''; if (!in_array($code, self::reopenable(), true)) { wp_send_json_error(null, 400); } $_GET['aieo_form_open'] = $code; ob_start(); self::render(); $html = ob_get_clean(); if ('' === trim((string) $html)) { wp_send_json_error(null, 404); } wp_send_json_success(array('html' => $html)); } public static function ajax_dismiss() { check_ajax_referer(self::AJAX_SUBMIT, 'nonce'); if (!current_user_can(self::cap())) { wp_send_json_error(null, 403); } $code = isset($_POST['form_code']) ? sanitize_key(wp_unslash($_POST['form_code'])) : ''; if ($code) { update_user_meta(get_current_user_id(), self::META_DISMISSED . $code, 1); } wp_send_json_success(); } } }