PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.21.4
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.21.4
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 2.10.2 All 137 releases
← All changes | includes/Frontend/Form/View/FormViewer.php +286 -92 1.92.21.4 View file →
@@ -1,114 +1,308 @@
1 1 <?php
2 2
3 3 namespace BitCode\BitForm\Frontend\Form\View;
4 4
5 +use BitCode\BitForm\Admin\Form\Helpers;
5 6 use BitCode\BitForm\Frontend\Form\FrontendFormManager;
7 +use BitCode\BitForm\Frontend\Form\View\Conversational\ConversationalHelpers;
8 +use BitCode\BitForm\Frontend\Form\View\Conversational\DefaultConversationalTheme;
6 9
7 10 class FormViewer
8 11 {
9 - private $_theme = 'Default';
10 - private $_themeDetails;
11 - private $_fields;
12 - private $_layout;
13 - private $_buttons;
14 - private $_form;
15 - private $_error;
16 - private $_previousValue;
17 - public function __construct(FrontendFormManager $formManager, $form_contents, $errorMessages = null, $previousValue = null)
18 - {
19 - $this->_fields = $form_contents->fields;
20 - $this->_layout = $form_contents->layout;
21 - $this->_buttons = isset($form_contents->buttons) ? $form_contents->buttons : '';
22 - $this->_form = $formManager;
23 - $this->_error = $errorMessages;
24 - $this->_previousValue = $previousValue;
12 + private $_theme = 'Default';
13 + private $_themeDetails;
14 + public $_fields;
15 + private $_layout;
16 + public $_nestedLayout;
17 + private $_buttons;
18 + public $_form;
19 + public $_error;
20 + private $_previousValue;
21 + public $_formAtomicClsMap;
22 + public $_tokens;
23 + public $_formContents;
24 +
25 + public function __construct(FrontendFormManager $formManager, $form_contents, $formAtomicClsMap, $errorMessages = null, $previousValue = null)
26 + {
27 + $this->_tokens = Helpers::csrfEecrypted();
28 + $this->_fields = $form_contents->fields;
29 + $this->_layout = $form_contents->layout;
30 + $this->_nestedLayout = isset($form_contents->nestedLayout) ? $form_contents->nestedLayout : '';
31 + $this->_buttons = isset($form_contents->buttons) ? $form_contents->buttons : '';
32 + $this->_form = $formManager;
33 + $this->_error = $errorMessages;
34 + $this->_formContents = $form_contents;
35 + $this->_previousValue = $previousValue;
36 + $this->_formAtomicClsMap = $formAtomicClsMap;
37 + }
38 +
39 + public function getView($hasFile, $msg = null)
40 + {
41 + $name = str_replace(' ', '', $this->_theme);
42 + $file = false !== strpos($name, 'Theme') ? $name . '.php' : $name . 'Theme.php';
43 + if (file_exists(__DIR__ . '/' . $file)) {
44 + $className = __NAMESPACE__ . '\\Theme\\' . $name . 'Theme';
45 + $this->_themeDetails = new $className();
46 + } else {
47 + $className = __NAMESPACE__ . '\\Theme\\' . 'DefaultTheme';
48 + $this->_themeDetails = new $className();
25 49 }
26 - public function getView($hasFile)
27 - {
28 - $name = str_replace(' ', '', $this->_theme);
29 - $file = strpos($name, 'Theme') !== false ? $name . '.php' : $name . 'Theme.php';
30 - if (file_exists(__DIR__ . '/' . $file)) {
31 - $className = __NAMESPACE__ . '\\Theme\\' . $name . 'Theme';
32 - $this->_themeDetails = new $className;
50 + return $this->setView($hasFile, $msg);
51 + }
52 +
53 + public function honeypotField()
54 + {
55 + $time = time();
56 + $honeypodFldName = Helpers::honeypotEncryptedToken("_bitforms_{$this->getFormID()}_{$time}_");
57 + $honeypotInput = '';
58 + if (Helpers::property_exists_nested($this->_formContents, 'additional->enabled->honeypot', true)) {
59 + $honeypotInput =
60 + <<<HTMLa
61 + <input type="text" class="d-none" name="b_h_t" value="{$honeypodFldName}">
62 + <input type="text" class="d-none" name="{$honeypodFldName}" required>
63 +HTMLa;
64 + return $honeypotInput;
65 + }
66 + return $honeypotInput;
67 + }
68 +
69 + public function setTheme($theme = 'Default')
70 + {
71 + $this->_theme = $theme;
72 + }
73 +
74 + public function getError($field_name)
75 + {
76 + return isset($this->_error[$field_name]) ? $this->_error[$field_name] : null;
77 + }
78 +
79 + public function getFieldName($rowId)
80 + {
81 + $formIdentifier = $this->_form->getFormIdentifier();
82 + $field_name = $rowId;
83 + if ('button' === $this->_fields->{$rowId}->typ && 'submit' === $this->_fields->{$rowId}->btnTyp) {
84 + $field_name = $formIdentifier;
85 + }
86 + $field_name .= isset($this->_fields->{$rowId}->lbl) ? preg_replace('/[\`\~\!\@\#\$\'\.\s\?\+\-\*\&\|\/\\\!]/', '_', $this->_fields->{$rowId}->lbl) : '';
87 + return $field_name;
88 + }
89 +
90 + public function getAtomicClaMap()
91 + {
92 + return $this->_formAtomicClsMap;
93 + }
94 +
95 + public function getValue($field_name, $rowId)
96 + {
97 + $valueToEsc = isset($this->_previousValue[$field_name]) ?
98 + $this->_previousValue[$field_name] : (isset($this->_fields->{$rowId}->val) ? $this->_fields->{$rowId}->val : null);
99 + if (empty($valueToEsc)) {
100 + $value = null;
101 + } else {
102 + if ((isset($this->_fields->{$rowId}->mul) || 'check' === $this->_fields->{$rowId}->typ || 'select' === $this->_fields->{$rowId}->typ)) {
103 + if ('select' === $this->_fields->{$rowId}->typ && is_string($valueToEsc)) {
104 + $valueToEsc = explode(',', $valueToEsc);
105 + }
106 + if (is_array($valueToEsc)) {
107 + $value = array_map('esc_attr', $valueToEsc);
33 108 } else {
34 - $className = __NAMESPACE__ . '\\Theme\\' . 'DefaultTheme';
35 - $this->_themeDetails = new $className;
109 + $value = esc_attr($valueToEsc);
36 110 }
37 - return $this->setView($hasFile);
111 + } else {
112 + $value = !is_array($valueToEsc) ? esc_attr($valueToEsc) :
113 + esc_attr($valueToEsc[count($valueToEsc) - 1]);
114 + }
38 115 }
116 + return $value;
117 + }
39 118
40 - public function setTheme($theme = 'Default')
41 - {
42 - $this->_theme = $theme;
119 + public function getFormID()
120 + {
121 + return $this->_form->getFormID();
122 + }
123 +
124 + public function fields($rowID)
125 + {
126 + return $this->_fields->{$rowID};
127 + }
128 +
129 + public function getNestedLayout($rowID)
130 + {
131 + // return null;
132 + return isset($this->_nestedLayout->{$rowID}) ? $this->_nestedLayout->{$rowID} : null;
133 + }
134 +
135 + public function getFormInfo()
136 + {
137 + return $this->_formContents->formInfo;
138 + }
139 +
140 + private function getLayoutHtml($lay)
141 + {
142 + $html = '';
143 + foreach ($lay->lg as $row) {
144 + $html .= $this->_themeDetails->inputWrapper($this, $row->i);
43 145 }
146 + return $html;
147 + }
44 148
45 - private function setView($hasFile)
46 - {
47 - $file_upload_tag = null;
48 - $formID = $this->_form->getFormID();
49 - if ($hasFile) {
50 - $file_upload_tag = 'enctype="multipart/form-data"';
51 - wp_enqueue_script('bitforms-frontend-file');
52 - }
53 - $formIdentifier = $this->_form->getFormIdentifier();
54 - $fieldHtml = "";
55 - foreach ($this->_layout->lg as $key => $row) {
56 - $field_name = $row->i;
57 - if ($this->_fields->{$row->i}->typ === 'button' && $this->_fields->{$row->i}->btnTyp === 'submit') {
58 - $field_name = $formIdentifier;
59 - }
60 - // $field_name .= isset($this->_fields->{$row->i}->lbl) ? preg_replace('/[\`\~\!\@\#\$\'\.\s\?\+\-\*\&\|\/\\\!]/', '_', $this->_fields->{$row->i}->lbl) : "";
61 - $error = isset($this->_error[$field_name]) ? $this->_error[$field_name] : null;
62 - $valueToEsc = isset($this->_previousValue[$field_name]) ?
63 - $this->_previousValue[$field_name] : (isset($this->_fields->{$row->i}->val) ? $this->_fields->{$row->i}->val : null);
64 - if (empty($valueToEsc)) {
65 - $value = null;
66 - } else {
67 - if ((isset($this->_fields->{$row->i}->mul) || $this->_fields->{$row->i}->typ === 'check' || $this->_fields->{$row->i}->typ === 'select')) {
68 - if ($this->_fields->{$row->i}->typ === 'select' && is_string($valueToEsc)) {
69 - $valueToEsc = explode(',', $valueToEsc);
70 - }
71 - if (is_array($valueToEsc)) {
72 - $value = array_map('esc_attr', $valueToEsc);
73 - } else {
74 - $value = esc_attr($valueToEsc);
75 - }
76 - } else {
77 - $value = !is_array($valueToEsc) ? esc_attr($valueToEsc) :
78 - esc_attr($valueToEsc[count($valueToEsc) - 1]);
79 - }
80 - }
149 + public function getConversationalView($hasFile, $msg = null)
150 + {
151 + $conversationSettings = $this->getFormInfo()->conversationalSettings;
152 + $this->_themeDetails = new DefaultConversationalTheme($conversationSettings);
153 + $file_upload_tag = null;
154 + $restrictionMsg = '';
155 + $formID = $this->_form->getFormID();
156 + if ($hasFile) {
157 + $file_upload_tag = 'enctype="multipart/form-data"';
158 + }
159 + $formIdentifier = $this->_form->getFormIdentifier();
160 + $fieldHtml = '';
161 + $layouts = $this->_layout;
162 + $isMultiStep = is_array($layouts) && count($layouts) > 1;
163 + $layoutIsArray = !$isMultiStep && is_array($layouts);
164 + if ($layoutIsArray) {
165 + $layout = $layouts[0];
166 + $layouts = isset($layout->layout) ? $layout->layout : $layout;
167 + $this->_layout = $layouts;
168 + }
169 + $conversationalHelper = new ConversationalHelpers($this->getFormID(), $conversationSettings);
170 + $welcomePageHtml = $conversationalHelper->getWelcomePageView();
171 + if (!$isMultiStep) {
172 + $tempLayout = $conversationalHelper->filterConversationalAllowedFields($layouts, $this->_fields);
173 + $fieldHtml .= $this->getLayoutHtml($tempLayout);
174 + } else {
175 + foreach ($layouts as $lay) {
176 + $tempLayout = $conversationalHelper->filterConversationalAllowedFields($lay->layout, $this->_fields);
177 + $fieldHtml .= $this->getLayoutHtml($tempLayout);
178 + }
179 + }
180 + $conversationNavigationHtml = $conversationalHelper->getNavigationView();
81 181
82 - $fieldHtml .= $this->_themeDetails->inputWrapper(
83 - $this->_fields->{$row->i},
84 - $row->i,
85 - $field_name,
86 - $error,
87 - $value,
88 - $formID
89 - );
90 - }
182 + $confMsg = $this->_form->getSuccessMessageMarkups();
183 + $abandonmentMsg = $this->_form->getFormAbandonmentMessage();
91 184
92 - if (!empty($this->_buttons)) {
93 - $this->_buttons->name = $formIdentifier;
94 - $buttonClass = "button-{$formIdentifier}";
95 - $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
96 - }
185 + // if (!empty($this->_buttons)) {
186 + // $this->_buttons->name = $formIdentifier;
187 + // $buttonClass = "button-{$formIdentifier}";
188 + // $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
189 + // }
97 190
98 - $formHTML =
99 - <<<FORM
100 -<div id="f-{$formID}">
101 - <form novalidate id="form-{$formIdentifier}" class="_frm-bg-{$formID}" action="" $file_upload_tag method='post'>
102 - <input type="hidden" name="bitforms_token" value="{$this->_form->getFormToken()}">
103 - <input type="hidden" name="bitforms_id" value="bitforms_{$this->_form->getFormID()}">
104 - <div class="_frm-{$formID}">
105 - <div class="_frm-g _frm-g-{$formID}">
106 - $fieldHtml
191 + if (!empty($msg)) {
192 + $restrictionMsg = <<<MSG
193 + <div class="{$this->_form->getAtomicCls("_frm-ovrly-b{$formID}")}">
194 + <p class="{$this->_form->getAtomicCls("_frm-ovrly-msg-b{$formID}")}">
195 + $msg
196 + </p>
197 + </div>
198 +MSG;
199 + }
200 + $formHTML =
201 + <<<HTMLa
202 + <div id="{$formIdentifier}" class="bit-form {$this->_form->getAtomicCls("_frm-bg-b{$formID}")}">
203 + $restrictionMsg
204 + <form novalidate id="form-{$formIdentifier}" class="_frm-bc{$formID}" $file_upload_tag method='post'>
205 + <input type="text" class="d-none" name="csrf" value="{$this->_tokens['csrf']}">
206 + <input type="text" class="d-none" name="t_identity" value="{$this->_tokens['t_identity']}">
207 + {$this->honeypotField()}
208 + <input type="text" class="d-none" name="bitforms_id" value="bitforms_{$this->_form->getFormID()}">
209 + <div class="bc{$formID}-steps-container">
210 + $welcomePageHtml
211 + $fieldHtml
212 + </div>
213 + </form>
214 + <div id='bc-form-msg-wrp-{$formIdentifier}' class="bc-form-msg-wrp"></div>
215 + $abandonmentMsg
216 + $conversationNavigationHtml
217 + </div>
218 +HTMLa;
219 +
220 + return $formHTML;
221 + }
222 +
223 + private function setView($hasFile, $msg)
224 + {
225 + $file_upload_tag = null;
226 + $restrictionMsg = '';
227 + $formID = $this->_form->getFormID();
228 + if ($hasFile) {
229 + $file_upload_tag = 'enctype="multipart/form-data"';
230 + }
231 + $formIdentifier = $this->_form->getFormIdentifier();
232 + $fieldHtml = '';
233 + $layouts = $this->_layout;
234 + $isMultiStep = is_array($layouts) && count($layouts) > 1;
235 + $layoutIsArray = !$isMultiStep && is_array($layouts);
236 + if ($layoutIsArray) {
237 + $layout = $layouts[0];
238 + $layouts = isset($layout->layout) ? $layout->layout : $layout;
239 + $this->_layout = $layouts;
240 + }
241 + if (!$isMultiStep) {
242 + $fieldHtml .= $this->getLayoutHtml($layouts);
243 + } else {
244 + $formViewHelper = new FormViewHelper($this->_form, $this->_formContents);
245 +
246 + $fieldHtml .= <<<STEPWRPR
247 + <div class='{$this->_form->getAtomicCls("_frm-b{$formID}-stp-cntnr")} _frm-b-stp-cntnr'>
248 + {$formViewHelper->getStepHeaderHtml()}
249 + <div class='{$this->_form->getAtomicCls("_frm-b{$formID}-stp-wrpr")} _frm-b-stp-wrpr'>
250 + {$formViewHelper->getProgressBarMarkup()}
251 + <div class='{$this->_form->getAtomicCls("_frm-b{$formID}-stp-cntnt-wrpr")} _frm-b-stp-cntnt-wrpr'>
252 +STEPWRPR;
253 + foreach ($layouts as $key => $lay) {
254 + $hideOtherSteps = $key > 0 ? 'deactive' : '';
255 + $step = $key + 1;
256 + $fieldHtml .= <<<HTMLa
257 + <div class="{$this->_form->getAtomicCls("_frm-b{$formID}-stp-cntnt")} _frm-b-stp-cntnt $hideOtherSteps" data-step="{$step}">
258 + <div class="_frm-b{$formID} _frm-b">
259 + {$this->getLayoutHtml($lay->layout)}
260 + </div>
261 + {$formViewHelper->getStepButtonMarkup()}
107 262 </div>
263 +HTMLa;
264 + }
265 + $fieldHtml .= <<<CLOSINGTAG
266 + </div>
108 267 </div>
109 - </form>
110 -</div>
111 -FORM;
112 - return $formHTML;
268 + </div>
269 +CLOSINGTAG;
113 270 }
271 +
272 + $confMsg = $this->_form->getSuccessMessageMarkups();
273 + $abandonmentMsg = $this->_form->getFormAbandonmentMessage();
274 +
275 + if (!empty($this->_buttons)) {
276 + $this->_buttons->name = $formIdentifier;
277 + $buttonClass = "button-{$formIdentifier}";
278 + $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
279 + }
280 +
281 + if (!empty($msg)) {
282 + $restrictionMsg = <<<MSG
283 + <div class="{$this->_form->getAtomicCls("_frm-ovrly-b{$formID}")}">
284 + <p class="{$this->_form->getAtomicCls("_frm-ovrly-msg-b{$formID}")}">
285 + $msg
286 + </p>
287 + </div>
288 +MSG;
289 + }
290 + $formHTML =
291 + <<<HTMLa
292 + <div id="{$formIdentifier}" class="bit-form {$this->_form->getAtomicCls("_frm-bg-b{$formID}")}">
293 + $restrictionMsg
294 + <form novalidate id="form-{$formIdentifier}" class="{$this->_form->getAtomicCls("_frm-b{$formID}")}" $file_upload_tag method='post'>
295 + <input type="text" class="d-none" name="csrf" value="{$this->_tokens['csrf']}">
296 + <input type="text" class="d-none" name="t_identity" value="{$this->_tokens['t_identity']}">
297 + {$this->honeypotField()}
298 + <input type="text" class="d-none" name="bitforms_id" value="bitforms_{$this->_form->getFormID()}">
299 + $fieldHtml
300 + </form>
301 + $abandonmentMsg
302 + <div id='bf-form-msg-wrp-{$formIdentifier}'></div>
303 + $confMsg
304 + </div>
305 +HTMLa;
306 + return $formHTML;
307 + }
114 308 }