PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / V3.3.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder vV3.3.2
V3.3.2 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 All 139 releases
← All changes | includes/Frontend/Form/View/FormViewer.php +62 -20 V3.0.2 → V3.3.2 View file →
@@ -2,8 +2,9 @@
2 2
3 3 namespace BitCode\BitForm\Frontend\Form\View;
4 4
5 5 use BitCode\BitForm\Admin\Form\Helpers;
6 +use BitCode\BitForm\Core\Util\Translation\TranslationManager;
6 7 use BitCode\BitForm\Frontend\Form\FrontendFormManager;
7 8 use BitCode\BitForm\Frontend\Form\View\Conversational\ConversationalHelpers;
8 9 use BitCode\BitForm\Frontend\Form\View\Conversational\DefaultConversationalTheme;
9 10
@@ -65,8 +66,40 @@
65 66 }
66 67 return $honeypotInput;
67 68 }
68 69
70 + /**
71 + * Opt-out markers for HTML-layer translators (Google/GTranslate, TranslatePress)
72 + * when a form disables translation. Empty otherwise, so markup is untouched.
73 + *
74 + * @return array{attrs:string, cls:string}
75 + */
76 + private function noTranslateMarkup()
77 + {
78 + // Pass the row we already hold; otherwise the lookup re-queries form_content per render.
79 + $rawContent = $this->_form->isExist() ? $this->_form->getFieldsContent() : null;
80 + $enabled = TranslationManager::isFormTranslationEnabled($this->getFormID(), $rawContent);
81 + if ($enabled) {
82 + return ['attrs' => '', 'cls' => ''];
83 + }
84 + return ['attrs' => ' translate="no" data-no-translation', 'cls' => ' notranslate'];
85 + }
86 +
87 + /**
88 + * Carries the page language into the AJAX submission so validation and
89 + * confirmation strings match it. Empty when no provider resolves one.
90 + *
91 + * @return string
92 + */
93 + private function languageField()
94 + {
95 + $lang = (string) apply_filters('bitform_current_language', '', $this->getFormID());
96 + if ('' === $lang) {
97 + return '';
98 + }
99 + return '<input type="text" class="d-none" name="bf_lang" value="' . esc_attr($lang) . '">';
100 + }
101 +
69 102 public function setTheme($theme = 'Default')
70 103 {
71 104 $this->_theme = $theme;
72 105 }
@@ -122,9 +155,9 @@
122 155 }
123 156
124 157 public function fields($rowID)
125 158 {
126 - return $this->_fields->{$rowID};
159 + return $this->_fields->{$rowID} ?? null;
127 160 }
128 161
129 162 public function getNestedLayout($rowID)
130 163 {
@@ -147,8 +180,9 @@
147 180 }
148 181
149 182 public function getConversationalView($hasFile, $msg = null)
150 183 {
184 + $noTranslate = $this->noTranslateMarkup();
151 185 $conversationSettings = $this->getFormInfo()->conversationalSettings;
152 186 $this->_themeDetails = new DefaultConversationalTheme($conversationSettings);
153 187 $file_upload_tag = null;
154 188 $restrictionMsg = '';
@@ -178,9 +212,9 @@
178 212 }
179 213 }
180 214 $conversationNavigationHtml = $conversationalHelper->getNavigationView();
181 215
182 - $confMsg = $this->_form->getSuccessMessageMarkups();
216 + // $confMsg = $this->_form->getSuccessMessageMarkups();
183 217 $abandonmentMsg = $this->_form->getFormAbandonmentMessage();
184 218
185 219 // if (!empty($this->_buttons)) {
186 220 // $this->_buttons->name = $formIdentifier;
@@ -188,20 +222,13 @@
188 222 // $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
189 223 // }
190 224
191 225 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 - ';
226 + $restrictionMsg = $this->restrictionOverlay($msg, $formID);
200 227 }
201 228 $formHTML =
202 229 '
203 - <div id="' . $formIdentifier . '" class="b' . $formID . '-bit-form ' . $this->_form->getAtomicCls("_frm-bg-b{$formID}") . ' bit-form bf-form-wrapper">
230 + <div id="' . $formIdentifier . '"' . $noTranslate['attrs'] . ' class="b' . $formID . '-bit-form ' . $this->_form->getAtomicCls("_frm-bg-b{$formID}") . ' bit-form bf-form-wrapper' . $noTranslate['cls'] . '">
204 231 ' . $restrictionMsg . '
205 232 <form novalidate id="form-' . $formIdentifier . '" class="_frm-bc' . $formID . ' bf-form" ' . $file_upload_tag . ' method=\'post\'>
206 233 <input type="text" class="d-none" name="csrf" value="' . $this->_tokens['csrf'] . '">
207 234 <input type="text" class="d-none" name="t_identity" value="' . $this->_tokens['t_identity'] . '">
@@ -206,8 +233,9 @@
206 233 <input type="text" class="d-none" name="csrf" value="' . $this->_tokens['csrf'] . '">
207 234 <input type="text" class="d-none" name="t_identity" value="' . $this->_tokens['t_identity'] . '">
208 235 ' . $this->honeypotField() . '
209 236 <input type="text" class="d-none" name="bitforms_id" value="bitforms_' . $this->_form->getFormID() . '">
237 + ' . $this->languageField() . '
210 238 <div class="bc' . $formID . '-steps-container">
211 239 ' . $welcomePageHtml . '
212 240 ' . $fieldHtml . '
213 241 ' . $conversationNavigationHtml . '
@@ -220,10 +248,30 @@
220 248
221 249 return $formHTML;
222 250 }
223 251
252 + /**
253 + * Restriction overlay; message may hold the visitor IP, so it is kses-filtered.
254 + *
255 + * @param string $msg Restriction message
256 + * @param int $formID Form ID
257 + *
258 + * @return string Overlay markup
259 + */
260 + private function restrictionOverlay($msg, $formID)
261 + {
262 + return '
263 + <div class="' . $this->_form->getAtomicCls("_frm-ovrly-b{$formID}") . '">
264 + <p class="' . $this->_form->getAtomicCls("_frm-ovrly-msg-b{$formID}") . '">
265 + ' . wp_kses_post($msg) . '
266 + </p>
267 + </div>
268 +';
269 + }
270 +
224 271 private function setView($hasFile, $msg)
225 272 {
273 + $noTranslate = $this->noTranslateMarkup();
226 274 $file_upload_tag = null;
227 275 $restrictionMsg = '';
228 276 $formID = $this->_form->getFormID();
229 277 if ($hasFile) {
@@ -290,20 +338,13 @@
290 338 $subBtn = $this->_themeDetails->getField($this->_buttons, $buttonClass, '');
291 339 }
292 340
293 341 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 -';
342 + $restrictionMsg = $this->restrictionOverlay($msg, $formID);
302 343 }
303 344 $formHTML =
304 345 '
305 - <div id="' . $formIdentifier . '" class="b' . $formID . '-bit-form ' . $this->_form->getAtomicCls("_frm-bg-b{$formID}") . ' bit-form bf-form-wrapper">
346 + <div id="' . $formIdentifier . '"' . $noTranslate['attrs'] . ' class="b' . $formID . '-bit-form ' . $this->_form->getAtomicCls("_frm-bg-b{$formID}") . ' bit-form bf-form-wrapper' . $noTranslate['cls'] . '">
306 347 ' . $restrictionMsg . '
307 348 <form novalidate id="form-' . $formIdentifier . '" class="' . $this->_form->getAtomicCls("_frm-b{$formID}") . ' bf-form" ' . $file_upload_tag . ' method=\'post\'>
308 349 <input type="text" class="d-none" name="csrf" value="' . $this->_tokens['csrf'] . '">
309 350 <input type="text" class="d-none" name="t_identity" value="' . $this->_tokens['t_identity'] . '">
@@ -308,8 +349,9 @@
308 349 <input type="text" class="d-none" name="csrf" value="' . $this->_tokens['csrf'] . '">
309 350 <input type="text" class="d-none" name="t_identity" value="' . $this->_tokens['t_identity'] . '">
310 351 ' . $this->honeypotField() . '
311 352 <input type="text" class="d-none" name="bitforms_id" value="bitforms_' . $this->_form->getFormID() . '">
353 + ' . $this->languageField() . '
312 354 ' . $fieldHtml . '
313 355 </form>
314 356 ' . $abandonmentMsg . '
315 357 <div id=\'bf-form-msg-wrp-' . $formIdentifier . '\'></div>