PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.15.3
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.15.3
3.3.1 V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 2.10.1 All 138 releases
← All changes | includes/Frontend/Form/View/FieldHelpers.php +38 -324 3.3.12.15.3 View file →
@@ -1,10 +1,8 @@
1 1 <?php
2 2
3 3 namespace BitCode\BitForm\Frontend\Form\View;
4 4
5 -use BitCode\BitForm\Admin\Form\Helpers;
6 -use BitCode\BitForm\Core\Util\EscapingHelper;
7 5 use BitCode\BitForm\Core\Util\FieldValueHandler;
8 6 use BitCode\BitForm\Core\Util\FrontendHelpers;
9 7
10 8 class FieldHelpers
@@ -11,16 +9,14 @@
11 9 {
12 10 private $_fld;
13 11 private $_fk;
14 12 private $_form_atomic_Cls_map;
15 - private $_formID;
16 13
17 - public function __construct($field, $fk, $form_atomic_Cls_map = null, $formID = null)
14 + public function __construct($field, $fk, $form_atomic_Cls_map = null)
18 15 {
19 16 $this->_fld = $field;
20 17 $this->_fk = $fk;
21 18 $this->_form_atomic_Cls_map = $form_atomic_Cls_map;
22 - $this->_formID = $formID;
23 19 }
24 20
25 21 public function getCustomAttributes($element)
26 22 {
@@ -28,11 +24,8 @@
28 24 $attrString = '';
29 25 $customAttributs = $this->_fld->customAttributes->{$element};
30 26
31 27 foreach ($customAttributs as $attr) {
32 - if (!isset($attr->key) || !EscapingHelper::isSafeAttributeKey((string) $attr->key)) {
33 - continue;
34 - }
35 28 $attrString .= " {$this->esc_attr($attr->key)}='{$this->esc_attr($attr->value)}'";
36 29 }
37 30 return $attrString;
38 31 }
@@ -46,137 +39,46 @@
46 39 }
47 40 return '';
48 41 }
49 42
50 - public function renderHTMR($content)
43 + public function renderHTMR($title)
51 44 {
52 - $safeContent = Helpers::sanitizeUserHTML($content);
53 - return $safeContent;
45 + $allowed_html = wp_kses_allowed_html('post');
46 +
47 + $allowed_html['iframe'] = [
48 + 'src' => true,
49 + 'width' => true,
50 + 'height' => true,
51 + 'frameborder' => true,
52 + 'allow' => true,
53 + 'allowfullscreen' => true,
54 + 'title' => true,
55 + 'style' => true,
56 + ];
57 + return wp_kses($title, $allowed_html);
54 58 }
55 59
56 60 public function getAtomicCls($element)
57 61 {
58 - $meaningfulElementClass = "bf-{$this->getMeaningfullElementClass($element)}";
59 62 if (empty($this->_fld) && empty($this->_fk)) {
60 - if (is_object($this->_form_atomic_Cls_map) && property_exists($this->_form_atomic_Cls_map, ".$element")) {
63 + if (property_exists($this->_form_atomic_Cls_map, ".$element")) {
61 64 $getAtomicCls = $this->_form_atomic_Cls_map->{".$element"};
62 - return implode(' ', $getAtomicCls) . " {$element} {$meaningfulElementClass}";
65 + return implode(' ', $getAtomicCls) . " $element";
63 66 }
64 - return "$element {$meaningfulElementClass}";
67 + return $element;
65 68 }
66 - if (isset($this->_fld->typ) && 'advanced-file-up' === $this->_fld->typ && isset($this->_form_atomic_Cls_map->{".$element"})) {
69 + if ('advanced-file-up' === $this->_fld->typ && isset($this->_form_atomic_Cls_map->{".$element"})) {
67 70 $getAtomicCls = $this->_form_atomic_Cls_map->{".$element"};
68 - return implode(' ', $getAtomicCls) . " {$this->_fk}-{$element} {$meaningfulElementClass}";
71 + return implode(' ', $getAtomicCls) . " {$this->_fk}-{$element}";
69 72 }
70 - $fieldElementCls = ".{$this->_fk}-{$element}";
71 - $formId = explode('-', $this->_fk)[0]; // exmp: b12-10 => $formId = b12
72 - // $formElementCls = ".{$element}-" . $formId;
73 - $formElementCls = ".{$formId}-" . $element;
74 -
75 - if (isset($this->_form_atomic_Cls_map->{$fieldElementCls})) {
76 - $formElementAtomicClsString = '';
77 - if (property_exists($this->_form_atomic_Cls_map, $formElementCls)) {
78 - $formElementAtomicClsArray = $this->_form_atomic_Cls_map->{$formElementCls};
79 - $formElementAtomicClsString = implode(' ', $formElementAtomicClsArray);
80 - }
81 - $getAtomicCls = $this->_form_atomic_Cls_map->{$fieldElementCls};
82 - return implode(' ', $getAtomicCls) . " {$formElementAtomicClsString} {$this->_fk}-{$element} {$formId}-{$element} bf-{$element} {$meaningfulElementClass}";
73 + $cls = ".$this->_fk-$element";
74 + if (isset($this->_form_atomic_Cls_map->{$cls})) {
75 + $getAtomicCls = $this->_form_atomic_Cls_map->{$cls};
76 + return implode(' ', $getAtomicCls) . " {$this->_fk}-{$element} bf-{$element}";
83 77 }
84 - return "{$this->_fk}-{$element} {$formId}-{$element} bf-{$element} {$meaningfulElementClass}";
78 + return "{$this->_fk}-{$element} bf-{$element}";
85 79 }
86 80
87 - public function getMeaningfullElementClass($element)
88 - {
89 - $elementTitleMap = [
90 - 'fld-wrp' => 'field-wrapper',
91 - 'lbl-wrp' => 'label-wrapper',
92 - 'lbl' => 'label',
93 - 'lbl-pre-i' => 'label-prefix-icon',
94 - 'lbl-suf-i' => 'label-suffix-icon',
95 - 'sub-titl' => 'subtitle',
96 - 'sub-titl-pre-i' => 'subtitle-prefix-icon',
97 - 'sub-titl-suf-i' => 'subtitle-suffix-icon',
98 - 'fld' => 'field',
99 - 'pre-i' => 'field-prefix-icon',
100 - 'suf-i' => 'field-suffix-icon',
101 - 'hlp-txt' => 'helper-text-container',
102 - 'hlp-txt-pre-i' => 'helper-text-prefix-icon',
103 - 'hlp-txt-suf-i' => 'helper-text-suffix-icon',
104 - 'err-msg' => 'error-messages-container',
105 - 'err-txt-pre-i' => 'error-text-prefix-icon',
106 - 'err-txt-suf-i' => 'error-text-suffix-icon',
107 - 'currency-fld-wrp' => 'currency-field-wrapper',
108 - 'btn' => 'button',
109 - 'btn-pre-i' => 'button-prefix-icon',
110 - 'btn-suf-i' => 'button-suffix-icon',
111 - 'other-inp' => 'other-option-input',
112 - 'inp-wrp' => 'input-wrapper',
113 - 'inp-wrp .filepond--panel-root' => 'item-panel-wrapper',
114 - 'inp-wrp .filepond--item-panel' => 'item-panel',
115 - 'inp-wrp .filepond--file-action-button' => 'file-action-button',
116 - 'inp-wrp .filepond--file' => 'file',
117 - 'inp-wrp .filepond--drop-label' => 'drop-label',
118 - 'inp-wrp .filepond--label-action' => 'label-action',
119 - 'option-list' => 'option-list',
120 - 'option-list .option' => 'option',
121 - 'option-list .opt-lbl-wrp' => 'option-label-container',
122 - 'option-list .opt-icn' => 'option-icon',
123 - 'option-list .opt-lbl' => 'option-label',
124 - 'option-list .opt-suffix' => 'option-suffix',
125 - 'option-list .opt-prefix' => 'option-prefix',
126 - 'divider' => 'divider',
127 - 'bx' => 'box',
128 - 'stripe-btn' => 'stripe-button',
129 - 'stripe-icn' => 'stripe-icon',
130 - 'stripe-pay-btn' => 'stripe-pay-button',
131 - 'rating-img' => 'rating-image',
132 - 'rating-msg' => 'rating-message',
133 - 'req-smbl' => 'asterisk-symbol',
134 - '_frm-bg' => 'form-wrapper',
135 - '_frm' => 'form-container',
136 - ];
137 -
138 - if (isset($elementTitleMap[$element])) {
139 - return $elementTitleMap[$element];
140 - }
141 -
142 - // Fallback: convert hyphenated element key to meaningful class
143 - // e.g., 'fld-wrp' => 'fld wrp' => join with '-' after expanding abbreviations
144 - $abbreviations = [
145 - 'fld' => 'field',
146 - 'wrp' => 'wrapper',
147 - 'lbl' => 'label',
148 - 'pre' => 'prefix',
149 - 'suf' => 'suffix',
150 - 'i' => 'icon',
151 - 'titl' => 'title',
152 - 'sub' => 'sub',
153 - 'hlp' => 'helper',
154 - 'txt' => 'text',
155 - 'err' => 'error',
156 - 'msg' => 'message',
157 - 'btn' => 'button',
158 - 'inp' => 'input',
159 - 'opt' => 'option',
160 - 'icn' => 'icon',
161 - 'img' => 'image',
162 - 'smbl' => 'symbol',
163 - 'req' => 'required',
164 - 'frm' => 'form',
165 - 'bg' => 'background',
166 - ];
167 -
168 - $splitElements = explode('-', $element);
169 - $meaningfulParts = [];
170 -
171 - foreach ($splitElements as $part) {
172 - $cleanPart = ltrim($part, '_');
173 - $meaningfulParts[] = isset($abbreviations[$cleanPart]) ? $abbreviations[$cleanPart] : $cleanPart;
174 - }
175 -
176 - return implode('-', $meaningfulParts);
177 - }
178 -
179 81 public function replaceToBackSlash($str)
180 82 {
181 83 $phReplaceToBackslash = str_replace('$_bf_$', '\\', $str); // Replace React inputs value "$_bf_$" to '\\'
182 84 return FieldValueHandler::replaceSmartTagWithValue($phReplaceToBackslash);
@@ -186,54 +88,18 @@
186 88 * @param $element @exmp $element = 'fld-wrp'
187 89 */
188 90 public function icon($icnPropName, $element)
189 91 {
190 - $hasIconImg = $this->property_exists_nested($this->_fld, $icnPropName, '', 1);
191 - $showPasswordIcon = $this->property_exists_nested($this->_fld, 'typ', 'password')
192 - && $this->property_exists_nested($this->_fld, 'config->showPasswordIcon', true);
193 - // For password suffix, render a shared suffix wrapper that can contain both
194 - // show/hide SVG and the configured suffix image (in this order).
195 - if ('suf-i' === $element && ($hasIconImg || $showPasswordIcon)) {
196 - $toggleButton = '';
197 - $suffixIconImg = '';
198 - if ($showPasswordIcon) {
199 - $fieldKey = $this->esc_attr($this->_fk);
200 - $toggleBtnId = "bf-pw-showhide-btn-{$fieldKey}";
201 - $toggleSlashId = "bf-pw-eye-{$fieldKey}";
202 - $toggleButton = '<button id="' . $toggleBtnId . '" class="show-hide-password-btn" data-fldkey="' . $fieldKey . '" type="button" title="Show password" aria-label="Show password" aria-pressed="false" style="height: 20px; width: 20px; cursor: pointer; border: none; background: none; padding: 0; margin: 0; outline: none;">'
203 - . '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" width="20">'
204 - . '<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />'
205 - . '<circle cx="12" cy="12" r="3" />'
206 - . '<path d="M20 4l-16 16" id="' . $toggleSlashId . '" style="display: none;"/>'
207 - . '</svg>'
208 - . '</button>';
209 - }
210 -
211 - if ($hasIconImg) {
212 - $suffixIconImg = '<img'
213 - . $this->getCustomAttributes($element)
214 - . ' src="' . $this->esc_url($this->_fld->{$icnPropName}) . '"'
215 - . ' alt=""'
216 - . ' aria-hidden="true"'
217 - . '/>';
218 - }
219 - if ($toggleButton) {
220 - return '<div class="' . $this->getAtomicCls($element) . ' ' . $this->getCustomClasses($element) . '">'
221 - . $toggleButton
222 - . $suffixIconImg
223 - . '</div>';
224 - }
92 + if ($this->property_exists_nested($this->_fld, $icnPropName, '', 1)) {
93 + return <<<ICON
94 +<img
95 + {$this->getCustomAttributes($element)}
96 + class="{$this->getAtomicCls($element)} {$this->getCustomClasses($element)}"
97 + src="{$this->esc_url($this->_fld->{$icnPropName})}"
98 + alt=""
99 +/>
100 +ICON;
225 101 }
226 -
227 - if ($hasIconImg) {
228 - return '<img'
229 - . $this->getCustomAttributes($element)
230 - . ' class="' . $this->getAtomicCls($element) . ' ' . $this->getCustomClasses($element) . '"'
231 - . ' src="' . $this->esc_url($this->_fld->{$icnPropName}) . '"'
232 - . ' alt=""'
233 - . ' aria-hidden="true"'
234 - . '/>';
235 - }
236 102 return '';
237 103 }
238 104
239 105 public function property_exists_nested($obj, $path = '', $valToCheck = null, $checkNegativeVal = 0)
@@ -276,64 +142,8 @@
276 142 }
277 143 return '';
278 144 }
279 145
280 - public function mn()
281 - {
282 - if ($this->property_exists_nested($this->_fld, 'mn', '', 1)) {
283 - return "min='{$this->esc_attr($this->_fld->mn)}'";
284 - }
285 - return '';
286 - }
287 -
288 - public function mx()
289 - {
290 - if ($this->property_exists_nested($this->_fld, 'mx', '', 1)) {
291 - return "max='{$this->esc_attr($this->_fld->mx)}'";
292 - }
293 - return '';
294 - }
295 -
296 - public function minlength()
297 - {
298 - if ($this->property_exists_nested($this->_fld, 'valid->minlength', '', 1)) {
299 - return "minlength='{$this->esc_attr($this->_fld->valid->minlength)}'";
300 - }
301 - return '';
302 - }
303 -
304 - public function maxlength()
305 - {
306 - if ($this->property_exists_nested($this->_fld, 'valid->maxlength', '', 1)) {
307 - return "maxlength='{$this->esc_attr($this->_fld->valid->maxlength)}'";
308 - }
309 - return '';
310 - }
311 -
312 - public function maxword()
313 - {
314 - if ($this->property_exists_nested($this->_fld, 'valid->maxword', '', 1)) {
315 - return "data-maxword='{$this->esc_attr($this->_fld->valid->maxword)}'";
316 - }
317 - return '';
318 - }
319 -
320 - public function minword()
321 - {
322 - if ($this->property_exists_nested($this->_fld, 'valid->minword', '', 1)) {
323 - return "data-minword='{$this->esc_attr($this->_fld->valid->minword)}'";
324 - }
325 - return '';
326 - }
327 -
328 - public function inputMode()
329 - {
330 - if ($this->property_exists_nested($this->_fld, 'inputMode', '', 1)) {
331 - return "inputMode='{$this->esc_attr($this->_fld->inputMode)}'";
332 - }
333 - return '';
334 - }
335 -
336 146 public function readonly()
337 147 {
338 148 if ($this->property_exists_nested($this->_fld, 'readonly', true)) {
339 149 return 'readonly';
@@ -410,12 +220,10 @@
410 220 }
411 221 if ($this->property_exists_nested($this->_fld, 'typ', 'file-up') && $this->property_exists_nested($this->_fld, 'config->multiple', true)) {
412 222 return "name='{$this->esc_attr($this->_fld->fieldName)}[]'";
413 223 }
414 - if (
415 - $this->property_exists_nested($this->_fld, 'typ', 'image-select')
416 - && $this->property_exists_nested($this->_fld, 'inpType', 'checkbox')
417 - ) {
224 + if ($this->property_exists_nested($this->_fld, 'typ', 'image-select')
225 + && $this->property_exists_nested($this->_fld, 'inpType', 'checkbox')) {
418 226 return "name='{$this->esc_attr($this->_fld->fieldName)}[]'";
419 227 }
420 228 return "name='{$this->esc_attr($this->_fld->fieldName)}'";
421 229 }
@@ -427,11 +235,11 @@
427 235 $val = '';
428 236 if ($this->property_exists_nested($this->_fld, 'val', '', 1)) {
429 237 $val = $this->_fld->val;
430 238 } elseif ($this->property_exists_nested($this->_fld, 'defaultValue', '', 1)) {
431 - $val = FieldValueHandler::replaceSmartTagWithValue($this->_fld->defaultValue);
239 + $val = $this->_fld->defaultValue;
432 240 }
433 - if (isset($val) && '' !== $val && 'textarea' !== $this->_fld->typ) {
241 + if (!empty($val) && 'textarea' !== $this->_fld->typ) {
434 242 return "value='{$this->esc_attr($val)}'";
435 243 }
436 244 return $val;
437 245 }
@@ -459,100 +267,6 @@
459 267 {
460 268 $bfFrontendFormIds = FrontendHelpers::$bfFrontendFormIds;
461 269 $contentCount = count($bfFrontendFormIds);
462 270 return "{$this->_fk}-{$contentCount}";
463 - }
464 -
465 - public function isChecked()
466 - {
467 - if (!isset($this->_fld->val)) {
468 - return false;
469 - }
470 - $checked = false;
471 - $msg = $this->_fld->msg;
472 - foreach ($msg as $status => $value) {
473 - if ($value === $this->_fld->val) {
474 - if ('checked' === $status) {
475 - $checked = true;
476 - break;
477 - }
478 - }
479 - }
480 -
481 - return $checked;
482 - }
483 -
484 - /**
485 - * Get error message container ID for accessibility
486 - * @return string
487 - */
488 - public function getErrorId()
489 - {
490 - return "{$this->_fk}-err-txt";
491 - }
492 -
493 - /**
494 - * Get helper text container ID for accessibility
495 - * @return string
496 - */
497 - public function getHelperTextId()
498 - {
499 - return "{$this->_fk}-hlp-txt";
500 - }
501 -
502 - /**
503 - * Get label ID for accessibility (aria-labelledby)
504 - * @return string
505 - */
506 - public function getLabelId()
507 - {
508 - $bfFrontendFormIds = FrontendHelpers::$bfFrontendFormIds;
509 - $contentCount = count($bfFrontendFormIds);
510 - return "{$this->_fk}-{$contentCount}-lbl";
511 - }
512 -
513 - /**
514 - * Check if field has helper text
515 - * @return bool
516 - */
517 - public function hasHelperText()
518 - {
519 - return $this->property_exists_nested($this->_fld, 'helperTxt', '', 1);
520 - }
521 -
522 - /**
523 - * Generate aria-describedby attribute linking to helper text and error message
524 - * @return string
525 - */
526 - public function ariaDescribedBy()
527 - {
528 - $ids = [];
529 - if ($this->hasHelperText()) {
530 - $ids[] = $this->getHelperTextId();
531 - }
532 - // Always include error ID so it can be announced when errors appear
533 - $ids[] = $this->getErrorId();
534 -
535 - return !empty($ids) ? 'aria-describedby="' . implode(' ', $ids) . '"' : '';
536 - }
537 -
538 - /**
539 - * Generate aria-required attribute for required fields
540 - * @return string
541 - */
542 - public function ariaRequired()
543 - {
544 - if ($this->property_exists_nested($this->_fld, 'valid->req', true)) {
545 - return 'aria-required="true"';
546 - }
547 - return '';
548 - }
549 -
550 - /**
551 - * Get the field data object
552 - * @return object
553 - */
554 - public function getFieldData()
555 - {
556 - return $this->_fld;
557 271 }
558 272 }