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/Core/Database/FormEntryMetaModel.php +307 -164 2.02.21.4 View file →
@@ -5,25 +5,30 @@
5 5 */
6 6
7 7 namespace BitCode\BitForm\Core\Database;
8 8
9 +use BitCode\BitForm\Core\Util\FileHandler;
10 +
9 11 /**
10 12 * Undocumented class
11 13 */
12 14
13 -class FormEntryMetaModel extends Model {
15 +class FormEntryMetaModel extends Model
16 +{
14 17 protected static $table = 'bitforms_form_entrymeta';
15 18
16 - public function duplicateEntryMeta($data) {
19 + public function duplicateEntryMeta($data)
20 + {
17 21 $values[] = $data['duplicateID'];
18 22 $values[] = $data['entryID'];
19 23 $sql = "INSERT INTO $this->table_name (bitforms_form_entry_id,meta_key,meta_value)"
20 - . ' SELECT %d as bitforms_form_entry_id,meta_key,meta_value'
21 - . " FROM `$this->table_name` WHERE bitforms_form_entry_id = %d";
24 + . ' SELECT %d as bitforms_form_entry_id,meta_key,meta_value'
25 + . " FROM `$this->table_name` WHERE bitforms_form_entry_id = %d";
22 26 return $this->execute($sql, $values)->getResult();
23 27 }
24 28
25 - public function update(array $data, array $condition) {
29 + public function update(array $data, array $condition)
30 + {
26 31 $entryID = $condition['bitforms_form_entry_id'];
27 32 if (empty($entryID)) {
28 33 return false;
29 34 }
@@ -43,10 +48,10 @@
43 48 $updatedData = [];
44 49 $oldEntriesKey = array_keys($oldEntries);
45 50 foreach ($data as $upKey => $upValue) {
46 51 $updatedData[$upKey] = is_string($upValue) ?
47 - $upValue :
48 - wp_json_encode($upValue);
52 + $upValue :
53 + wp_json_encode($upValue);
49 54 if (!\in_array($upKey, $oldEntriesKey)) {
50 55 $this->insert(
51 56 [
52 57 'bitforms_form_entry_id' => $entryID,
@@ -93,9 +98,10 @@
93 98 }
94 99 return $updatedData;
95 100 }
96 101
97 - public function validQueryCondition($conditions) {
102 + public function validQueryCondition($conditions)
103 + {
98 104 foreach ($conditions as $index => $condition) {
99 105 if (is_object($condition)) {
100 106 if (empty($condition->field) || empty($condition->logic) || empty($condition->val) && !in_array($condition->val, ['0', 0, 0.0], true)) {
101 107 unset($conditions[$index], $conditions[$index + 1]);
@@ -104,9 +110,10 @@
104 110 }
105 111 return $conditions;
106 112 }
107 113
108 - public function sqlQryGenerateByFldCondition($conditions) {
114 + public function sqlQryGenerateByFldCondition($conditions)
115 + {
109 116 $dbHelper = new Helper();
110 117 $sql = '';
111 118
112 119 $dateQuery = $dbHelper->dateQueryList();
@@ -121,10 +128,9 @@
121 128 $value = $dbHelper->strValueModifyByLogic($condition->logic, $condition->val);
122 129 }
123 130
124 131 $operator = $dbHelper->convertToSqlOperator($condition->logic);
125 -
126 - if (isset($dateQuery[$condition->val])) {
132 + if (!is_array($condition->val) && isset($dateQuery[$condition->val])) {
127 133 $sql .= $dbHelper->fieldQueryByDate($condition->field, $operator, $value, $condition->logic);
128 134 } else {
129 135 if (!is_int($value)) {
130 136 $value = "'" . $value . "'";
@@ -139,9 +145,10 @@
139 145
140 146 return trim($sql);
141 147 }
142 148
143 - public function queryRecount($selectedMeta, $groupedCondition, $orderCondition, $all_values) {
149 + public function queryRecount($selectedMeta, $groupedCondition, $orderCondition, $all_values)
150 + {
144 151 $entry_table = $this->app_db->prefix . 'bitforms_form_entries';
145 152 $sql = 'SELECT count(*) as count FROM (';
146 153 $sql .= "SELECT $selectedMeta FROM `$this->table_name` em";
147 154 $sql .= " INNER JOIN $entry_table e on e.id = em.bitforms_form_entry_id ";
@@ -150,9 +157,10 @@
150 157 $countResult = $this->execute($sql, $all_values)->getResult();
151 158 return $countResult[0]->count;
152 159 }
153 160
154 - public function selectedEntryMeta($formFields, $fieldCount) {
161 + public function selectedEntryMeta($formFields, $fieldCount)
162 + {
155 163 $all_values = [];
156 164 $formFieldsNames = [];
157 165 $metaChecker = 0;
158 166 $selectedMeta = '`bitforms_form_entry_id` as entry_id,';
@@ -185,13 +193,13 @@
185 193 $selectedMeta .= ',';
186 194 }
187 195 //#unused code commented by me##
188 196 // if ( !empty( $filter['global'] ) ) {
189 - // $globalFilterString .= " `" . $fieldDetails['key'] . "` LIKE '%%" . $this->getFieldFormat( $filter['global'] ) . "%%' ";
190 - // if ( $metaChecker < $fieldCount ) {
191 - // $globalFilterString .= " OR ";
192 - // }
193 - // $globalFilterValues[] = $filter['global'];
197 + // $globalFilterString .= " `" . $fieldDetails['key'] . "` LIKE '%%" . $this->getFieldFormat( $filter['global'] ) . "%%' ";
198 + // if ( $metaChecker < $fieldCount ) {
199 + // $globalFilterString .= " OR ";
200 + // }
201 + // $globalFilterValues[] = $filter['global'];
194 202 // }
195 203 }
196 204
197 205 return [
@@ -200,9 +208,10 @@
200 208 'all_values' => $all_values,
201 209 ];
202 210 }
203 211
204 - public function groupedCondition($condition, $all_values, $fieldConditions) {
212 + public function groupedCondition($condition, $all_values, $fieldConditions)
213 + {
205 214 $isFldCondition = false;
206 215 $formattedCondition = $this->getFormatedCondition($condition);
207 216 if ($formattedCondition) {
208 217 $groupedCondition = $formattedCondition['conditions'] . 'GROUP BY
@@ -214,40 +223,40 @@
214 223 //#unused code commented by me##
215 224 //$isRecount = false;
216 225
217 226 // if ( !empty( $filter['field'] ) ) {
218 - // $isRecount = true;
219 - // $filterFieldCount = count( $filter['field'] );
220 - // $filterFieldChecker = 0;
221 - // if ( $filterFieldCount > 0 ) {
222 - // $groupedCondition .= " HAVING ";
223 - // }
224 - // foreach ( $filter['field'] as $filterFieldKey => $filterFieldDetails ) {
225 - // $groupedCondition .= " `$filterFieldDetails->id` ='%%" . $this->getFieldFormat( $filterFieldDetails->value ) . "%%'";
226 - // $all_values[] = $filterFieldDetails->value;
227 - // if ( $filterFieldChecker < $filterFieldCount ) {
228 - // $groupedCondition .= " AND ";
229 - // }
230 - // }
227 + // $isRecount = true;
228 + // $filterFieldCount = count( $filter['field'] );
229 + // $filterFieldChecker = 0;
230 + // if ( $filterFieldCount > 0 ) {
231 + // $groupedCondition .= " HAVING ";
232 + // }
233 + // foreach ( $filter['field'] as $filterFieldKey => $filterFieldDetails ) {
234 + // $groupedCondition .= " `$filterFieldDetails->id` ='%%" . $this->getFieldFormat( $filterFieldDetails->value ) . "%%'";
235 + // $all_values[] = $filterFieldDetails->value;
236 + // if ( $filterFieldChecker < $filterFieldCount ) {
237 + // $groupedCondition .= " AND ";
238 + // }
239 + // }
231 240 // }
232 241
233 242 // if ( !empty( $filter['global'] ) && !empty( $globalFilterString ) && !empty( $globalFilterValues ) ) {
234 - // $isRecount = true;
235 - // if ( !empty( $filter['field'] ) ) {
236 - // $groupedCondition .= " AND (" . $globalFilterString . ") ";
237 - // } else {
238 - // $groupedCondition .= " HAVING $globalFilterString ";
239 - // }
240 - // $offset = 0;
241 - // $all_values = array_merge( $all_values, $globalFilterValues );
243 + // $isRecount = true;
244 + // if ( !empty( $filter['field'] ) ) {
245 + // $groupedCondition .= " AND (" . $globalFilterString . ") ";
246 + // } else {
247 + // $groupedCondition .= " HAVING $globalFilterString ";
248 + // }
249 + // $offset = 0;
250 + // $all_values = array_merge( $all_values, $globalFilterValues );
242 251 // }
243 252
244 253 // if ( !empty( $dateBetweenFilter ) && !empty( $dateBetweenFilter->start_date ) && !empty( $dateBetweenFilter->end_date ) ) {
245 - // if ( strpos( $groupedCondition, 'HAVING' ) !== false ) {
246 - // $groupedCondition .= " AND `__created_at` BETWEEN '" . $dateBetweenFilter->start_date . "' AND '" . $dateBetweenFilter->end_date . "' ";
247 - // } else {
248 - // $groupedCondition .= " HAVING `__created_at` BETWEEN '" . $dateBetweenFilter->start_date . "' AND '" . $dateBetweenFilter->end_date . "' ";
249 - // }
254 + // if ( strpos( $groupedCondition, 'HAVING' ) !== false ) {
255 + // $groupedCondition .= " AND `__created_at` BETWEEN '" . $dateBetweenFilter->start_date . "' AND '" . $dateBetweenFilter->end_date . "' ";
256 + // } else {
257 + // $groupedCondition .= " HAVING `__created_at` BETWEEN '" . $dateBetweenFilter->start_date . "' AND '" . $dateBetweenFilter->end_date . "' ";
258 + // }
250 259 // }
251 260
252 261 $sqlQryByFldCondtion = $this->sqlQryGenerateByFldCondition($fieldConditions);
253 262
@@ -265,9 +274,10 @@
265 274 'isFldCondition' => $isFldCondition,
266 275 ];
267 276 }
268 277
269 - public function orderCondition($formFieldsNames, $sortBy) {
278 + public function orderCondition($formFieldsNames, $sortBy)
279 + {
270 280 $orderCondition = null;
271 281 if (!empty($sortBy)) {
272 282 $sortableFieldCount = count($sortBy);
273 283 $sortableFieldChecker = 0;
@@ -296,9 +306,10 @@
296 306 $orderCondition .= empty($orderCondition) ? ' ORDER BY `bitforms_form_entry_id` DESC ' : ',`bitforms_form_entry_id` DESC ';
297 307 return $orderCondition;
298 308 }
299 309
300 - public function isEntryMetaExist($conditions) {
310 + public function isEntryMetaExist($conditions)
311 + {
301 312 $existMetaData = $this->get(
302 313 [
303 314 'meta_key',
304 315 'meta_value',
@@ -310,13 +321,13 @@
310 321 }
311 322 return false;
312 323 }
313 324
314 - public function getEntryMeta($formFields, $entries, $limit = null, $offset = null, $filter = null, $sortBy = null, $fieldConditions = null, $dateBetweenFilter = null) {
325 + public function getEntryMeta($formFields, $entries, $limit = null, $offset = null, $filter = null, $sortBy = null, $fieldConditions = null, $dateBetweenFilter = null)
326 + {
315 327 $entry_table = $this->app_db->prefix . 'bitforms_form_entries';
316 328 $fieldCount = count($formFields);
317 329 $getSelectedMetaFldValue = $this->selectedEntryMeta($formFields, $fieldCount);
318 -
319 330 $selectedMeta = $getSelectedMetaFldValue['selected_meta'];
320 331 $formFieldsNames = $getSelectedMetaFldValue['form_fields_names'];
321 332 $all_values = $getSelectedMetaFldValue['all_values'];
322 333 $entryIDs = [];
@@ -324,9 +335,9 @@
324 335 // $paginateEntry = empty($sortBy) && empty($filter['field']) && empty($filter['global']);
325 336 // $entries = $paginateEntry ? array_slice($entries, $offset, $limit) : $entries;
326 337 $paginateEntry = false;
327 338 foreach ($entries as $entryDetail) {
328 - $entryIDs[] = $entryDetail->id;
339 + $entryIDs[] = isset($entryDetail->id) ? $entryDetail->id : $entryDetail;
329 340 }
330 341 if (empty($entryIDs)) {
331 342 return [
332 343 'count' => 0,
@@ -337,9 +348,9 @@
337 348 $group = $this->groupedCondition($condition, $all_values, $fieldConditions);
338 349 $groupedCondition = $group['groupedCondition'];
339 350 $all_values = $group['all_values'];
340 351 $isFldCondition = $group['isFldCondition'];
341 - $orderCondition = $this->orderCondition($formFieldsNames, $sortBy);
352 + $orderCondition = $this->orderCondition($formFieldsNames, (array) $sortBy);
342 353
343 354 $paginate = null;
344 355 if (!\is_null($limit)) {
345 356 $limit = \intval($limit);
@@ -383,144 +394,276 @@
383 394 ];
384 395 return $resultedEntries;
385 396 }
386 397
387 - private function csvInjectionPrevent($value) {
388 - $formula = ['=', '-', '+', '@', "\t", "\r"];
389 - $valueFilter = preg_replace('/[\]["]/i', '', $value);
390 - if (\in_array(substr($value, 0, 1), $formula, true)) {
391 - $valueFilter = "'" . trim($valueFilter);
398 + public function getSingleEntryMeta($formFields, $entryId)
399 + {
400 + $entry_table = $this->app_db->prefix . 'bitforms_form_entries';
401 + $fieldCount = count($formFields);
402 + $getSelectedMetaFldValue = $this->selectedEntryMeta($formFields, $fieldCount);
403 + $selectedMeta = $getSelectedMetaFldValue['selected_meta'];
404 + $formFieldsNames = $getSelectedMetaFldValue['form_fields_names'];
405 + $all_values = $getSelectedMetaFldValue['all_values'];
406 + $condition['bitforms_form_entry_id'] = [$entryId];
407 + $group = $this->groupedCondition($condition, $all_values, []);
408 + $groupedCondition = $group['groupedCondition'];
409 + $all_values = $group['all_values'];
410 + $orderCondition = $this->orderCondition($formFieldsNames, null);
411 + $sql = "SELECT $selectedMeta FROM `$this->table_name` em";
412 + $sql .= " INNER JOIN $entry_table e on e.id = em.bitforms_form_entry_id ";
413 + $sql .= $groupedCondition . $orderCondition;
414 + $result = $this->execute($sql, $all_values)->getResult();
415 +
416 + if (is_wp_error($result)) {
417 + return [];
418 + }
419 + return $result;
420 + }
421 +
422 + private function csvInjectionPrevent($value)
423 + {
424 + $formula = ['=', '-', '+', '@', "\t", "\r"];
425 + $valueFilter = preg_replace('/[\]["]/i', '', $value);
426 + if (\in_array(substr($value, 0, 1), $formula, true)) {
427 + $valueFilter = "'" . trim($valueFilter);
428 + }
429 +
430 + return $valueFilter;
431 + }
432 +
433 + private function unescapeString($str)
434 + {
435 + // return preg_replace_callback(
436 + // '/\\\\u([0-9a-fA-F]{4})/',
437 + // fn ($match) => mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE'),
438 + // $str
439 + // );
440 + if (is_string($str) && '' !== $str) {
441 + // Handle JSON-style escaping
442 + $decoded = json_decode('"' . str_replace('"', '\\"', $str) . '"');
443 + return (null !== $decoded) ? $decoded : $str;
444 + }
445 + return $str;
446 + }
447 +
448 + private function formatRepeaterValue($rawValue, $fieldMap)
449 + {
450 + if (empty($rawValue)) {
451 + return '';
452 + }
453 + $rows = [];
454 + preg_match_all('/\{([^}]+)\}/', $rawValue, $matches);
455 +
456 + foreach ($matches[1] as $row) {
457 + $pairs = explode(',', $row);
458 + $formattedPairs = [];
459 +
460 + foreach ($pairs as $pair) {
461 + if (false === strpos($pair, ':')) {
462 + continue;
463 + }
464 + [$childKey, $value] = explode(':', $pair, 2);
465 + $childKey = trim($childKey);
466 + $value = trim($value);
467 +
468 + // Get label from fieldMap or use key
469 + $label = $fieldMap[$childKey]['adminLbl'] ?? $childKey;
470 + $formattedPairs[] = "$label: " . self::unescapeString($value);
392 471 }
393 472
394 - return $valueFilter;
473 + $rows[] = implode(', ', $formattedPairs);
395 474 }
396 475
397 - public function getExportEntry($formFields, $entries, $formId, $fieldLabels, $limit = null, $sortBy = null, $sortByField = null) {
398 - $entry_table = $this->app_db->prefix . 'bitforms_form_entries';
399 - $selectedEntryMeta = '`bitforms_form_entry_id` as entry_id,';
400 - $selectedEntryMeta .= "e.user_id as '__user_id',";
401 - $selectedEntryMeta .= "e.status as '__entry_status',";
402 - $selectedEntryMeta .= "e.user_ip as '__user_ip',";
403 - $selectedEntryMeta .= "e.user_location as '__user_location',";
404 - $selectedEntryMeta .= "e.user_device as '__user_device',";
405 - $selectedEntryMeta .= "e.referer as '__referer',";
406 - $selectedEntryMeta .= "e.created_at as '__created_at',";
407 - $selectedEntryMeta .= "e.updated_at as '__updated_at',";
408 - $metaChecker = 0;
476 + return implode('; ', $rows);
477 + }
409 478
410 - $entryInfo = ['__user_id', '__user_ip', /* '__user_location', */'__user_device',
411 - '__referer', '__created_at', '__updated_at'];
412 - $all_values = [];
413 - if ([] === $formFields) {
414 - $data = [
415 - 'count' => 0,
416 - 'entries' => [],
417 - ];
418 - wp_send_json_success($data, 200);
479 + public function getExportEntry($formFields, $entries, $formId, $fieldLabels, $limit = null, $sortBy = null, $sortByField = null, $offset = null, $entryConditions = null)
480 + {
481 + $entry_table = $this->app_db->prefix . 'bitforms_form_entries';
482 + $selectedEntryMeta = '`bitforms_form_entry_id` as entry_id,';
483 + $selectedEntryMeta .= 'e.user_id as `__user_id`,';
484 + $selectedEntryMeta .= 'e.status as `__entry_status`,';
485 + $selectedEntryMeta .= 'e.user_ip as `__user_ip`,';
486 + $selectedEntryMeta .= 'e.user_location as `__user_location`,';
487 + $selectedEntryMeta .= 'e.user_device as `__user_device`,';
488 + $selectedEntryMeta .= 'e.referer as `__referer`,';
489 + $selectedEntryMeta .= 'e.created_at as `__created_at`,';
490 + $selectedEntryMeta .= 'e.updated_at as `__updated_at`,';
491 + $metaChecker = 0;
492 +
493 + $entryInfo = [
494 + '__user_id',
495 + '__user_ip', /* '__user_location', */
496 + '__user_device',
497 + '__entry_status',
498 + '__referer',
499 + '__created_at',
500 + '__updated_at'
501 + ];
502 + $all_values = [];
503 + if ([] === $formFields) {
504 + $data = [
505 + 'count' => 0,
506 + 'entries' => [],
507 + ];
508 + wp_send_json_success($data, 200);
509 + }
510 + $fieldCount = count($formFields) - count(array_intersect($formFields, $entryInfo));
511 + $formFieldsNames = [];
512 + foreach ($formFields as $fldKey) {
513 + $formFieldsNames[] = $fldKey;
514 + if (in_array($fldKey, $entryInfo)) {
515 + continue;
419 516 }
420 - $fieldCount = count($formFields) - count(array_intersect($formFields, $entryInfo));
421 - $formFieldsNames = [];
422 - foreach ($formFields as $fldKey) {
423 - $formFieldsNames[] = $fldKey;
424 - if (in_array($fldKey, $entryInfo)) {
425 - continue;
426 - }
427 - $fieldFormat = $this->getFieldFormat($fldKey);
428 - $selectedEntryMeta .= "GROUP_CONCAT(
517 + $fieldFormat = $this->getFieldFormat($fldKey);
518 + $selectedEntryMeta .= "GROUP_CONCAT(
429 519 CASE
430 520 `meta_key`
431 521 WHEN '$fieldFormat' THEN `meta_value`
432 522 END
433 523 ) AS '$fieldFormat'";
434 - $metaChecker += 1;
435 - $all_values[] = $fldKey;
436 - $all_values[] = $fldKey;
437 - if ($metaChecker < $fieldCount) {
438 - $selectedEntryMeta .= ',';
439 - }
524 + $metaChecker += 1;
525 + $all_values[] = $fldKey;
526 + $all_values[] = $fldKey;
527 + if ($metaChecker < $fieldCount) {
528 + $selectedEntryMeta .= ',';
440 529 }
441 - $entryIDs = [];
442 - foreach ($entries as $entryDetail) {
443 - $entryIDs[] = $entryDetail->id;
530 + }
531 + $entryIDs = [];
532 + foreach ($entries as $entryDetail) {
533 + $entryIDs[] = $entryDetail->id;
534 + }
535 + if (empty($entryIDs)) {
536 + return [
537 + 'count' => 0,
538 + 'entries' => [],
539 + ];
540 + }
541 + $condition['bitforms_form_entry_id'] = $entryIDs;
542 + $formattedCondition = $this->getFormatedCondition($condition);
543 + $groupedCondition = null;
544 + $grpCon = $this->groupedCondition($condition, $all_values, $entryConditions);
545 + $groupedCondition = $grpCon['groupedCondition'];
546 + $all_values = $grpCon['all_values'];
547 +
548 + // if ($formattedCondition) {
549 + // $groupedCondition = $formattedCondition['conditions'] . ' GROUP BY
550 + // `bitforms_form_entry_id` ';
551 + // $all_values = array_merge($all_values, $formattedCondition['values']);
552 + // }
553 + $order = 'DESC' === $sortBy ? 'DESC ' : 'ASC ';
554 + $orderField = \is_null($sortByField) ? 'bitforms_form_entry_id' : "`$sortByField`";
555 +
556 + $orderCondition = "ORDER BY $orderField $order ";
557 + // if (!\is_null($limit)) {
558 + // $limitInt = \intval($limit);
559 + // $limit = " LIMIT $limitInt ";
560 + // }
561 + $limitClause = '';
562 + if (!\is_null($limit)) {
563 + $limitInt = \intval($limit);
564 + $limitClause = " LIMIT $limitInt ";
565 + if (!\is_null($offset)) {
566 + $offsetInt = \intval($offset);
567 + $limitClause .= " OFFSET $offsetInt ";
444 568 }
445 - if (empty($entryIDs)) {
446 - return [
447 - 'count' => 0,
448 - 'entries' => [],
449 - ];
569 + }
570 +
571 + $sql = "SELECT $selectedEntryMeta FROM `$this->table_name` em";
572 + $sql .= " INNER JOIN $entry_table e on e.id = em.bitforms_form_entry_id ";
573 + $sql .= $groupedCondition . $orderCondition . $limitClause;
574 + $result = $this->execute($sql, $all_values)->getResult();
575 + $allData = [];
576 + $entry_id = 'entry_id';
577 + $users = get_users(['fields' => ['ID', 'display_name']]);
578 + $userNames = [];
579 + $entryStatus = [
580 + '0' => 'Read',
581 + '1' => 'Unread',
582 + '2' => 'Unconfirmed',
583 + '3' => 'Confirmed',
584 + '9' => 'Draft',
585 + ];
586 + foreach ($users as $key => $value) {
587 + $userNames[$value->ID] = $value->display_name;
588 + }
589 + foreach ($result as $key => $value) {
590 + foreach ($formFieldsNames as $formFieldName) {
591 + $allData[$key]['entry_id'] = preg_replace('/[\]["]/i', '', $value->$entry_id);
592 + if ('__user_id' === $formFieldName && intval($value->$formFieldName) > 0) {
593 + $allData[$key][$formFieldName] = $userNames[$value->$formFieldName];
594 + } elseif ('__user_ip' === $formFieldName) {
595 + $allData[$key][$formFieldName] = long2ip((int) $value->$formFieldName);
596 + } elseif ('__entry_status' === $formFieldName) {
597 + // replace numeric marker for status with actual status text
598 + $allData[$key][$formFieldName] = $entryStatus[$value->{$formFieldName}];
599 + } else {
600 + $allData[$key][$formFieldName] = preg_replace('/[\]["]/i', '', $value->$formFieldName);
601 + }
450 602 }
451 - $condition['bitforms_form_entry_id'] = $entryIDs;
452 - $formattedCondition = $this->getFormatedCondition($condition);
453 - $groupedCondition = null;
454 - if ($formattedCondition) {
455 - $groupedCondition = $formattedCondition['conditions'] . ' GROUP BY
456 - `bitforms_form_entry_id` ';
457 - $all_values = array_merge($all_values, $formattedCondition['values']);
603 + }
604 +
605 + if (is_wp_error($result)) {
606 + wp_send_json_error('Internal server error', 500);
607 + } else {
608 + // Create mappings:
609 + $fieldMap = []; // fieldKey => fieldData
610 + $repeaterFields = []; // repeater fieldKeys
611 + $fileFields = [];
612 + $downloadableFieldType = ['file-up', 'signature', 'advanced-file-up'];
613 +
614 + foreach ($fieldLabels as $field) {
615 + $key = $field['key'];
616 + $fieldMap[$key] = $field;
617 + if ('repeater' === $field['type']) {
618 + $repeaterFields[] = $key;
619 + } elseif (in_array($field['type'], $downloadableFieldType, true)) {
620 + $fileFields[] = $key;
621 + }
458 622 }
459 - $order = \is_null($sortBy) ? 'DESC ' : "$sortBy";
460 - $orderField = \is_null($sortByField) ? 'bitforms_form_entry_id' : "`$sortByField`";
461 623
462 - $orderCondition = "ORDER BY $orderField $order ";
463 - if (!\is_null($limit)) {
464 - $limitInt = \intval($limit);
465 - $limit = " LIMIT $limitInt ";
466 - }
467 - $sql = "SELECT $selectedEntryMeta FROM `$this->table_name` em";
468 - $sql .= " INNER JOIN $entry_table e on e.id = em.bitforms_form_entry_id ";
469 - $sql .= $groupedCondition . $orderCondition . $limit;
624 + // Step 4: Process all entries efficiently
625 + foreach ($allData as &$entry) {
626 + // Process all fields with unified unescaping
627 + foreach ($entry as $key => &$value) {
628 + if (is_string($value)) {
629 + $value = self::unescapeString($value);
630 + }
470 631
471 - $result = $this->execute($sql, $all_values)->getResult();
472 - $allData = [];
473 - $entry_id = 'entry_id';
474 - $users = get_users(['fields' => ['ID', 'display_name']]);
475 - $userNames = [];
476 - foreach ($users as $key => $value) {
477 - $userNames[$value->ID] = $value->display_name;
478 - }
479 - foreach ($result as $key => $value) {
480 - foreach ($formFieldsNames as $formFieldName) {
481 - $allData[$key]['entry_id'] = preg_replace('/[\]["]/i', '', $value->$entry_id);
482 - if ('__user_id' === $formFieldName && intval($value->$formFieldName) > 0) {
483 - $allData[$key][$formFieldName] = $userNames[$value->$formFieldName];
484 - } elseif ('__user_ip' === $formFieldName) {
485 - $allData[$key][$formFieldName] = long2ip($value->$formFieldName);
486 - } else {
487 - $allData[$key][$formFieldName] = preg_replace('/[\]["]/i', '', $value->$formFieldName);
632 + // Process repeater fields
633 + if (in_array($key, $repeaterFields, true)) {
634 + $value = self::formatRepeaterValue($value, $fieldMap);
488 635 }
489 636 }
637 +
638 + unset($value); // Break reference
490 639 }
640 + unset($entry, $value); // Break references
491 641
492 - if (is_wp_error($result)) {
493 - wp_send_json_error('Internal server error', 500);
494 - } else {
495 - foreach ($fieldLabels as $field) {
496 - foreach ($allData as $index => $entry) {
497 - if (array_key_exists($field['key'], $entry) && 'file-up' === $field['type']) {
498 - $key = $field['key'];
499 - if (empty($entry[$key])) {
500 - continue;
501 - }
502 - $_upload_dir = BITFORMS_UPLOAD_DIR . DIRECTORY_SEPARATOR . $formId . DIRECTORY_SEPARATOR . $entry['entry_id'];
503 - if (is_array(explode(',', $entry[$key]))) {
504 - $fileData = [];
505 - foreach (explode(',', $entry[$key]) as $file) {
506 - $uploadedFile = explode('_', $file);
507 - $path = "bitforms/bitforms-file/?formID=$formId&entryID=" . $entry['entry_id'] . "&fileID=$uploadedFile[0]";
508 - if (file_exists($_upload_dir . DIRECTORY_SEPARATOR . $uploadedFile[0])) {
509 - $fileData[] = site_url($path, null);
510 - }
511 - }
512 - $allData[$index][$key] = implode(',', $fileData);
513 - } else {
514 - $uploadedFile = explode('_', $entry[$key]);
515 - $path = "bitforms/bitforms-file/?formID=$formId&entryID=" . $entry['entry_id'] . '&fileID=' . $uploadedFile[0];
516 - if (file_exists($_upload_dir . DIRECTORY_SEPARATOR . $uploadedFile[0])) {
517 - $allData[$index][$key] = site_url($path, null);
518 - }
519 - }
642 + // Process file fields (existing logic optimized)
643 + foreach ($allData as $index => &$entry) {
644 + $entryId = $entry['entry_id'];
645 + $_upload_dir = FileHandler::getEntriesFileUploadDir($formId, $entryId);
646 + foreach ($fileFields as $fileKey) {
647 + if (empty($entry[$fileKey])) {
648 + continue;
649 + }
650 +
651 + $fileIds = explode(',', $entry[$fileKey]);
652 + $urls = [];
653 +
654 + foreach ($fileIds as $fileId) {
655 + $path = "bitforms/bitforms-file/?formID=$formId&entryID=$entryId&fileID=$fileId";
656 + if (file_exists($_upload_dir . DIRECTORY_SEPARATOR . $fileId)) {
657 + $urls[] = site_url($path);
520 658 }
521 659 }
660 +
661 + $entry[$fileKey] = implode(',', $urls);
522 662 }
523 - wp_send_json_success($allData, 200);
524 663 }
664 +
665 + unset($entry); // Break reference
666 + wp_send_json_success($allData, 200);
525 667 }
668 + }
526 669 }