PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 3.1.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v3.1.2
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
bit-form / includes / Frontend / Form / View / FormViewer.php

FormViewer.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 3.1.2, at includes/Frontend/Form/View/FormViewer.php

332 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace BitCode\BitForm\Frontend\Form\View;
4
5 use BitCode\BitForm\Admin\Form\Helpers;
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;
9
10 class FormViewer
11 {
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();
49 }
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 '
61 <input type="text" class="d-none" name="b_h_t" value="' . $honeypodFldName . '">
62 <input type="text" class="d-none" name="' . $honeypodFldName . '" required>
63 ';
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);
108 } else {
109 $value = esc_attr($valueToEsc);
110 }
111 } else {
112 $value = !is_array($valueToEsc) ? esc_attr($valueToEsc) :
113 esc_attr($valueToEsc[count($valueToEsc) - 1]);
114 }
115 }
116 return $value;
117 }
118
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);
145 }
146 return $html;
147 }
148
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();
181
182 $confMsg = $this->_form->getSuccessMessageMarkups();
183 $abandonmentMsg = $this->_form->getFormAbandonmentMessage();
184
185 // if (!empty($this->_buttons)) {
186 // $this->_buttons->name = $formIdentifier;
187 // $buttonClass = "button-{$formIdentifier}";
188 // $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
189 // }
190
191 if (!empty($msg)) {
192 $restrictionMsg =
193 '
194 <div class="' . $this->_form->getAtomicCls("_frm-ovrly-b{$formID}") . '">
195 <p class="' . $this->_form->getAtomicCls("_frm-ovrly-msg-b{$formID}") . '">
196 ' . $msg . '
197 </p>
198 </div>
199 ';
200 }
201 $formHTML =
202 '
203 <div id="' . $formIdentifier . '" class="b' . $formID . '-bit-form ' . $this->_form->getAtomicCls("_frm-bg-b{$formID}") . ' bit-form bf-form-wrapper">
204 ' . $restrictionMsg . '
205 <form novalidate id="form-' . $formIdentifier . '" class="_frm-bc' . $formID . ' bf-form" ' . $file_upload_tag . ' method=\'post\'>
206 <input type="text" class="d-none" name="csrf" value="' . $this->_tokens['csrf'] . '">
207 <input type="text" class="d-none" name="t_identity" value="' . $this->_tokens['t_identity'] . '">
208 ' . $this->honeypotField() . '
209 <input type="text" class="d-none" name="bitforms_id" value="bitforms_' . $this->_form->getFormID() . '">
210 <div class="bc' . $formID . '-steps-container">
211 ' . $welcomePageHtml . '
212 ' . $fieldHtml . '
213 ' . $conversationNavigationHtml . '
214 </div>
215 </form>
216 <div id=\'bc-form-msg-wrp-' . $formIdentifier . '\' class="bc-form-msg-wrp"></div>
217 ' . $abandonmentMsg . '
218 </div>
219 ';
220
221 return $formHTML;
222 }
223
224 private function setView($hasFile, $msg)
225 {
226 $file_upload_tag = null;
227 $restrictionMsg = '';
228 $formID = $this->_form->getFormID();
229 if ($hasFile) {
230 $file_upload_tag = 'enctype="multipart/form-data"';
231 }
232 $formIdentifier = $this->_form->getFormIdentifier();
233 $fieldHtml = '';
234 $layouts = $this->_layout;
235 $isMultiStep = is_array($layouts) && count($layouts) > 1;
236 $layoutIsArray = !$isMultiStep && is_array($layouts);
237 if ($layoutIsArray) {
238 $layout = $layouts[0];
239 $layouts = isset($layout->layout) ? $layout->layout : $layout;
240 $this->_layout = $layouts;
241 }
242 if (!$isMultiStep) {
243 $fieldHtml .= $this->getLayoutHtml($layouts);
244 } else {
245 $formViewHelper = new FormViewHelper($this->_form, $this->_formContents);
246
247 $fieldHtml .=
248 '
249 <div class=\'' . $this->_form->getAtomicCls("_frm-b{$formID}-stp-cntnr") . ' _frm-b-stp-cntnr\'>
250 ' . $formViewHelper->getStepHeaderHtml() . '
251 <div class=\'' . $this->_form->getAtomicCls("_frm-b{$formID}-stp-wrpr") . ' _frm-b-stp-wrpr\'>
252 ' . $formViewHelper->getProgressBarMarkup() . '
253 <div class=\'' . $this->_form->getAtomicCls("_frm-b{$formID}-stp-cntnt-wrpr") . ' _frm-b-stp-cntnt-wrpr\'>
254 ';
255 foreach ($layouts as $key => $lay) {
256 $hideOtherSteps = $key > 0 ? 'deactive' : '';
257 $step = $key + 1;
258 $ariaHidden = $key > 0 ? 'aria-hidden="true"' : '';
259 $fieldHtml .=
260 '
261 <div
262 class="' . $this->_form->getAtomicCls("_frm-b{$formID}-stp-cntnt") . ' _frm-b-stp-cntnt ' . $hideOtherSteps . '"
263 data-step="' . $step . '"
264 role="tabpanel"
265 id="step-' . $formID . '-' . $step . '-panel"
266 aria-labelledby="step-' . $formID . '-' . $step . '-tab"
267 ' . $ariaHidden . '
268 >
269 <div class="_frm-b' . $formID . ' _frm-b">
270 ' . $this->getLayoutHtml($lay->layout) . '
271 </div>
272 ' . $formViewHelper->getStepButtonMarkup() . '
273 </div>
274 ';
275 }
276 $fieldHtml .=
277 '
278 </div>
279 </div>
280 </div>
281 ';
282 }
283
284 $confMsg = $this->_form->getSuccessMessageMarkups();
285 $abandonmentMsg = $this->_form->getFormAbandonmentMessage();
286
287 if (!empty($this->_buttons)) {
288 $this->_buttons->name = $formIdentifier;
289 $buttonClass = "button-{$formIdentifier}";
290 $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
291 }
292
293 if (!empty($msg)) {
294 $restrictionMsg =
295 '
296 <div class="' . $this->_form->getAtomicCls("_frm-ovrly-b{$formID}") . '">
297 <p class="' . $this->_form->getAtomicCls("_frm-ovrly-msg-b{$formID}") . '">
298 ' . $msg . '
299 </p>
300 </div>
301 ';
302 }
303 $formHTML =
304 '
305 <div id="' . $formIdentifier . '" class="b' . $formID . '-bit-form ' . $this->_form->getAtomicCls("_frm-bg-b{$formID}") . ' bit-form bf-form-wrapper">
306 ' . $restrictionMsg . '
307 <form novalidate id="form-' . $formIdentifier . '" class="' . $this->_form->getAtomicCls("_frm-b{$formID}") . ' bf-form" ' . $file_upload_tag . ' method=\'post\'>
308 <input type="text" class="d-none" name="csrf" value="' . $this->_tokens['csrf'] . '">
309 <input type="text" class="d-none" name="t_identity" value="' . $this->_tokens['t_identity'] . '">
310 ' . $this->honeypotField() . '
311 <input type="text" class="d-none" name="bitforms_id" value="bitforms_' . $this->_form->getFormID() . '">
312 ' . $fieldHtml . '
313 </form>
314 ' . $abandonmentMsg . '
315 <div id=\'bf-form-msg-wrp-' . $formIdentifier . '\'></div>
316 <!--
317 Live Region for Screen Reader Announcements (Accessibility)
318 -->
319 <div
320 class="bf-live-region"
321 role="status"
322 aria-live="polite"
323 aria-atomic="true"
324 style="position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;"
325 ></div>
326 ' . $confMsg . '
327 </div>
328 ';
329 return $formHTML;
330 }
331 }
332