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
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 / Core / Form / FormManager.php

FormManager.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 2.15.3, at includes/Core/Form/FormManager.php

1,110 lines 39.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Get set Form,fields
5 */
6
7 namespace BitCode\BitForm\Core\Form;
8
9 /**
10 * FrontendFormManager class
11 */
12
13 use BitCode\BitForm\Admin\Form\CustomFieldHandler;
14 use BitCode\BitForm\Core\Database\FormEntryLogModel;
15 use BitCode\BitForm\Core\Database\FormEntryMetaModel;
16 use BitCode\BitForm\Core\Database\FormEntryModel;
17 use BitCode\BitForm\Core\Database\FormModel;
18 use BitCode\BitForm\Core\Integration\IntegrationHandler;
19 use BitCode\BitForm\Core\Messages\SuccessMessageHandler;
20 use BitCode\BitForm\Core\Util\FieldValueHandler;
21 use BitCode\BitForm\Core\Util\FileHandler;
22 use BitCode\BitForm\Core\Util\FrontendHelpers;
23 use BitCode\BitForm\Core\Util\IpTool;
24 use BitCode\BitForm\Core\WorkFlow\WorkFlow;
25 use BitCode\BitForm\Core\WorkFlow\WorkFlowHandler;
26 use WP_Error;
27
28 class FormManager
29 {
30 protected static $form;
31 protected $formModel;
32 protected $form_id;
33 private $_has_upload;
34 private $_field_label;
35 private $_fields;
36 private $_repeaterFields;
37 private $_work_flows;
38 private $_conf_messages;
39 private $_atomic_class_map;
40 private $_saveFormAsDraft;
41
42 public function __construct($form_id)
43 {
44 $this->form_id = $form_id;
45 $this->formModel = new FormModel();
46
47 static::$form = $this->formModel->get(
48 [
49 'id',
50 'form_content',
51 'form_name',
52 'created_at',
53 'views',
54 'entries',
55 'status',
56 'builder_helper_state',
57 'atomic_class_map',
58 'generated_script_page_ids',
59 ],
60 [
61 'id' => $form_id,
62 ]
63 );
64 if (!is_wp_error(static::$form)) {
65 $this->_atomic_class_map = json_decode(static::$form[0]->atomic_class_map);
66 $bfMultipleFormsExists = FrontendHelpers::hasMultipleForms();
67 if ($bfMultipleFormsExists && isset($this->_atomic_class_map->atomic_class_map_with_form_id)) {
68 $this->_atomic_class_map = $this->_atomic_class_map->atomic_class_map_with_form_id;
69 } elseif (isset($this->_atomic_class_map->atomic_class_map)) {
70 $this->_atomic_class_map = $this->_atomic_class_map->atomic_class_map;
71 }
72 }
73 }
74
75 public function isExist()
76 {
77 return (!static::$form || is_wp_error(static::$form)) ? false : true;
78 }
79
80 public function checkStatus()
81 {
82 return '1' === static::$form[0]->status ? true : false;
83 }
84
85 public function getFieldsContent()
86 {
87 return self::$form[0]->form_content;
88 }
89
90 public function getFont()
91 {
92 $atomicClassMap = $this->_atomic_class_map;
93 $font = isset($atomicClassMap->font) ? $atomicClassMap->font : '';
94 return $font;
95 }
96
97 public function getStyle()
98 {
99 $builerState = \json_decode(static::$form[0]->builder_helper_state);
100 $style = '';
101 $themeVars = $builerState->themeVars;
102 $themeColors = $builerState->themeColors;
103
104 if (!empty($themeVars)) {
105 $style .= ':root {';
106 foreach ($themeVars->lgLightThemeVars as $key => $value) {
107 $style .= "$key: $value; ";
108 }
109 $style .= '} ';
110 }
111 if (!empty($themeColors)) {
112 $style .= ' :root {';
113 foreach ($themeColors->lightThemeColors as $k => $v) {
114 $style .= "$k:$v; ";
115 }
116 $style .= '} ';
117 }
118
119 $field = $builerState->style->lgLightStyles->fields;
120 foreach ($field as $value) {
121 $classes = $value->classes;
122 foreach ($classes as $key => $value) {
123 $style .= "{$key} {";
124 foreach ($value as $k => $v) {
125 $style .= "$k:$v; ";
126 }
127 $style .= '} ';
128 }
129 }
130 return $style;
131 }
132
133 public function getCustomStyle()
134 {
135 $customCssCodes = '';
136 $customCSSPath = BITFORMS_CONTENT_DIR . DIRECTORY_SEPARATOR . 'form-styles' . DIRECTORY_SEPARATOR . "bitform-custom-{$this->form_id}.css";
137
138 if (file_exists($customCSSPath)) {
139 $file = fopen($customCSSPath, 'r');
140 $customCssCodes = fread($file, filesize($customCSSPath));
141 fclose($file);
142 }
143
144 return $customCssCodes;
145 }
146
147 public function getCustomJS()
148 {
149 $customJSCodes = '';
150 $customJsPath = BITFORMS_CONTENT_DIR . DIRECTORY_SEPARATOR . 'form-scripts' . DIRECTORY_SEPARATOR . "bitform-custom-{$this->form_id}.js";
151 if (file_exists($customJsPath)) {
152 $file = fopen($customJsPath, 'r');
153 $customJSCodes = fread($file, filesize($customJsPath));
154 fclose($file);
155 }
156
157 return $customJSCodes;
158 }
159
160 public function getFormContentWithValue($defaultValues)
161 {
162 $form_content = \json_decode(static::$form[0]->form_content);
163 // this filter just use private purpose
164 $form_content->fields = apply_filters('bitform_dynamic_field_filter', $form_content->fields);
165 if (!is_array($defaultValues) || 0 === count($defaultValues)) {
166 return $form_content;
167 }
168 foreach ($form_content->fields as $fieldKey => $fieldDetails) {
169 // $field_name = empty($fieldDetails->lbl) ? null : \preg_replace('/[\`\~\!\@\#\$\'\.\s\?\+\-\*\&\|\/\\!]/', '_', $fieldDetails->lbl);
170 $fieldName = $fieldDetails->fieldName;
171 $defaultValue = isset($defaultValues[$fieldName]) ? $defaultValues[$fieldName] : null;
172 $defaultValue = isset($defaultValues[$fieldKey]) ? $defaultValues[$fieldKey] : $defaultValue;
173 if ((isset($fieldDetails->mul) || 'check' === $fieldDetails->typ) && isset($defaultValue)) {
174 // if (is_array($defaultValue)) {
175 // $fieldDetails->val =
176 // wp_json_encode(
177 // array_map('sanitize_text_field', $defaultValue)
178 // );
179 // } else {
180 // $fieldDetails->val = sanitize_text_field($defaultValue);
181 // }
182 if ((isset($fieldDetails->mul) && true === $fieldDetails->mul) || is_array($defaultValue)) {
183 $fieldDetails->val = wp_json_encode(array_map('sanitize_text_field', $defaultValue));
184 } elseif (!is_array($defaultValue)) {
185 $fieldDetails->val = sanitize_text_field($defaultValue);
186 }
187 } elseif (!is_null($defaultValue)) {
188 $fieldDetails->val = is_string($defaultValue) ?
189 sanitize_text_field($defaultValue) :
190 sanitize_text_field($defaultValue[count($defaultValue) - 1]);
191 }
192 }
193 return $form_content;
194 }
195
196 public function getFormContent()
197 {
198 $formContent = json_decode(static::$form[0]->form_content);
199 $types = ['check', 'radio', 'select'];
200 $filter = false;
201 foreach ($formContent->fields as $field) {
202 if (in_array($field->typ, $types) && property_exists($field, 'customType')) {
203 $filter = true;
204 break; // reduce unnecessary loop
205 }
206 }
207 if (true === $filter) {
208 $updateFields = apply_filters('bitform_dynamic_field_filter', $formContent->fields);
209 $formContent->fields = $updateFields;
210 }
211 return $formContent;
212 }
213
214 public function getFormInfo()
215 {
216 $formContent = json_decode(static::$form[0]->form_content);
217 $formInfo = isset($formContent->formInfo) ? $formContent->formInfo : null;
218 return $formInfo;
219 }
220
221 public function getFormHelperStates()
222 {
223 $formHelperStates = json_decode(static::$form[0]->builder_helper_state);
224 return $formHelperStates;
225 }
226
227 public function getAtomicClsMap()
228 {
229 return $this->_atomic_class_map;
230 }
231
232 private function is_json($str)
233 {
234 $json = json_decode($str);
235 return $json && $str !== $json;
236 }
237
238 public function getFormData($columnName = '')
239 {
240 if (empty($columnName)) {
241 return null;
242 }
243
244 $form = static::$form[0];
245 if (!isset($form->{$columnName})) {
246 return null;
247 }
248
249 $data = $form->{$columnName};
250 if ($this->is_json($data)) {
251 return json_decode($data);
252 }
253
254 return $data;
255 }
256
257 public function getFormName()
258 {
259 return static::$form[0]->form_name;
260 }
261
262 public function getFields()
263 {
264 if (!is_null($this->_fields)) {
265 return $this->_fields;
266 }
267 $form_content = \json_decode(static::$form[0]->form_content);
268 $layout = $form_content->layout;
269 $fields = $form_content->fields;
270 $field_details = [];
271 foreach ($fields as $key => $field) {
272 if ('recaptcha' === $field->typ) {
273 continue;
274 }
275 // $field_name = empty($field->lbl) ? null : \preg_replace('/[\`\~\!\@\#\$\'\.\s\?\+\-\*\&\|\/\\\!]/', '_', $field->lbl);
276 $field_type = $field->typ;
277 $field_details[$key]['label'] = empty($field->lbl) ? null : $field->lbl;
278 $field_details[$key]['type'] = $field_type;
279 $field_details[$key]['key'] = $key;
280 $field_details[$key]['name'] = isset($field->fieldName) ? $field->fieldName : '';
281 if (isset($field->customType)) {
282 $field_details[$key]['customType'] = $field->customType;
283 }
284
285 if (isset($field->err)) {
286 if (isset($field->err->entryUnique)) {
287 $field_details[$key]['entryUnique'] = $field->err->entryUnique;
288 }
289 if (isset($field->err->userUnique)) {
290 $field_details[$key]['userUnique'] = $field->err->userUnique;
291 }
292 }
293
294 if (isset($field->mul)) {
295 $field_details[$key]['mul'] = $field->mul;
296 }
297 if ('file-up' === $field_type && isset($field->exts)) {
298 $field_details[$key]['valid']['type'] = $field->exts;
299 }
300 if ('file-up' === $field_type && isset($field->mxUp)) {
301 $field_details[$key]['valid']['upload_size'] = (int) $field->mxUp;
302 }
303 if (isset($field->valid) && !is_null($field->valid)) {
304 if (isset($field->valid->req)) {
305 $field_details[$key]['valid']['req'] = $field->valid->req;
306 }
307 if (isset($field->valid->reqMsg)) {
308 $field_details[$key]['valid']['reqMsg'] = $field->valid->reqMsg;
309 }
310 if (isset($field->valid->typMsg)) {
311 $field_details[$key]['valid']['typMsg'] = $field->valid->typMsg;
312 }
313 }
314 if ($this->isRepeatedField($key)) {
315 $field_details[$key]['repeated'] = true;
316 }
317 }
318 if ($this->isGCLIDEnabled()) {
319 $field_details['GCLID']['name'] = 'GCLID';
320 $field_details['GCLID']['adminLbl'] = 'GCLID';
321 $field_details['GCLID']['key'] = 'GCLID';
322 $field_details['GCLID']['type'] = 'hidden';
323 }
324 $this->_fields = $field_details;
325 return $field_details;
326 }
327
328 public function getFieldsKey()
329 {
330 $form_content = \json_decode(static::$form[0]->form_content);
331 $fields = $form_content->fields;
332 $field_details = [];
333 foreach ($fields as $key => $field) {
334 if ('recaptcha' === $field->typ) {
335 continue;
336 }
337 // $field_name = empty($field->lbl) ? null : \preg_replace('/[\`\~\!\@\#\$\'\.\s\?\+\-\*\&\|\/\\\!]/', '_', $field->lbl);
338 $field_details[$key] = $key;
339 }
340 if ($this->isGCLIDEnabled()) {
341 $field_details['GCLID'] = 'GCLID';
342 }
343 return $field_details;
344 }
345
346 public function getFieldLabel($forQuery = false)
347 {
348 if (!is_null($this->_field_label)) {
349 return $this->_field_label;
350 }
351 $form_content = \json_decode(static::$form[0]->form_content);
352 $fields = $form_content->fields;
353 $field_details = [];
354 $fieldCounter = 0;
355 foreach ($fields as $key => $field) {
356 if ('recaptcha' === $field->typ || 'turnstile' === $field->typ || 'html' === $field->typ || 'button' === $field->typ) {
357 continue;
358 }
359 $field_details[$fieldCounter]['name'] = empty($field->lbl) ? null : $field->lbl;
360 $field_details[$fieldCounter]['adminLbl'] = empty($field->adminLbl) ? $field_details[$fieldCounter]['name'] : $field->adminLbl;
361 $field_details[$fieldCounter]['key'] = $key;
362 $field_details[$fieldCounter]['type'] = $field->typ;
363 $fieldCounter += 1;
364 }
365 if ($this->isGCLIDEnabled()) {
366 $field_details[$fieldCounter]['name'] = 'GCLID';
367 $field_details[$fieldCounter]['adminLbl'] = 'GCLID';
368 $field_details[$fieldCounter]['key'] = 'GCLID';
369 $field_details[$fieldCounter]['type'] = 'hidden';
370 $fieldCounter += 1;
371 }
372 if (!$forQuery) {
373 $field_details = (array) $this->addEntryInfo($field_details, $fieldCounter);
374 }
375 $this->_field_label = $field_details;
376 return $field_details;
377 }
378
379 public function getUploadFields()
380 {
381 if (!is_null($this->_has_upload)) {
382 return $this->_has_upload;
383 }
384 $upload_fields = [];
385 $form_field_details = $this->getFields();
386 foreach ($form_field_details as $field_name => $__field_detail) {
387 if (isset($__field_detail['type']) && ('file-up' === $__field_detail['type'] || 'advanced-file-up' === $__field_detail['type'])) {
388 $upload_fields[] = $field_name;
389 }
390 }
391 $this->_has_upload = $upload_fields;
392 return $upload_fields;
393 }
394
395 public function getSignatureFilePath($blobLink, $form_id, $entry_id, $imgType)
396 {
397 $imgTypes = [
398 'image/png' => 'png',
399 'image/jpeg' => 'jpg',
400 'image/svg+xml' => 'svg',
401 ];
402 $data_uri = $blobLink;
403 $encoded_image = explode(',', $data_uri)[1];
404 $decoded_image = base64_decode($encoded_image);
405 $_upload_dir = BITFORMS_UPLOAD_DIR . DIRECTORY_SEPARATOR . $form_id . DIRECTORY_SEPARATOR . $entry_id;
406
407 wp_mkdir_p($_upload_dir);
408
409 $filename = "{$entry_id}-" . time() . ".{$imgTypes[$imgType]}";
410 $fullPath = $_upload_dir . DIRECTORY_SEPARATOR . $filename;
411 file_put_contents($fullPath, $decoded_image);
412
413 return $filename;
414 }
415
416 private function entryInsert($user_details)
417 {
418 $formEntryModel = new FormEntryModel();
419 $entryId = $formEntryModel->insert(
420 [
421 'form_id' => $this->form_id,
422 'user_id' => $user_details['id'],
423 'user_ip' => $user_details['ip'],
424 'user_device' => $user_details['device'],
425 'referer' => $user_details['page'],
426 'status' => $this->_saveFormAsDraft ? 9 : 1,
427 'created_at' => $user_details['time'],
428 ]
429 );
430 return $entryId;
431 }
432
433 private function submisionLog($user_details, $entry_id, $type)
434 {
435 $formEntryLogModel = new FormEntryLogModel();
436 $submissionLogData = [
437 'user_id' => $user_details['id'],
438 'action_type' => $type, // create, update
439 'log_type' => 'entry',
440 'ip' => $user_details['ip'],
441 'form_entry_id' => $entry_id,
442 'content' => null,
443 'form_id' => $this->form_id,
444 'created_at' => $user_details['time'],
445 ];
446 $submissionLogData = apply_filters('bitform_filter_submission_log_data', $submissionLogData, $this->form_id, $type);
447 $logId = $formEntryLogModel->form_log_insert(
448 $submissionLogData
449 );
450 return $logId;
451 }
452
453 private function isArrayAllKeyInt($InputArray)
454 {
455 if (!is_array($InputArray)) {
456 return false;
457 }
458
459 if (count($InputArray) <= 0) {
460 return true;
461 }
462
463 return array_unique(array_map('is_int', array_keys($InputArray))) === [true];
464 }
465
466 public function formatSubmittedData($submitted_data)
467 {
468 $form_content = $this->getFormContent();
469 $form_fields = $form_content->fields;
470
471 foreach ($submitted_data as $key => $value) {
472 if (!isset($form_fields->{$key})) {
473 continue;
474 }
475 $field_data = $form_fields->{$key};
476 $field_type = $field_data->typ;
477 if ('select' === $field_type && !empty($field_data->config->multipleSelect)) {
478 $valueArr = [];
479 if ($this->isRepeatedField($key)) {
480 foreach ($value as $index => $v) {
481 $valueArr[$index] = explode(BITFORMS_BF_SEPARATOR, $v);
482 }
483 } else {
484 $valueArr = explode(BITFORMS_BF_SEPARATOR, $value);
485 }
486 $submitted_data[$key] = $valueArr;
487 }
488 }
489 $submitted_data = apply_filters('bitform_filter_format_submitted_data', $submitted_data, $this->form_id);
490 return $submitted_data;
491 }
492
493 private function formatRepeateFieldData($submitted_data, $form_fields)
494 {
495 $repeaterFields = $this->getRepeaterFields();
496 foreach ($repeaterFields as $repeaterFldKey => $repeatedFields) {
497 $repeatIndexes = $submitted_data["{$form_fields[$repeaterFldKey]['name']}-repeat-index"];
498 $repeatIndexes = explode(',', $repeatIndexes);
499 foreach ($repeatIndexes as $slNo => $repeatIndex) {
500 foreach ($repeatedFields as $repeatedField) {
501 if (!isset($submitted_data[$repeaterFldKey][$slNo])) {
502 $submitted_data[$repeaterFldKey][$slNo] = [];
503 }
504 $submitted_data[$repeaterFldKey][$slNo][$repeatedField] = $submitted_data[$repeatedField][$repeatIndex];
505 }
506 }
507 foreach ($repeatedFields as $repeatedField) {
508 unset($submitted_data[$repeatedField]);
509 }
510 unset($submitted_data["{$form_fields[$repeaterFldKey]['name']}-repeat-index"]);
511 }
512
513 return $submitted_data;
514 }
515
516 private function saveEntryMeta($submitted_data, $entry_id)
517 {
518 $errorInEntryMetaInsert = false;
519 $entryMeta = new FormEntryMetaModel();
520 foreach ($submitted_data as $key => $value) {
521 $value = $submitted_data[$key];
522 if (is_string($value)) {
523 $value = wp_unslash($value);
524 } elseif ($this->isArrayAllKeyInt($value)) {
525 $value = wp_json_encode(array_values($value));
526 } else {
527 $value = wp_json_encode($value);
528 }
529 $status = $entryMeta->insert(
530 [
531 'bitforms_form_entry_id' => $entry_id,
532 'meta_key' => $key,
533 'meta_value' => $value,
534 ]
535 );
536 if (is_wp_error($status)) {
537 $errorInEntryMetaInsert = true;
538 break;
539 }
540 }
541 return $errorInEntryMetaInsert;
542 }
543
544 public function setSaveFormAsDraft()
545 {
546 $this->_saveFormAsDraft = true;
547 }
548
549 public function saveFormEntry($submitted_data)
550 {
551 $submitted_data = $this->formatSubmittedData($submitted_data);
552 $submitted_data = apply_filters('bitform_filter_save_form_entry', $submitted_data, $this->form_id);
553 $form_content = \json_decode(static::$form[0]->form_content);
554 do_action('bitform_save_entry', $this, $submitted_data, $this->form_id);
555 $key = null;
556 $ipTool = new IpTool();
557 $fileHandler = new FileHandler();
558 $form_fields = $this->getFields();
559 $file_fields = $this->getUploadFields();
560
561 foreach ($_FILES as $file_name => $file_details) {
562 if ($file_fields && in_array($file_name, $file_fields)) {
563 $validation = $fileHandler->validation($file_name, $file_details, $this->form_id);
564 if (!empty($validation['error_type']) && !empty($validation['message'])) {
565 return new WP_Error($validation['error_type'], __($validation['message'], 'bit-form'));
566 }
567 }
568 }
569 $user_details = $ipTool->getUserDetail();
570 $user_details = apply_filters('bitform_filter_user_details', $user_details, $this->form_id);
571 $user_details = apply_filters('bitform_filter_save_entry_user_details', $user_details, $this->form_id);
572
573 $form_fields = $this->getFields();
574 $submitted_data = $this->passwordEncrypted($submitted_data, $form_fields);
575 $submitted_data = $this->formatRepeateFieldData($submitted_data, $form_fields);
576 global $wpdb;
577 $wpdb->query('START TRANSACTION');
578 $entry_id = $this->entryInsert($user_details);
579 $log_id = null;
580
581 $GLOBALS['bf_entry_id'] = $entry_id;
582
583 if (is_wp_error($entry_id)) {
584 return new WP_Error('insert_error', __('Sorry, Error occurred in saving form entry', 'bit-form'));
585 }
586 if ($entry_id) {
587 $log_id = $this->submisionLog($user_details, $entry_id, 'create', $key);
588 if (is_wp_error($log_id)) {
589 $wpdb->query('ROLLBACK');
590 return new WP_Error('error_entry_log', __('Sorry, error occurred in logging form entry', 'bit-form'));
591 }
592 }
593 if ($entry_id) {
594 $submitted_fields = $this->getFormContentWithValue($submitted_data)->fields;
595 $workFlowRunHelper = new WorkFlow($this->form_id);
596
597 $workFlowreturnedOnSubmit = $workFlowRunHelper->executeOnSubmit(
598 'create',
599 $submitted_fields,
600 $submitted_data,
601 $entry_id,
602 $log_id
603 );
604
605 if (!empty($workFlowreturnedOnSubmit['fields'])) {
606 $submitted_data = $workFlowreturnedOnSubmit['fields'];
607 }
608
609 $file_fields = $this->getUploadFields();
610 $formFields = $this->getFields();
611 $submitted_data = FileHandler::tempDirToUploadDir($submitted_data, $formFields, $this->form_id, $entry_id);
612 $fileHandler = new FileHandler();
613 foreach ($_FILES as $file_name => $file_details) {
614 if ($file_fields && in_array($file_name, $file_fields)) {
615 $filePath = [];
616 $repeaterFldKey = $this->isRepeatedField($file_name);
617 if ($repeaterFldKey) {
618 foreach ($file_details['name'] as $slNo => $fileName) {
619 $repeateFileDetails = [
620 'name' => $file_details['name'][$slNo],
621 'type' => $file_details['type'][$slNo],
622 'tmp_name' => $file_details['tmp_name'][$slNo],
623 'error' => $file_details['error'][$slNo],
624 'size' => $file_details['size'][$slNo],
625 ];
626 $filePath = $fileHandler->moveUploadedFiles($repeateFileDetails, $this->form_id, $entry_id);
627 if (!empty($filePath)) {
628 $submitted_data[$repeaterFldKey][$slNo - 1][$file_name] = $filePath;
629 }
630 }
631 } else {
632 $filePath = $fileHandler->moveUploadedFiles($file_details, $this->form_id, $entry_id);
633 if (!empty($filePath)) {
634 $submitted_data[$file_name] = $filePath;
635 }
636 }
637 }
638 }
639
640 /* ======== for Signature field ===========*/
641 foreach ($form_content->fields as $key => $field) {
642 if ('signature' === $field->typ) {
643 $fld_data = $submitted_data[$key];
644 $img_type = $field->config->imgTyp;
645 $submitted_data[$key] = $this->getSignatureFilePath($fld_data, $this->form_id, $entry_id, $img_type);
646 break;
647 }
648 }
649
650 if (!isset($form_content->additional->enabled->submission)) {
651 $errorInEntryMetaInsert = $this->saveEntryMeta($submitted_data, $entry_id);
652 if ($errorInEntryMetaInsert) {
653 do_action('bitform_save_entry_error', $this, $submitted_data, $this->form_id);
654 $wpdb->query('ROLLBACK');
655 return new WP_Error('insert_error', __('Sorry, Error occured in saving form entry data', 'bit-form'));
656 }
657 do_action('bitform_after_save_entry_success', $this, $submitted_data, $entry_id);
658 } else {
659 $wpdb->query('ROLLBACK');
660 }
661 $wpdb->query('COMMIT');
662 $this->setSubmissionCount();
663 $workFlowreturnedOnSubmit['entry_id'] = $entry_id;
664 $workFlowreturnedOnSubmit['fields'] = $submitted_data;
665 $workFlowreturnedOnSubmit = apply_filters('bitform_filter_return_submit_success', $workFlowreturnedOnSubmit, $this->form_id);
666
667 return $workFlowreturnedOnSubmit;
668 }
669 }
670
671 public function passwordEncrypted($updatedValue, $form_fields)
672 {
673 $integrationHandler = new IntegrationHandler($this->form_id);
674 $formIntegrations = $integrationHandler->getAllIntegration('wp_user_auth', 'wp_auth', 1);
675 if (!isset($formIntegrations->errors['result_empty'])) {
676 foreach ($form_fields as $field) {
677 if (array_key_exists($field['key'], $updatedValue) && 'password' === $field['type']) {
678 $updatedValue[$field['key']] = '**** (encrypted)';
679 }
680 }
681 }
682 return $updatedValue;
683 }
684
685 public function updateFormEntry($updatedValue, $formID, $entryID)
686 {
687 $updatedValue = $this->formatSubmittedData($updatedValue);
688 $updatedValue = apply_filters('bitform_filter_update_form_entry', $updatedValue, $this->form_id);
689 do_action('bitform_update_entry', $this, $updatedValue, $formID, $entryID);
690 $formEntryModel = new FormEntryModel();
691 $formEntryLogModel = new FormEntryLogModel();
692 $formOldData = $formEntryLogModel->get_form_value($entryID);
693 $key = null;
694 $entryMeta = new FormEntryMetaModel();
695 $ipTool = new IpTool();
696 $user_details = $ipTool->getUserDetail();
697 $user_details = apply_filters('bitform_filter_user_details', $user_details, $this->form_id);
698 $user_details = apply_filters('bitform_filter_update_entry_user_details', $user_details, $this->form_id);
699
700 $form_fields = $this->getFields();
701
702 $updatedValue = $this->passwordEncrypted($updatedValue, $form_fields);
703 $updatedValue = $this->formatRepeateFieldData($updatedValue, $form_fields);
704 $field_map = [];
705 foreach ($formOldData as $index => $data) {
706 foreach ($form_fields as $field_key => $field) {
707 if ($data->meta_key === $field['key']) {
708 $field_map[$field_key] = $field['key'];
709 }
710 }
711 }
712 $oldEntry = $formEntryModel->get('status', ['id' => $entryID])[0];
713 $formEntry = $formEntryModel->update(
714 [
715 'user_id' => $user_details['id'],
716 'user_ip' => $user_details['ip'],
717 'user_device' => $user_details['device'],
718 'status' => ('9' === $oldEntry->status && !$this->_saveFormAsDraft) ? 1 : $oldEntry->status,
719 'updated_at' => $user_details['time'],
720 ],
721 [
722 'form_id' => $formID,
723 'id' => $entryID,
724 ]
725 );
726 $log_id = null;
727 if ($formEntry) {
728 $log_id = $this->submisionLog($user_details, $entryID, 'update');
729 }
730
731 if (is_wp_error($formEntry) || !$formEntry) {
732 return new WP_Error('empty_form', __('provided form entries does not exists', 'bit-form'));
733 }
734 $formFields = $this->getFields();
735 $updatedValue = FileHandler::tempDirToUploadDir($updatedValue, $formFields, $this->form_id, $entryID);
736 $file_fields = $this->getUploadFields();
737 if (count($file_fields) > 0) {
738 $fileHandler = new FileHandler();
739 foreach ($_FILES as $file_name => $file_details) {
740 if ($file_fields && in_array($file_name, $file_fields)) {
741 $validation = $fileHandler->validation($file_name, $file_details, $this->form_id);
742 if (!empty($validation['error_type']) && !empty($validation['message'])) {
743 return new WP_Error($validation['error_type'], __($validation['message'], 'bit-form'));
744 }
745 }
746 }
747 foreach ($file_fields as $field_name) {
748 if (isset($updatedValue[$field_name . '_old'])) {
749 $file_exists = $entryMeta->get(
750 'meta_value',
751 [
752 'bitforms_form_entry_id' => $entryID,
753 'meta_key' => $field_name,
754 ]
755 );
756 if (!is_wp_error($file_exists) && count($file_exists) > 0) {
757 $files_in_db = json_decode($file_exists[0]->meta_value);
758 $files_old = empty($updatedValue[$field_name . '_old']) ? [] : explode(',', $updatedValue[$field_name . '_old']);
759 $deleted_file = array_diff($files_in_db, $files_old);
760 if (count($deleted_file) > 0) {
761 $fileHandler->deleteFiles($formID, $entryID, $deleted_file);
762 }
763 $updatedValue[$field_name] = wp_json_encode($files_old);
764 }
765 }
766 if (!empty($_FILES[$field_name]['name'])) {
767 $repeaterFldKey = $this->isRepeatedField($field_name);
768 if ($repeaterFldKey) {
769 $file_details = $_FILES[$field_name];
770 foreach ($file_details['name'] as $index => $file) {
771 $repeateFileDetails = [
772 'name' => $file_details['name'][$index],
773 'type' => $file_details['type'][$index],
774 'tmp_name' => $file_details['tmp_name'][$index],
775 'error' => $file_details['error'][$index],
776 'size' => $file_details['size'][$index],
777 ];
778 $meta_value = $fileHandler->moveUploadedFiles($repeateFileDetails, $formID, $entryID, $index);
779 if (!empty($meta_value)) {
780 $updatedValue[$repeaterFldKey][$index - 1][$field_name] = wp_json_encode($meta_value);
781 }
782 }
783 } else {
784 $meta_value = $fileHandler->moveUploadedFiles($_FILES[$field_name], $formID, $entryID);
785 if (!empty($meta_value)) {
786 if (isset($updatedValue[$field_name . '_old']) && !is_wp_error($file_exists) && count($file_exists) > 0) {
787 $meta_value = empty($files_old) ? $meta_value : array_merge($meta_value, $files_old);
788 $updatedValue[$field_name] = wp_json_encode($meta_value);
789 } else {
790 $updatedValue[$field_name] = wp_json_encode($meta_value);
791 }
792 }
793 }
794 }
795 }
796 }
797
798 unset($updatedValue['_ajax_nonce'], $_REQUEST['g-recaptcha-response']);
799
800 $workFlowRunHelper = new WorkFlow($formID);
801 $workFlowreturnedOnSubmit = $workFlowRunHelper->executeOnSubmit(
802 'edit',
803 $this->getFormContentWithValue($updatedValue)->fields,
804 $updatedValue,
805 $entryID,
806 $log_id
807 );
808 if (!empty($workFlowreturnedOnSubmit['fields'])) {
809 $updatedValue = $workFlowreturnedOnSubmit['fields'];
810 }
811
812 $toUpdateValues = [];
813 foreach ($form_fields as $field) {
814 if (isset($updatedValue[$field['key']])) {
815 $toUpdateValues[$field['key']] = $updatedValue[$field['key']];
816 }
817 }
818 $form_content = \json_decode(static::$form[0]->form_content);
819
820 foreach ($form_content->fields as $key => $field) {
821 if ('signature' === $field->typ) {
822 $fld_data = $updatedValue[$key];
823 $img_type = $field->config->imgTyp;
824 $toUpdateValues[$key] = $this->getSignatureFilePath($fld_data, $this->form_id, $entryID, $img_type);
825 break;
826 }
827 }
828
829 $formEntryMetaUpdateStatus = $entryMeta->update(
830 $toUpdateValues,
831 [
832 'bitforms_form_entry_id' => $entryID,
833 ]
834 );
835 if (is_wp_error($formEntryMetaUpdateStatus) || isset($newFileInsertStatus) && is_wp_error($newFileInsertStatus)) {
836 do_action('bitform_update_entry_error', $this, $toUpdateValues, $formEntryMetaUpdateStatus, $this->form_id);
837 return $formEntryMetaUpdateStatus;
838 }
839 $toUpdateValues = array_merge($formEntryMetaUpdateStatus, ['entry_id' => $entryID]);
840 do_action('bitform_after_update_entry_success', $this, $toUpdateValues, $formID, $entryID);
841 if (empty($workFlowreturnedOnSubmit['message'])) {
842 $workFlowreturnedOnSubmit['message'] = __('Entry Updated Successfully', 'bit-form');
843 }
844 $customFieldHandler = new CustomFieldHandler();
845 $toUpdateValues = $customFieldHandler->updatedData($form_fields, $toUpdateValues);
846
847 $workFlowreturnedOnSubmit['updatedData'] = $toUpdateValues;
848 $counter = 0;
849 for ($i = 0; $i < count($formOldData); $i++) {
850 if (array_key_exists($formOldData[$i]->meta_key . '_old', $toUpdateValues)) {
851 unset($toUpdateValues[$formOldData[$i]->meta_key . '_old']);
852 }
853 if (in_array($formOldData[$i]->meta_key, $file_fields)) {
854 if (
855 empty($_FILES[$formOldData[$i]->meta_key]['name'])
856 || (is_array($_FILES[$formOldData[$i]->meta_key]['name'])
857 && 1 === count($_FILES[$formOldData[$i]->meta_key]['name'])
858 && empty($_FILES[$formOldData[$i]->meta_key]['name'][0]))
859 ) {
860 unset($toUpdateValues[$formOldData[$i]->meta_key]);
861 continue;
862 }
863 if (is_array($_FILES[$formOldData[$i]->meta_key]['name']) && !in_array($_FILES[$formOldData[$i]->meta_key]['name'], json_decode($formOldData[$i]->meta_value))) {
864 $key[$i] = '${' . $formOldData[$i]->meta_key . '} file was Updated To ' . wp_json_encode($_FILES[$formOldData[$i]->meta_key]['name']);
865 } elseif (!is_array($_FILES[$formOldData[$i]->meta_key]['name']) && !in_array($_FILES[$formOldData[$i]->meta_key]['name'], json_decode($formOldData[$i]->meta_value))) {
866 $key[$i] = '${' . $formOldData[$i]->meta_key . '} file was Updated To ' . $_FILES[$formOldData[$i]->meta_key]['name'];
867 }
868 unset($toUpdateValues[$formOldData[$i]->meta_key]);
869 } elseif (isset($toUpdateValues[$formOldData[$i]->meta_key])) {
870 if (is_array($toUpdateValues[$formOldData[$i]->meta_key])) {
871 if (json_decode($formOldData[$i]->meta_value) !== $toUpdateValues[$formOldData[$i]->meta_key]) {
872 $key[$i] = '${' . $formOldData[$i]->meta_key . '} was Updated From ' . implode(',', json_decode($formOldData[$i]->meta_value)) . ' To ' . implode(',', $toUpdateValues[$formOldData[$i]->meta_key]);
873 }
874 } elseif (is_string($toUpdateValues[$formOldData[$i]->meta_key]) && !FieldValueHandler::isEmpty($toUpdateValues[$formOldData[$i]->meta_key])) {
875 if ($formOldData[$i]->meta_value !== $toUpdateValues[$formOldData[$i]->meta_key]) {
876 $key[$i] = '${' . $formOldData[$i]->meta_key . '} was Updated' . ($formOldData[$i]->meta_value ? ' From ' . $formOldData[$i]->meta_value : '') . ' To ' . $toUpdateValues[$formOldData[$i]->meta_key];
877 }
878 }
879 }
880 $counter++;
881 }
882
883 $newField = array_keys(array_diff_key($formEntryMetaUpdateStatus, $field_map));
884 for ($i = 0; $i < count($newField); $i++) {
885 if (is_array($toUpdateValues[$newField[$i]]) && !empty($toUpdateValues[$newField[$i]])) {
886 $key[$counter + $i] = '${' . $newField[$i] . '} Updated To ' . implode(',', $toUpdateValues[$newField[$i]]);
887 } elseif (is_string($newField[$i]) && !FieldValueHandler::isEmpty($toUpdateValues[$newField[$i]])) {
888 $key[$counter + $i] = '${' . $newField[$i] . '} Updated To ' . $toUpdateValues[$newField[$i]];
889 }
890 }
891 if (null !== $key) {
892 $logUpdate = implode('b::f', (array) $key);
893 $formEntryLogUpdate = $formEntryLogModel->logUpdate($logUpdate, $log_id);
894 }
895 $workFlowreturnedOnSubmit['entry_id'] = $entryID;
896 $workFlowreturnedOnSubmit = apply_filters('bitform_filter_return_edit_success', $workFlowreturnedOnSubmit, $this->form_id);
897
898 return $workFlowreturnedOnSubmit;
899 }
900
901 public function getRepeaterFields()
902 {
903 if (!is_null($this->_repeaterFields)) {
904 return $this->_repeaterFields;
905 }
906 $repeaterFields = [];
907 $form_content = \json_decode(static::$form[0]->form_content);
908 $fields = $form_content->fields;
909 $nestedLayouts = !empty($form_content->nestedLayout) ? $form_content->nestedLayout : [];
910 foreach ($nestedLayouts as $fieldKey => $repeatLayout) {
911 if ('repeater' !== $fields->{$fieldKey}->typ) {
912 continue;
913 }
914 $repeaterFields[$fieldKey] = [];
915 foreach ($repeatLayout->lg as $fieldLayoutData) {
916 $repeaterFields[$fieldKey][] = $fieldLayoutData->i;
917 }
918 }
919 $this->_repeaterFields = $repeaterFields;
920 return $repeaterFields;
921 }
922
923 public function isRepeatedField($fieldKey)
924 {
925 $repeatedFields = $this->getRepeaterFields();
926 foreach ($repeatedFields as $repeaterKey => $repeaterFields) {
927 if (in_array($fieldKey, $repeaterFields)) {
928 return $repeaterKey;
929 }
930 }
931 return false;
932 }
933
934 public function fieldNameReplaceOfPost()
935 {
936 $fields = $this->getFields();
937 foreach ($fields as $fieldKey => $fieldData) {
938 if (array_key_exists('name', $fieldData)) {
939 $fldName = $fieldData['name'];
940 $fldName = str_replace(['.', ' '], '_', $fldName);
941 if (array_key_exists($fldName, $_POST)) {
942 $temp = $_POST[$fldName];
943 unset($_POST[$fldName]);
944 $_POST[$fieldKey] = $temp;
945 } elseif (array_key_exists($fldName, $_FILES)) {
946 $temp = $_FILES[$fldName];
947 unset($_FILES[$fldName]);
948 $_FILES[$fieldKey] = $temp;
949 }
950 }
951 }
952 }
953
954 public function setSubmissionCount($countStep = 1)
955 {
956 $update_status = $this->formModel->update(
957 [
958 'entries' => intval(static::$form[0]->entries) + $countStep,
959 ],
960 [
961 'id' => $this->form_id,
962 ]
963 );
964 }
965
966 public function resetSubmissionCount($countStep)
967 {
968 $update_status = $this->formModel->update(
969 [
970 'entries' => intval($countStep),
971 ],
972 [
973 'id' => $this->form_id,
974 ]
975 );
976 }
977
978 public function getCaptchaSettings()
979 {
980 $formContents = $this->getFormContent();
981 $fieldStr = wp_json_encode($formContents->fields);
982 if (false !== strpos($fieldStr, '"typ":"recaptcha"')) {
983 return true;
984 }
985 }
986
987 public function getTurnstileSettings()
988 {
989 $formContents = $this->getFormContent();
990 $fieldStr = wp_json_encode($formContents->fields);
991 if (false !== strpos($fieldStr, '"typ":"turnstile"')) {
992 return true;
993 }
994 }
995
996 public function getCaptchaV3Settings()
997 {
998 $formContents = $this->getFormContent();
999 if (!empty($formContents->additional->enabled) && !empty($formContents->additional->enabled->recaptchav3)) {
1000 return $formContents->additional->settings->recaptchav3;
1001 }
1002 return false;
1003 }
1004
1005 // public function getSuccessMessageMarkups() {
1006 // if (is_null($this->_work_flows)) {
1007 // $workFlowManager = new WorkFlowHandler($this->form_id);
1008 // $this->_work_flows = $workFlowManager->getAllworkFlow();
1009 // }
1010
1011 // $ids = [];
1012 // foreach ($this->_work_flows as $msgItem) {
1013 // foreach ($msgItem['conditions'] as $condition) {
1014 // if (isset($condition->actions->success)) {
1015 // foreach ($condition->actions->success as $msg) {
1016 // if ('successMsg' === $msg->type && isset($msg->details->id)) {
1017 // $msgDetailsId = $msg->details->id;
1018 // $idObj = json_decode(stripslashes($msgDetailsId));
1019 // if (is_object($idObj) && !empty($idObj->id)) {
1020 // array_push($ids, $idObj->id);
1021 // }
1022 // }
1023 // }
1024 // }
1025 // if (isset($condition->actions->failure)) {
1026 // $idObj = json_decode(stripslashes($condition->actions->failure));
1027 // if (is_object($idObj) && !empty($idObj->id)) {
1028 // array_push($ids, $idObj->id);
1029 // }
1030 // }
1031 // }
1032 // }
1033 // $ids = array_unique($ids);
1034 // if (is_null($this->_conf_messages)) {
1035 // $successMsgHandler = new SuccessMessageHandler($this->form_id);
1036 // $this->_conf_messages = $successMsgHandler->getMessages($ids);
1037 // }
1038
1039 // $messageMarkups = '';
1040 // if (is_wp_error($this->_conf_messages)) {
1041 // return $messageMarkups;
1042 // }
1043
1044 // foreach ($this->_conf_messages as $key => $msgItem) {
1045 // $messageMarkups .= $this->messageMarkup($msgItem->id);
1046 // }
1047
1048 // return $messageMarkups;
1049 // }
1050
1051 // private function messageMarkup($msgId) {
1052 // return <<<SUCCESSMSG
1053 // <div role="dialog" aria-hidden="true" data-modal-backdrop="true" class="{$this->getAtomicCls("msg-container-{$msgId}")} deactive2 test">
1054 // <div role="button" class="{$this->getAtomicCls("msg-background-{$msgId}")} msg-backdrop">
1055 // <div class="bf-notification-message {$this->getAtomicCls("msg-content-{$msgId}")}">
1056 // <button class="{$this->getAtomicCls("close-{$msgId}")} bf-msg-close" type="button">
1057 // <svg class="{$this->getAtomicCls("close-icn-{$msgId}")}" viewBox="0 0 30 30">
1058 // <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" x1="4" y1="3.88" x2="26" y2="26.12"></line>
1059 // <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" x1="26" y1="3.88" x2="4" y2="26.12"></line>
1060 // </svg>
1061 // </button>
1062 // <div class="msg-content"></div>
1063 // </div>
1064 // </div>
1065 // </div>
1066 // SUCCESSMSG;
1067 // }
1068
1069 public function getAtomicCls($element)
1070 {
1071 $atomicClassMap = $this->getAtomicClsMap();
1072 if (is_object($atomicClassMap) && property_exists($atomicClassMap, ".$element")) {
1073 $getAtomicCls = $atomicClassMap->{".$element"};
1074 return implode(' ', $getAtomicCls) . " $element";
1075 }
1076 return $element;
1077 }
1078
1079 public function isGCLIDEnabled()
1080 {
1081 $formContents = $this->getFormContent();
1082 if (isset($formContents->additional->enabled->captureGCLID) && $formContents->additional->enabled->captureGCLID) {
1083 return true;
1084 }
1085 return false;
1086 }
1087
1088 protected function addEntryInfo($field_details, $counter)
1089 {
1090 $infos = [
1091 '__user_id' => __('User'),
1092 '__entry_status' => __('Status'),
1093 //'__user_location' => __(''),
1094 '__referer' => __('Refer URL'),
1095 '__user_device' => __('Device'),
1096 '__user_ip' => __('IP address'),
1097 '__created_at' => __('Created Time'),
1098 '__updated_at' => __('Modified Time'),
1099 ];
1100 foreach ($infos as $key => $value) {
1101 $field_details[$counter]['name'] = $value;
1102 $field_details[$counter]['key'] = $key;
1103 $field_details[$counter]['type'] = 'sys';
1104 $counter = $counter + 1;
1105 }
1106
1107 return $field_details;
1108 }
1109 }
1110