register_rewrite(); flush_rewrite_rules(false); update_option(self::REWRITE_VERSION_OPTION, self::REWRITE_VERSION, true); } public function register_rewrite(): void { add_rewrite_rule( '^al/r/([^/]+)/?$', 'index.php?' . self::QUERY_VAR . '=$matches[1]', 'top' ); $stored = (string) get_option(self::REWRITE_VERSION_OPTION, ''); if ($stored !== self::REWRITE_VERSION) { flush_rewrite_rules(false); update_option(self::REWRITE_VERSION_OPTION, self::REWRITE_VERSION, true); } } /** * @param array $vars * @return array */ public function add_query_vars(array $vars): array { $vars[] = self::QUERY_VAR; return $vars; } public function maybe_start_session(): void { if (is_admin() || !function_exists('WC')) { return; } if (WC()->session && !WC()->session->has_session()) { WC()->session->set_customer_session_cookie(true); } } public static function get_state(): array { $defaults = [ 'session_id' => '', 'distributor_id' => '', 'event_id' => '', 'event_title' => '', ]; if (!function_exists('WC') || !WC()->session) { return $defaults; } $state = WC()->session->get(self::SESSION_KEY, []); if (!is_array($state)) { $state = []; } return array_merge($defaults, $state); } public static function set_state(array $patch): array { $state = self::get_state(); foreach (['session_id', 'distributor_id', 'event_id', 'event_title'] as $key) { if (array_key_exists($key, $patch)) { $state[$key] = sanitize_text_field((string) $patch[$key]); } } if ($state['session_id'] === '') { $state['session_id'] = self::new_session_id(); } if (function_exists('WC') && WC()->session) { WC()->session->set(self::SESSION_KEY, $state); } if (!headers_sent() && $state['session_id']) { setcookie( self::COOKIE_NAME, $state['session_id'], time() + 60 * 60 * 24 * 30, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, is_ssl(), true ); } return $state; } private static function new_session_id(): string { try { return wp_generate_uuid4(); } catch (\Throwable $e) { return bin2hex(random_bytes(16)); } } /** * `/al/r/{siteId}` → session + redirect home (preserve `_e` when present). */ public function maybe_handle_pretty_slug(): void { if (is_admin()) { return; } try { $affiliate = get_query_var(self::QUERY_VAR); if (!is_string($affiliate) || $affiliate === '') { return; } $affiliate = sanitize_text_field(rawurldecode($affiliate)); if ($affiliate === '') { wp_safe_redirect(home_url('/')); exit; } // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Public affiliate link tracking param from an inbound visitor URL; no form or nonce exists. Value is sanitized. $event = isset($_GET['_e']) ? sanitize_text_field(wp_unslash((string) $_GET['_e'])) : ''; // phpcs:enable WordPress.Security.NonceVerification.Recommended $patch = ['distributor_id' => $affiliate]; if ($event !== '') { $patch['event_id'] = $event; } self::set_state($patch); $target = home_url('/'); if ($event !== '') { $target = add_query_arg('_e', $event, $target); } wp_safe_redirect($target); exit; } catch (\Throwable $e) { // Fail open: never take down the storefront. return; } } public function capture_from_request(): void { if (is_admin()) { return; } try { // Pretty slug handler already redirected; skip if somehow still here. if (get_query_var(self::QUERY_VAR)) { return; } $affiliate = self::read_affiliate_from_request(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public affiliate link tracking param from an inbound visitor URL; no form or nonce exists. Value is sanitized. $event = isset($_GET['_e']) ? sanitize_text_field(wp_unslash((string) $_GET['_e'])) : ''; $state = self::get_state(); if ($state['session_id'] === '' && !empty($_COOKIE[self::COOKIE_NAME])) { $state['session_id'] = sanitize_text_field(wp_unslash((string) $_COOKIE[self::COOKIE_NAME])); } $changed = false; if ($affiliate !== '') { $state['distributor_id'] = $affiliate; $changed = true; } if ($event !== '') { $state['event_id'] = $event; $changed = true; } if ($changed || $state['session_id'] === '') { self::set_state($state); } } catch (\Throwable $e) { return; } } private static function read_affiliate_from_request(): string { $keys = ['_f', 'idnumber', 'idno', 'repid', 'rep']; // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Public affiliate link tracking params (?_f= and legacy rep ids) from inbound visitor URLs; no form or nonce exists. Values are sanitized. foreach ($keys as $key) { if (!empty($_GET[$key])) { return sanitize_text_field(wp_unslash((string) $_GET[$key])); } } // phpcs:enable WordPress.Security.NonceVerification.Recommended // Hash form: /#siteId (JS also handles; PHP only sees fragment if posted) return ''; } }