PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 3.3.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v3.3.1
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 2.10.1 All 138 releases
← All changes | includes/Core/Integration/IntegrationHandler.php +346 -22 2.10.13.3.1 View file →
@@ -6,15 +6,17 @@
6 6 use BitCode\BitForm\Admin\Form\Helpers;
7 7 use BitCode\BitForm\Core\Database\FormEntryLogModel;
8 8 use BitCode\BitForm\Core\Database\FormEntryModel;
9 9 use BitCode\BitForm\Core\Database\IntegrationModel;
10 +use BitCode\BitForm\Core\Form\FormManager;
10 11 use BitCode\BitForm\Core\Util\FieldValueHandler;
12 +use BitCode\BitForm\Core\Util\Log;
11 13 use BitCode\BitForm\Core\Util\MailNotifier;
12 14 use BitCode\BitForm\Frontend\Form\FrontendFormManager;
13 15
14 16 final class IntegrationHandler
15 17 {
16 - private static $_formID;
18 + private $_formID;
17 19 private static $_integrationModel;
18 20 private $_user_details;
19 21
20 22 /**
@@ -26,9 +28,9 @@
26 28 * @return void
27 29 */
28 30 public function __construct($formID, $user_details = null)
29 31 {
30 - static::$_formID = $formID;
32 + $this->_formID = $formID;
31 33 static::$_integrationModel = new IntegrationModel();
32 34 $this->_user_details = $user_details;
33 35 }
34 36
@@ -34,9 +36,9 @@
34 36
35 37 public function getAIntegration($integrationID, $integrationCategory = null, $integrationType = null)
36 38 {
37 39 $conditions = [
38 - 'form_id' => static::$_formID,
40 + 'form_id' => $this->_formID,
39 41 'id' => $integrationID,
40 42 ];
41 43 if (!is_null($integrationType)) {
42 44 $conditions = array_merge($conditions, ['integration_type' => $integrationType]);
@@ -49,8 +51,9 @@
49 51 'id',
50 52 'integration_name',
51 53 'integration_type',
52 54 'integration_details',
55 + 'status',
53 56 'form_id',
54 57 ],
55 58 $conditions
56 59 );
@@ -58,9 +61,9 @@
58 61
59 62 public function getAllIntegration($integrationCategory = null, $integrationType = null, $status = null, $id = null)
60 63 {
61 64 $conditions = [
62 - 'form_id' => static::$_formID,
65 + 'form_id' => $this->_formID,
63 66 ];
64 67 if (!is_null($integrationType)) {
65 68 $conditions = array_merge($conditions, ['integration_type' => $integrationType]);
66 69 }
@@ -126,9 +129,9 @@
126 129 'integration_name' => $integrationName,
127 130 'integration_type' => $integrationType,
128 131 'integration_details' => $integrationDetails,
129 132 'category' => $integrationCategory,
130 - 'form_id' => static::$_formID,
133 + 'form_id' => $this->_formID,
131 134 'user_id' => $this->_user_details['id'],
132 135 'user_ip' => $this->_user_details['ip'],
133 136 'status' => $status,
134 137 'created_at' => $this->_user_details['time'],
@@ -147,9 +150,9 @@
147 150 'integration_name' => $integrationName,
148 151 'integration_type' => $integrationType,
149 152 'integration_details' => $integrationDetails,
150 153 'category' => $integrationCategory,
151 - 'form_id' => static::$_formID,
154 + 'form_id' => $this->_formID,
152 155 'user_id' => $this->_user_details['id'],
153 156 'user_ip' => $this->_user_details['ip'],
154 157 'status' => $status,
155 158 'updated_at' => $this->_user_details['time'],
@@ -159,8 +162,44 @@
159 162 ]
160 163 );
161 164 }
162 165
166 + /**
167 + * Name-only rename of a connected account row, scoped to
168 + * category=connected_integration_apps and this handler's form id (0).
169 + * updateIntegration() is unusable here: it overwrites details/type/category/status.
170 + */
171 + public function renameConnectedApp($integrationID, $integrationName)
172 + {
173 + $data = ['integration_name' => $integrationName];
174 + if (!empty($this->_user_details['time'])) {
175 + $data['updated_at'] = $this->_user_details['time'];
176 + }
177 + return static::$_integrationModel->update(
178 + $data,
179 + [
180 + 'id' => $integrationID,
181 + 'form_id' => $this->_formID,
182 + 'category' => 'connected_integration_apps',
183 + ]
184 + );
185 + }
186 +
187 + public function updateIntegrationStatus($integrationID, $status)
188 + {
189 + $data = ['status' => (int) $status];
190 + if (!empty($this->_user_details['time'])) {
191 + $data['updated_at'] = $this->_user_details['time'];
192 + }
193 + return static::$_integrationModel->update(
194 + $data,
195 + [
196 + 'id' => $integrationID,
197 + 'form_id' => $this->_formID,
198 + ]
199 + );
200 + }
201 +
163 202 public function duplicateAllInAForm($oldFormId)
164 203 {
165 204 $integCols = ['integration_name', 'integration_type', 'integration_details', 'category', 'form_id', 'user_id', 'user_ip', 'status', 'created_at', 'updated_at'];
166 205 $integDupData = [
@@ -167,9 +206,9 @@
167 206 'integration_name',
168 207 'integration_type',
169 208 'integration_details',
170 209 'category',
171 - static::$_formID,
210 + $this->_formID,
172 211 $this->_user_details['id'],
173 212 $this->_user_details['ip'],
174 213 'status',
175 214 $this->_user_details['time'],
@@ -182,9 +221,9 @@
182 221 {
183 222 return static::$_integrationModel->delete(
184 223 [
185 224 'id' => $integrationID,
186 - 'form_id' => static::$_formID,
225 + 'form_id' => $this->_formID,
187 226 ]
188 227 );
189 228 }
190 229
@@ -216,13 +255,29 @@
216 255 }
217 256 $fieldPattern = '/\${\w[^ ${}]*}/';
218 257 preg_match_all($fieldPattern, $stringToReplaceField, $matchedField);
219 258 $uniqueFieldsInStr = array_unique($matchedField[0]);
220 - foreach ($uniqueFieldsInStr as $key => $value) {
259 +
260 + foreach ($uniqueFieldsInStr as $value) {
221 261 $fieldName = substr($value, 2, strlen($value) - 3);
262 +
263 + $repeaterArr = explode('.', $fieldName);
222 264 if (isset($fieldValues[$fieldName])) {
223 - $stringToReplaceField = is_string($fieldValues[$fieldName]) ? str_replace($value, $fieldValues[$fieldName], $stringToReplaceField) :
224 - wp_json_encode($fieldValues[$fieldName]);
265 + $stringToReplaceField = is_string($fieldValues[$fieldName])
266 + ? str_replace($value, $fieldValues[$fieldName], $stringToReplaceField)
267 + : wp_json_encode($fieldValues[$fieldName]);
268 + } elseif (2 === count($repeaterArr) && isset($fieldValues[$repeaterArr[0]])) {
269 + $repeaterValues = [];
270 + $repeaterFieldValues = $fieldValues[$repeaterArr[0]];
271 + foreach ($repeaterFieldValues as $value) {
272 + if (isset($value[$repeaterArr[1]])) {
273 + $repeaterValues[] = $value[$repeaterArr[1]];
274 + }
275 + }
276 +
277 + $stringToReplaceField = $repeaterValues;
278 + } else {
279 + $stringToReplaceField = FieldValueHandler::replaceSmartTagWithValue($value);
225 280 }
226 281 }
227 282 return $stringToReplaceField;
228 283 }
@@ -229,9 +284,9 @@
229 284
230 285 public static function updatedHiddenFieldValue($formID)
231 286 {
232 287 $hiddenFields = [];
233 - $frontendFormManger = new FrontendFormManager($formID);
288 + $frontendFormManger = FrontendFormManager::getInstance($formID);
234 289
235 290 if ($frontendFormManger->isHoneypotActive()) {
236 291 $str = '_bitform' . '_' . $formID . '_' . time() . '_';
237 292 $honpotToken = Helpers::honeypotEncryptedToken($str);
@@ -264,8 +319,11 @@
264 319 $responseData['msg_id'] = isset($workFlowReturnedData['msg_id']) ? $workFlowReturnedData['msg_id'] : 0;
265 320 if (isset($workFlowReturnedData['msg_duration'])) {
266 321 $responseData['msg_duration'] = $workFlowReturnedData['msg_duration'];
267 322 }
323 + if (isset($workFlowReturnedData['afterSubmit'])) {
324 + $responseData['afterSubmit'] = $workFlowReturnedData['afterSubmit'];
325 + }
268 326 }
269 327 if (isset($workFlowReturnedData['redirectPage'])) {
270 328 $responseData['redirectPage'] = $workFlowReturnedData['redirectPage'];
271 329 }
@@ -271,8 +329,11 @@
271 329 }
272 330 if ('update' === $opType && isset($workFlowReturnedData['updatedData'])) {
273 331 $responseData['updatedData'] = $workFlowReturnedData['updatedData'];
274 332 }
333 + if (isset($workFlowReturnedData['new_nonce'])) {
334 + $responseData['new_nonce'] = $workFlowReturnedData['new_nonce'];
335 + }
275 336 if (!isset($workFlowReturnedData['triggerData'])) {
276 337 return $responseData;
277 338 }
278 339
@@ -277,10 +338,17 @@
277 338 }
278 339
279 340 $triggerData = $workFlowReturnedData['triggerData'];
280 341
342 + if (!isset($workFlowReturnedData['fields'])) {
343 + $workFlowReturnedData['fields'] = isset($workFlowReturnedData['updatedData'])
344 + ? $workFlowReturnedData['updatedData']
345 + : [];
346 + }
347 +
281 348 $trnasientData = get_transient("bitform_trigger_transient_{$entryId}");
282 349 $trnasientData = is_string($trnasientData) ? json_decode($trnasientData) : $trnasientData;
350 +
283 351 if (!empty($trnasientData['fields'])) {
284 352 $workFlowReturnedData['fields'] = array_merge($workFlowReturnedData['fields'], $trnasientData['fields']);
285 353 }
286 354
@@ -304,9 +372,9 @@
304 372 ];
305 373 }
306 374 }
307 375 ob_start();
308 - echo wp_doing_ajax() || defined('REST_REQUEST') ? wp_json_encode($response) : $workFlowReturnedData['message'];
376 + echo wp_doing_ajax() || defined('REST_REQUEST') ? wp_json_encode($response) : esc_html($workFlowReturnedData['message']);
309 377 ob_end_flush();
310 378 flush();
311 379 session_write_close();
312 380
@@ -321,15 +389,21 @@
321 389 'id' => $triggerData['entryID'],
322 390 ]
323 391 );
324 392
393 + $triggerData['fields'] = $workFlowReturnedData['fields'];
325 394 if (!is_wp_error($updatedStatus)) {
326 395 if ($workFlowReturnedData['dflt_template']) {
327 - $triggerData['fields'] = $workFlowReturnedData['fields'];
328 - do_action('bf_double_optin_confirmation', $workFlowReturnedData['integrationDetails'], $triggerData);
396 + // $triggerData['fields'] = $workFlowReturnedData['fields'];
397 + do_action('bitform_double_optin_confirmation', $workFlowReturnedData['integrationDetails'], $triggerData);
329 398 } elseif (isset($triggerData['dblOptin'])) {
330 399 foreach ($triggerData['dblOptin'] as $value) {
331 - MailNotifier::notify($value, $triggerData['formID'], $triggerData['fields'], $triggerData['entryID'], true, $triggerData['logID']);
400 + try {
401 + MailNotifier::notify($value, $triggerData['formID'], $triggerData['fields'], $triggerData['entryID'], true, $triggerData['logID']);
402 + } catch (\Throwable $mailError) {
403 + // response already flushed — a mail failure here must not kill the rest of the run
404 + Log::debug_log('[+] Double opt-in mail failed: ' . $mailError->getMessage());
405 + }
332 406 }
333 407 }
334 408 }
335 409 if (function_exists('fastcgi_finish_request')) {
@@ -340,16 +414,20 @@
340 414 die;
341 415 }
342 416 return $workFlowReturnedData;
343 417 }
344 -
345 - if (isset($triggerData['mail'])) {
418 + if (isset($triggerData['mail']) && !empty($triggerData['mail'])) {
346 419 $formManager = new AdminFormManager($triggerData['formID']);
347 420 $formContent = $formManager->getFormContent();
348 421 $submitted_fields = $formContent->fields;
349 422 $fieldValueForMail = FieldValueHandler::formatFieldValueForMail($submitted_fields, $workFlowReturnedData['fields']);
350 423 foreach ($triggerData['mail'] as $value) {
351 - MailNotifier::notify($value, $triggerData['formID'], $fieldValueForMail, $triggerData['entryID']);
424 + try {
425 + MailNotifier::notify($value, $triggerData['formID'], $fieldValueForMail, $triggerData['entryID'], false, $triggerData['logID']);
426 + } catch (\Throwable $mailError) {
427 + // response already flushed — a mail failure here must not skip the integrations below
428 + Log::debug_log('[+] Mail notification failed: ' . $mailError->getMessage());
429 + }
352 430 }
353 431 }
354 432 do_action('bitforms_exec_integrations', $triggerData['integrations'], $workFlowReturnedData['fields'], $triggerData['formID'], $triggerData['entryID'], $triggerData['logID']);
355 433
@@ -363,9 +441,9 @@
363 441 return $workFlowReturnedData;
364 442 }
365 443
366 444 $entryID = $triggerData['entryID'];
367 - if (isset($workFlowReturnedData['cron']) && $workFlowReturnedData['cron'] && !isset($triggerData['mail']) && isset($workFlowReturnedData['integrationRun']) && $workFlowReturnedData['integrationRun']) {
445 + if (isset($workFlowReturnedData['cron']) && $workFlowReturnedData['cron'] && empty($triggerData['mail']) && isset($workFlowReturnedData['integrationRun']) && $workFlowReturnedData['integrationRun']) {
368 446 $eventScheuled = wp_schedule_single_event(time(), 'bitforms_exec_integrations', [$triggerData['integrations'], $workFlowReturnedData['fields'], $triggerData['formID'], $triggerData['entryID'], $triggerData['logID']]);
369 447 $scheduleTime = wp_next_scheduled('bitforms_exec_integrations', [$triggerData['integrations'], $workFlowReturnedData['fields'], $triggerData['formID'], $triggerData['entryID'], $triggerData['logID']]);
370 448 $responseData['cron'] = get_site_url(null, "/wp-cron.php?doing_wp_cron&{$scheduleTime}");
371 449 } elseif (!empty($triggerData['integrations']) || !empty($triggerData['mail']) || isset($workFlowReturnedData['integrationRun']) && !$workFlowReturnedData['integrationRun']) {
@@ -374,9 +452,15 @@
374 452 $triggerData['dbl_opt_donf'] = $workFlowReturnedData['integrationDetails'];
375 453 $triggerData['dbl_opt_dflt_template'] = $workFlowReturnedData['dflt_template'];
376 454 $triggerData['integrationRun'] = $workFlowReturnedData['integrationRun'];
377 455 }
456 +
457 + // Generate one-time trigger token for security
458 + $triggerToken = wp_hash($triggerData['entryID'] . $triggerData['logID'] . time() . wp_rand(), 'nonce');
459 + $triggerData['trigger_token'] = $triggerToken;
460 +
378 461 set_transient("bitform_trigger_transient_{$entryID}", $triggerData, HOUR_IN_SECONDS);
462 + $queuedAt = current_time('mysql');
379 463 $entryLog = new FormEntryLogModel();
380 464 $queueuEntry = $entryLog->log_history_insert(
381 465 [
382 466 'log_id' => $triggerData['logID'],
@@ -382,17 +466,257 @@
382 466 'log_id' => $triggerData['logID'],
383 467 'integration_id' => 0,
384 468 'api_type' => wp_json_encode(['type' => 'trigger', 'type_name' => 'Workflow', 'on' => $opType]),
385 469 'response_type' => 'queued',
386 - 'response_obj' => wp_json_encode(['status' => 'queued']),
387 - 'created_at' => current_time('mysql'),
470 + // 'trigger' is a durable copy of the transient payload: object-cache hosts can
471 + // evict the transient (and it expires after 1h), which would otherwise lose the run
472 + 'response_obj' => wp_json_encode(['status' => 'queued', 'queued_at' => $queuedAt, 'trigger' => $triggerData]),
473 + 'created_at' => $queuedAt,
388 474 ]
389 475 );
476 + if (\is_int($queueuEntry)) {
477 + // Safety net: the browser-fired bitforms_trigger_workflow request can be lost
478 + // (navigation abort, WAF, network drop). This event re-runs the queued workflow;
479 + // it no-ops if the browser trigger already claimed the run.
480 + wp_schedule_single_event(
481 + time() + 2 * MINUTE_IN_SECONDS,
482 + 'bitforms_reclaim_workflow',
483 + [(int) $entryID, (int) $triggerData['formID'], (int) $triggerData['logID'], $queueuEntry]
484 + );
485 + if (!wp_next_scheduled('bitforms_reclaim_sweep')) {
486 + wp_schedule_event(time() + HOUR_IN_SECONDS, 'hourly', 'bitforms_reclaim_sweep');
487 + }
488 + }
390 489 $responseData['cronNotOk'] = [
391 490 $triggerData['entryID'],
392 491 $triggerData['logID'],
393 492 $queueuEntry,
493 + $triggerToken, // Add one-time token as 4th element
394 494 ];
395 495 }
396 496 return $responseData;
397 497 }
498 +
499 + public static function repeaterFieldValueFormatter($fieldValues)
500 + {
501 + $formattedArray = [];
502 +
503 + foreach ($fieldValues as $key => $value) {
504 + if (is_array($value)) {
505 + foreach ($value as $index => $v) {
506 + if (is_array($v)) {
507 + foreach ($v as $k1 => $v1) {
508 + $formattedArray[$k1][] = $v1;
509 + }
510 + } else {
511 + $formattedArray[$key][] = $v;
512 + }
513 + }
514 + } else {
515 + $formattedArray[$key] = $value;
516 + }
517 + }
518 +
519 + return $formattedArray;
520 + }
521 +
522 + /**
523 + *
524 + * @param mixed $fieldValues
525 + * @param mixed $returnRepeaterValue default is array
526 + * @param mixed $formID form ID required for string formatting
527 + * @return array and repeater field value as array or string
528 + */
529 + public static function formattedRepeaterValue($fieldValues, $returnRepeaterValue = '', $formID = null)
530 + {
531 + // get the repeater field and store it in an array
532 + $repeaterField = [];
533 + foreach ($fieldValues as $key => $value) {
534 + if (!preg_match('/\./', $key)) {
535 + continue;
536 + }
537 + $repeaterField[] = $key;
538 + }
539 +
540 + // put the value of the child key to the parent repeater field\
541 + foreach ($repeaterField as $key) {
542 + list($parentKey, $childKey) = explode('.', $key);
543 + $repeatValues = isset($fieldValues[$parentKey]) ? $fieldValues[$parentKey] : $key;
544 +
545 + if (!is_array($repeatValues)) {
546 + $fieldValues[$key] = $fieldValues[$childKey];
547 + continue;
548 + }
549 +
550 + foreach ($repeatValues as $value) {
551 + if (isset($value[$childKey])) {
552 + if (!isset($fieldValues[$key]) || !is_array($fieldValues[$key])) {
553 + $fieldValues[$key] = [];
554 + }
555 + if (!empty($value[$childKey])) {
556 + $fieldValues[$key][] = $value[$childKey];
557 + }
558 + }
559 + }
560 + }
561 +
562 + // convert the array to string repeater field value
563 + if ('string' === $returnRepeaterValue) {
564 + $form = new FormManager($formID);
565 + foreach ($repeaterField as $key) {
566 + if (isset($fieldValues[$key]) && is_array($fieldValues[$key])) {
567 + $fieldValues[$key] = implode(', ', self::flattenArray($fieldValues[$key]));
568 + }
569 + }
570 +
571 + foreach ($fieldValues as $key=>$value) {
572 + if (!$form->isRepeaterField($key)) {
573 + continue;
574 + }
575 + $repeaterValues = $fieldValues[$key];
576 +
577 + $newFieldValues = self::constructRepeaterValue($repeaterValues, $formID);
578 +
579 + $fieldValues[$key] = is_array($newFieldValues) ? json_encode(array_values($newFieldValues), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : $fieldValues[$key];
580 + }
581 + }
582 +
583 + return $fieldValues;
584 + }
585 +
586 + private static function flattenArray($array)
587 + {
588 + return array_map(function ($val) {
589 + if (is_array($val)) {
590 + return count($val) > 1 ? ('[' . implode(', ') . ']') : implode(', ', $val);
591 + } else {
592 + return $val;
593 + }
594 + }, $array);
595 + }
596 +
597 + /**
598 + * Replace file field value with web url
599 + * @param mixed $fieldValues
600 + * @param number $formId
601 + * @param number $entryId
602 + * @return mixed $fieldValues
603 + */
604 + public static function handleFileUrl($fieldValues, $formId, $entryId)
605 + {
606 + if (!$formId || !$entryId) {
607 + return $fieldValues;
608 + }
609 + $form = FormManager::getInstance($formId);
610 + $formFields = $form->getFields();
611 +
612 + $fldsIncludeFile = ['file-up', 'advanced-file-up', 'repeater', 'signature'];
613 + foreach ($fieldValues as $key =>$value) {
614 + $fldTyp = $formFields[$key]['type'] ?? null;
615 + if (!in_array($fldTyp, $fldsIncludeFile)) {
616 + continue;
617 + }
618 +
619 + if ('repeater' === $fldTyp && is_array($value)) {
620 + foreach ($value as $rIndex => $rValue) {
621 + foreach ($rValue as $subKey=>$subValue) {
622 + if (!in_array($formFields[$subKey]['type'], $fldsIncludeFile)) {
623 + continue;
624 + }
625 + // for file fields inside repeater
626 + if (is_array($subValue)) {
627 + foreach ($subValue as $fileIndex=>$fileValue) {
628 + $fieldValues[$key][$rIndex][$subKey][$fileIndex] = self::constructFileUrl($formId, $entryId, $fileValue);
629 + }
630 + } else {
631 + // for signature field inside repeater;
632 + $fieldValues[$key][$rIndex][$subKey] = self::constructFileUrl($formId, $entryId, $subValue);
633 + }
634 + }
635 + }
636 + }
637 +
638 + if (in_array($fldTyp, ['file-up', 'advanced-file-up', 'signature'], true)) {
639 + if (is_array($value)) {
640 + foreach ($value as $fldIndex=>$fldValue) {
641 + $fieldValues[$key][$fldIndex] = self::constructFileUrl($formId, $entryId, $fldValue);
642 + }
643 + } else {
644 + $fieldValues[$key] = self::constructFileUrl($formId, $entryId, $value);
645 + }
646 + }
647 + }
648 +
649 + return $fieldValues;
650 + }
651 +
652 + public static function assignRepeaterFieldValue($fieldValues, $formId)
653 + {
654 + if (!$formId) {
655 + return $fieldValues;
656 + }
657 + $form = new FormManager($formId);
658 + $formFields = $form->getFields();
659 +
660 + foreach ($fieldValues as $key=>$value) {
661 + if (!$form->isRepeaterField($key)) {
662 + continue;
663 + }
664 +
665 + if ('repeater' === $formFields[$key]['type']) {
666 + if (is_array($value)) {
667 + foreach ($value as $rIndex=>$rValue) {
668 + foreach ($rValue as $subKey =>$subValue) {
669 + $fieldValues[$subKey] = $subValue;
670 + }
671 + }
672 + }
673 + }
674 + }
675 +
676 + return $fieldValues;
677 + }
678 +
679 + public static function constructRepeaterValue($repeaterValues, $formId)
680 + {
681 + if (!$formId || !is_array($repeaterValues)) {
682 + return $repeaterValues;
683 + }
684 + $form = FormManager::getInstance($formId);
685 + $formFields = $form->getFields();
686 + $newRptrValue = [];
687 + foreach ($repeaterValues as $key=>$value) {
688 + $newRepeatedValue = [];
689 + foreach ($value as $rKey =>$rValue) {
690 + $fldLbl = isset($formFields[$rKey]) ? $formFields[$rKey]['label'] : $rKey;
691 + $newRepeatedValue[$fldLbl] = $rValue;
692 + }
693 + $newRptrValue[$key] = $newRepeatedValue;
694 + }
695 +
696 + return $newRptrValue;
697 + }
698 +
699 + private static function constructFileUrl($formId, $entryId, $fileName)
700 + {
701 + $webPath = Helpers::getWebPathWithEncryptedEntryId($formId, $entryId);
702 +
703 + return rtrim($webPath, '/') . '/' . ltrim($fileName, '/');
704 + }
705 +
706 + // private static function constructFileUrl($formId, $entryId, $fileName)
707 + // {
708 + // $restBaseUrl = get_rest_url();
709 + // if (!$restBaseUrl) {
710 + // return $fileName;
711 + // }
712 + // //http://bitlocal.local/wp-json/bitform/v1/bitform-file-download/?formID=1&entryID=16&fileID=bit-form-1005.pdf
713 + // $queryParam = build_query([
714 + // 'formID' => $formId,
715 + // 'entryID' => $entryId,
716 + // 'fileID' => $fileName
717 + // ]);
718 +
719 + // $path = $restBaseUrl . 'bitform' . '/' . 'v1' . '/' . 'bitform-file-download' . '/' . '?' . $queryParam;
720 + // return rtrim($path, '/');
721 + // }
398 722 }