%s',
esc_attr($input_id), esc_attr($id), $ph, $req, esc_textarea($f['default'] ?? '')
);
case 'select': {
/*
* `?:` still reads the key — with no placeholder set, it throws "Undefined array key",
* and with WP_DEBUG on that prints onto the front-end page.
* Everywhere else in this file uses `?? ''`; this was the one place that missed it.
* (Found on 2026-08-22: a string of PHP warnings printed on the contact page's form.
* placeholder is an optional key and leaving it out is entirely normal.)
*/
$opts = '';
foreach (Fields::resolve_options($f) as $o) {
$opts .= sprintf('', esc_attr($o['value']), esc_html($o['label']));
}
return sprintf('',
esc_attr($input_id), esc_attr($id), $req, $opts);
}
case 'radio':
case 'checkbox': {
$out = '
';
}
case 'consent':
return sprintf(
'',
esc_attr($input_id), esc_attr($input_id), esc_attr($id), $req,
wp_kses($f['label'] ?? '', Fields::consent_label_html())
);
default: {
$html_type = in_array($type, ['email', 'tel', 'number'], true) ? $type : 'text';
/*
* autocomplete is what saves the user work, especially on a phone.
* Emit the hints browsers understand per field type rather than expecting people to type every
* field by hand.
*/
$ac = ['email' => 'email', 'tel' => 'tel'][$type] ?? 'on';
return sprintf(
'',
esc_attr($html_type), esc_attr($input_id), esc_attr($id),
esc_attr($f['default'] ?? ''), esc_attr($ac), $ph, $req
);
}
}
}
}