$v === null || $v === '' ? $def : (bool) $v; $text = static fn($v, string $def): string => $v === null ? $def : (is_scalar($v) ? (string) $v : $def); $fields = Fields::normalize($settings['fields'] ?? []); $steps = Fields::steps($fields); $total = count($steps); $multi = $total > 1; $show_labels = $bool($settings['show_labels'] ?? null, true); $inline = $show_labels && ($settings['label_position'] ?? 'top') === 'inline'; $mark = $bool($settings['mark_required'] ?? null, true); $show_progress = $multi && $bool($settings['show_progress'] ?? null, true); $show_titles = $multi && $bool($settings['show_step_titles'] ?? null, true); $honeypot = $bool($settings['honeypot'] ?? null, true); $recaptcha = in_array($settings['recaptcha'] ?? 'off', ['v2', 'v3'], true) ? (string) $settings['recaptcha'] : 'off'; $site_key = ''; if ($recaptcha !== 'off' && function_exists('get_option')) { $opts = get_option('zadex_settings', []); $site_key = is_array($opts) && isset($opts['recaptcha_site_key']) && is_string($opts['recaptcha_site_key']) ? trim($opts['recaptcha_site_key']) : ''; } $step_text = $text($settings['step_text'] ?? null, 'Step {current} of {total}'); $button_text = $text($settings['button_text'] ?? null, 'Send'); $next_text = $text($settings['next_text'] ?? null, 'Next'); $prev_text = $text($settings['prev_text'] ?? null, 'Back'); $config = [ 'messages' => [ 'success' => $text($settings['success_message'] ?? null, ''), 'error' => $text($settings['error_message'] ?? null, ''), 'required' => $text($settings['required_message'] ?? null, ''), 'invalid' => $text($settings['invalid_message'] ?? null, ''), ], 'stepText' => $step_text, 'reset' => $bool($settings['reset_on_success'] ?? null, true), 'recaptcha' => $recaptcha === 'off' ? null : ['version' => $recaptcha, 'siteKey' => $site_key], ]; $classes = array_filter([ $multi ? 'zx-form--steps' : '', $show_labels ? '' : 'zx-form--no-labels', $inline ? 'zx-form--labels-inline' : '', $bool($settings['button_full'] ?? null, false) ? 'zx-form--button-full' : '', ]); if ($classes) { $attrs = preg_replace('/class="/', 'class="' . esc_attr(implode(' ', $classes)) . ' ', $attrs, 1) ?? $attrs; } $attrs .= ' data-zx-form="' . esc_attr($el_id) . '" data-post="' . esc_attr((string) $zx_post_id) . '" action="' . esc_url($zx_action) . '" method="post" enctype="multipart/form-data" novalidate'; $attrs .= ' data-zx-config="' . esc_attr((string) wp_json_encode($config)) . '"'; $icon = is_array($settings['button_icon'] ?? null) ? $settings['button_icon'] : []; $icon_html = ''; if (!empty($icon['svg']) && is_string($icon['svg'])) { $icon_html = ''; } elseif (!empty($icon['value']) && is_string($icon['value'])) { $icon_html = ''; } $inline_html = static fn(string $zx_s): string => function_exists('wp_kses') ? wp_kses($zx_s, ['a' => ['href' => true, 'target' => true, 'rel' => true], 'strong' => [], 'em' => [], 'b' => [], 'i' => [], 'br' => [], 'span' => ['class' => true]]) : esc_html($zx_s); $render_field = static function (array $f) use ($el_id, $mark, $inline_html): string { $zx_id = 'zx-' . $el_id . '-' . $f['id']; $zx_name = 'fields[' . $f['id'] . ']'; $zx_type = $f['type']; if ($zx_type === 'hidden') { return ''; } $cls = 'zx-form__field zx-form__field--' . $zx_type . ' zx-form__field--w' . $f['width'] . ($f['required'] ? ' is-required' : ''); if ($zx_type === 'html') { $html = function_exists('wp_kses_post') ? wp_kses_post($f['html']) : esc_html($f['html']); return '
' . $html . '
'; } $req_mark = $f['required'] && $mark ? '' : ''; $group = $zx_type === 'radio' || $zx_type === 'checkbox'; $has_label = !($zx_type === 'acceptance' && $f['label'] === ''); $required = $f['required'] ? ' required' : ''; $described = ' aria-describedby="' . esc_attr($zx_id . '-error') . '"'; $out = '
'; if ($has_label) { if ($group || $zx_type === 'acceptance') { $out .= '' . esc_html($f['label']) . $req_mark . ''; } else { $out .= ''; } } $placeholder = $f['placeholder'] !== '' ? ' placeholder="' . esc_attr($f['placeholder']) . '"' : ''; switch ($zx_type) { case 'textarea': $out .= ''; break; case 'select': $out .= ''; break; case 'radio': case 'checkbox': $defaults = array_map('trim', explode(',', $f['default'])); $out .= '
'; foreach ($f['options'] as $i => $o) { $out .= ''; } $out .= '
'; break; case 'acceptance': $out .= ''; break; case 'upload': $out .= ''; break; default: $extra = ' type="' . esc_attr($zx_type) . '"'; foreach (['min', 'max', 'step'] as $k) { if ($f[$k] !== '') { $extra .= ' ' . $k . '="' . esc_attr($f[$k]) . '"'; } } if ($f['default'] !== '') { $extra .= ' value="' . esc_attr($f['default']) . '"'; } $auto = ['email' => 'email', 'tel' => 'tel'][$zx_type] ?? ''; if ($auto !== '') { $extra .= ' autocomplete="' . esc_attr($auto) . '"'; } $out .= ''; } $out .= '
'; return $out . '
'; }; $html = ''; if ($show_progress) { $first = str_replace(['{current}', '{total}'], ['1', (string) $total], $step_text); $html .= '
' . esc_html($first) . '
' . '
' . '
'; } if ($show_titles) { $html .= '
    '; foreach ($steps as $zx_s) { $zx_title = $zx_s['title'] !== '' ? $zx_s['title'] : sprintf(/* translators: %d: step number. */ __('Step %d', 'zadex'), $zx_s['index'] + 1); $html .= '
  1. ' . '' . esc_html((string) ($zx_s['index'] + 1)) . '' . esc_html($zx_title) . '
  2. '; } $html .= '
'; } foreach ($steps as $zx_s) { $i = $zx_s['index']; $html .= '
'; foreach ($zx_s['fields'] as $f) { $html .= $render_field($f); } $html .= '
'; if ($i > 0) { $html .= ''; } if ($i < $total - 1) { $html .= ''; } else { $html .= ''; } $html .= '
'; } if ($honeypot) { $hp = 'zx-' . $el_id . '-hp'; $html .= ''; } if ($recaptcha === 'v2') { $html .= '
'; } $html .= '
'; echo wp_kses('
' . $html . '
' . "\n", \Zadex\Frontend\Kses::allowed_html());