PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.13
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.13
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Services / Submission / SubmissionService.php

SubmissionService.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.13, at app/Services/Submission/SubmissionService.php

804 lines 27.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Services\Submission;
4
5 defined('ABSPATH') or die;
6
7 use Exception;
8 use FluentForm\App\Models\EntryDetails;
9 use FluentForm\App\Models\Form;
10 use FluentForm\App\Helpers\Helper;
11 use FluentForm\App\Models\FormMeta;
12 use FluentForm\App\Models\Submission;
13 use FluentForm\Framework\Support\Arr;
14 use FluentForm\App\Models\SubmissionMeta;
15 use FluentForm\Framework\Support\Collection;
16 use FluentForm\App\Services\Form\FormService;
17 use FluentForm\App\Modules\Form\FormDataParser;
18 use FluentForm\App\Modules\Form\FormFieldsParser;
19
20 class SubmissionService
21 {
22 /**
23 * @var \FluentForm\App\Models\Submission|\FluentForm\Framework\Database\Query\Builder|\FluentForm\Framework\Database\Orm\Builder
24 */
25 protected $model;
26 protected $formService;
27
28 public function __construct()
29 {
30 $this->model = new Submission();
31 $this->formService = new FormService();
32 }
33
34 public function get($attributes = [])
35 {
36 if (!defined('FLUENTFORM_RENDERING_ENTRIES')) {
37 define('FLUENTFORM_RENDERING_ENTRIES', true);
38 }
39
40 $entries = $this->model->paginateEntries($attributes);
41
42 if (Arr::get($attributes, 'parse_entry')) {
43 $form = Form::find(Arr::get($attributes, 'form_id'));
44
45 $parsedEntries = FormDataParser::parseFormEntries($entries->items(), $form);
46
47 $entries->setCollection(Collection::make($parsedEntries));
48 }
49
50 return apply_filters('fluentform/get_submissions', $entries);
51 }
52
53 public function find($submissionId)
54 {
55 try {
56 if (!defined('FLUENTFORM_RENDERING_ENTRY')) {
57 define('FLUENTFORM_RENDERING_ENTRY', true);
58 }
59
60 $submission = $this->model->with(['form','submissionMeta' => function($q) {
61 $q->where('meta_key', '_entry_uid_hash');
62 }])->findOrFail($submissionId);
63
64 $form = $submission->form;
65
66
67 $autoRead = apply_filters_deprecated(
68 'fluentform_auto_read',
69 [true, $form],
70 FLUENTFORM_FRAMEWORK_UPGRADE,
71 'fluentform/auto_read_submission'
72 );
73
74 $autoRead = apply_filters('fluentform/auto_read_submission', $autoRead, $form);
75
76 if ('unread' === $submission->status && $autoRead) {
77 $submission->fill(['status' => 'read'])->save();
78 }
79
80 $meta = $submission->submissionMeta;
81 if (count($meta)) {
82 $submission->_entry_uid_hash = Arr::get($meta, '0.value');
83 $this->setEntryUidLink($submission);
84 }
85
86 $submission = apply_filters('fluentform/submission_before_parse', $submission, $form);
87
88 $submission = FormDataParser::parseFormEntry($submission, $form, null, true);
89 $this->enrichWithUser($submission);
90
91 $submission = apply_filters_deprecated(
92 'fluentform_single_response_data',
93 [$submission, $form->id],
94 FLUENTFORM_FRAMEWORK_UPGRADE,
95 'fluentform/find_submission'
96 );
97
98 return apply_filters('fluentform/find_submission', $submission, $form->id)->makeHidden('form');
99 } catch (Exception $e) {
100 throw new Exception(
101 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message, not output
102 __('No Entry found.', 'fluentform')
103 );
104 }
105 }
106
107
108 /**
109 * @param array{
110 * formId?: int, // Optional when using uidHash
111 * serialNumber?: int, // Required if using formId without uidHash
112 * uidHash?: string, // Can be used with or without formId
113 * isHtml?: bool
114 * } $params Either (formId + serialNumber) OR uidHash required
115 *
116 * @return Submission
117 * @throws Exception
118 */
119 public function findByParams($params)
120 {
121 try {
122 if (!defined('FLUENTFORM_RENDERING_ENTRY')) {
123 define('FLUENTFORM_RENDERING_ENTRY', true);
124 }
125
126 $formId = $params['formId'] ?? null;
127 $serialNumber = $params['serialNumber'] ?? null;
128 $uidHash = $params['uidHash'] ?? null;
129 $isHtml = $params['isHtml'] ?? false;
130 if (!($uidHash || ($formId && $serialNumber))) {
131 throw new \Exception(
132 __('Either uidHash or (formId + serialNumber) must be provided', 'fluentform')
133 );
134 }
135
136 $query = Submission::query();
137
138 if ($formId) {
139 $query->where('form_id', $formId);
140 }
141
142 if ($serialNumber) {
143 $query->where('serial_number', $serialNumber);
144 } else {
145 $query->whereHas('submissionMeta', function ($metaQuery) use ($uidHash) {
146 $metaQuery->where('meta_key', '_entry_uid_hash')
147 ->where('value', $uidHash); // Changed to 'value' column
148 });
149 }
150
151 $submission = $query->orderBy('serial_number', 'desc')->first();
152
153 if (!$submission) {
154 throw new \Exception(
155 __('No entry found matching the criteria', 'fluentform')
156 );
157 }
158 $form = $submission->form;
159
160 $autoRead = apply_filters('fluentform/auto_read_submission', true, $form);
161
162 if ('unread' === $submission->status && $autoRead) {
163 $submission->fill(['status' => 'read'])->save();
164 }
165
166 $meta = $submission->submissionMeta()->where('meta_key', '_entry_uid_hash')->first();
167 if ($meta && $meta->value) {
168 $submission->_entry_uid_hash = $meta->value;
169 $this->setEntryUidLink($submission);
170 }
171
172 $submission = FormDataParser::parseFormEntry($submission, $form, null, $isHtml);
173 $this->enrichWithUser($submission);
174
175 return apply_filters('fluentform/find_submission', $submission, $form->id);
176 } catch (Exception $e) {
177 throw new Exception(
178 sprintf(
179 /* translators: %s: error message */
180 esc_html__('No Entry found. Error: %s', 'fluentform'),
181 esc_html($e->getMessage())
182 )
183 );
184 }
185 }
186
187 public function resources($attributes)
188 {
189 $resources = [];
190
191 $formId = Arr::get($attributes, 'form_id');
192 $submissionId = Arr::get($attributes, 'entry_id');
193
194 // When an entry is targeted, the authoritative form is the one stored on
195 // that submission — never a separately supplied request form_id, which
196 // could point counts/labels/fields/metadata reads at another form the
197 // caller was not authorized for (authorization resolved from the entry).
198 if ($submissionId) {
199 $submission = $this->model->find($submissionId);
200 if ($submission) {
201 $formId = (int) $submission->form_id;
202 }
203 }
204
205 if (Arr::get($attributes, 'counts')) {
206 $resources['counts'] = $this->model->countByGroup($formId);
207 }
208
209 $formInputsAndLabels = null;
210
211 $wantsLabels = Arr::get($attributes, 'labels');
212
213 if ($wantsLabels) {
214 $formInputsAndLabels = $this->formService->getInputsAndLabels($formId);
215 $resources['labels'] = $formInputsAndLabels['labels'];
216 }
217
218 if (Arr::get($attributes, 'fields')) {
219 $formInputsAndLabels = $formInputsAndLabels ? $formInputsAndLabels : $this->formService->getInputsAndLabels($formId);
220 $resources['fields'] = $formInputsAndLabels['inputs'];
221 }
222
223 if (Arr::get($attributes, 'visibleColumns')) {
224 $resources['visibleColumns'] = Helper::getFormMeta($formId, '_visible_columns', null);
225 }
226
227 if (Arr::get($attributes, 'columnsOrder')) {
228 $resources['columnsOrder'] = Helper::getFormMeta($formId, '_columns_order', null);
229 }
230
231 if (Arr::get($attributes, 'next')) {
232 $resources['next'] = $this->model->findAdjacentSubmission($attributes);
233 }
234
235 if (Arr::get($attributes, 'previous')) {
236 $attributes['direction'] = 'previous';
237 $resources['previous'] = $this->model->findAdjacentSubmission($attributes);
238 }
239 if (count(array_intersect(['orderData', 'widgets', 'cards'], array_keys($attributes))) > 0) {
240 try {
241 $submission = $this->model->with('form')->findOrFail($submissionId);
242 } catch (Exception $e) {
243 throw new Exception(
244 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message, not output
245 __('No Entry found.', 'fluentform')
246 );
247 }
248
249 if (Arr::get($attributes, 'orderData')) {
250 $hasPayment = $submission->payment_status || $submission->payment_total || 'subscription' === $submission->payment_type;
251
252 if ($hasPayment) {
253 $resources['orderData'] = apply_filters(
254 'fluentform/submission_order_data',
255 false,
256 $submission,
257 $submission->form
258 );
259
260 if ($wantsLabels) {
261 $resources['labels'] = apply_filters(
262 'fluentform/submission_labels',
263 $resources['labels'],
264 $submission,
265 $submission->form
266 );
267 }
268 }
269 }
270
271 if (Arr::get($attributes, 'widgets')) {
272 $resources['widgets'] = apply_filters(
273 'fluentform/submissions_widgets', [], $resources, $submission
274 );
275 }
276
277 if (Arr::get($attributes, 'cards')) {
278 $resources['cards'] = apply_filters(
279 'fluentform/submission_cards', [], $resources, $submission
280 );
281 }
282 }
283
284 return apply_filters('fluentform/submission_resources', $resources);
285 }
286
287 public function updateStatus($attributes = [])
288 {
289 $submissionId = intval(Arr::get($attributes, 'entry_id'));
290
291 $status = sanitize_text_field(Arr::get($attributes, 'status'));
292
293 $this->model->amend($submissionId, ['status' => $status]);
294
295 do_action('fluentform/after_submission_status_update', $submissionId, $status);
296
297 return $status;
298 }
299
300 public function toggleIsFavorite($submissionId)
301 {
302 try {
303 $submission = $this->model->findOrFail($submissionId);
304 } catch (Exception $e) {
305 throw new Exception(
306 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message, not output
307 __('No Entry found.', 'fluentform')
308 );
309 }
310
311 if ($submission->is_favourite) {
312 $message = __('The entry has been removed from favorites', 'fluentform');
313 } else {
314 $message = __('The entry has been marked as favorites', 'fluentform');
315 }
316
317 $submission->fill(['is_favourite' => !$submission->is_favourite])->save();
318
319 return [$message, $submission->is_favourite];
320 }
321
322 public function storeColumnSettings($attributes = [])
323 {
324 $formId = intval(Arr::get($attributes, 'form_id'));
325 $metaKey = sanitize_text_field(Arr::get($attributes, 'meta_key'));
326
327 $allowedKeys = ['_visible_columns', '_columns_order'];
328 if (!in_array($metaKey, $allowedKeys)) {
329 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
330 throw new \Exception(__('Invalid meta key for column settings.', 'fluentform'));
331 }
332
333 $metaValue = wp_unslash(Arr::get($attributes, 'settings'));
334
335 FormMeta::persist($formId, $metaKey, $metaValue);
336 }
337
338 public function handleBulkActions($attributes = [])
339 {
340 $formId = intval(Arr::get($attributes, 'form_id'));
341
342 $submissionIds = fluentFormSanitizer(Arr::get($attributes, 'entries', []));
343
344 $actionType = sanitize_text_field(Arr::get($attributes, 'action_type'));
345
346 if (!$formId || !count($submissionIds)) {
347 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message, not output
348 throw new Exception(__('Please select entries first', 'fluentform'));
349 }
350
351 $query = $this->model->where('form_id', $formId)->whereIn('id', $submissionIds);
352
353 $statuses = Helper::getEntryStatuses($formId);
354
355 $message = '';
356
357 if (isset($statuses[$actionType])) {
358 $query->update([
359 'status' => $actionType,
360 'updated_at' => current_time('mysql'),
361 ]);
362
363 foreach ($submissionIds as $submissionId) {
364 do_action('fluentform/after_submission_status_update', $submissionId, $actionType);
365 }
366
367 $message = 'Selected entries successfully marked as ' . $statuses[$actionType];
368 } elseif ('other.delete_permanently' == $actionType) {
369 $ownedIds = $this->model->where('form_id', $formId)
370 ->whereIn('id', $submissionIds)
371 ->pluck('id')
372 ->all();
373
374 if ($ownedIds) {
375 $this->deleteEntries($ownedIds, $formId);
376 }
377
378 $message = __('Selected entries successfully deleted', 'fluentform');
379 } elseif ('other.make_favorite' == $actionType) {
380 $query->update([
381 'is_favourite' => 1,
382 ]);
383
384 $message = __('Selected entries successfully marked as favorites', 'fluentform');
385 } elseif ('other.unmark_favorite' == $actionType) {
386 $query->update([
387 'is_favourite' => 0,
388 ]);
389
390 $message = __('Selected entries successfully removed from favorites', 'fluentform');
391 }
392
393 return $message;
394 }
395
396 public function deleteEntries($submissionIds, $formId)
397 {
398 $submissionIds = (array)$submissionIds;
399
400 do_action('fluentform/before_deleting_entries', $submissionIds, $formId);
401
402 foreach ($submissionIds as $submissionId) {
403 do_action_deprecated(
404 'fluentform_before_entry_deleted',
405 [$submissionId, $formId],
406 FLUENTFORM_FRAMEWORK_UPGRADE,
407 'fluentform/before_deleting_entries'
408 );
409 }
410
411 $this->deleteFiles($submissionIds, $formId);
412
413 Submission::remove($submissionIds, $formId);
414
415 do_action('fluentform/after_deleting_submissions', $submissionIds, $formId);
416
417 foreach ($submissionIds as $submissionId) {
418 do_action_deprecated(
419 'fluentform_after_entry_deleted',
420 [$submissionId, $formId],
421 FLUENTFORM_FRAMEWORK_UPGRADE,
422 'fluentform/after_deleting_entries'
423 );
424 }
425 }
426
427 public function deleteFiles($submissionIds, $formId)
428 {
429 apply_filters_deprecated(
430 'fluentform_disable_attachment_delete',
431 [
432 false,
433 $formId
434 ],
435 FLUENTFORM_FRAMEWORK_UPGRADE,
436 'fluentform/disable_attachment_delete',
437 'Use fluentform/disable_attachment_delete instead of fluentform_disable_attachment_delete'
438 );
439
440 $disableAttachmentDelete = apply_filters(
441 'fluentform/disable_attachment_delete', false, $formId
442 );
443
444 $shouldDelete = defined('FLUENTFORMPRO') && $formId && !$disableAttachmentDelete;
445
446 if ($shouldDelete) {
447 $deletables = $this->getAttachments($submissionIds, $formId);
448
449 foreach ($deletables as $file) {
450 $file = wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/' . basename($file);
451
452 if (is_readable($file) && !is_dir($file)) {
453 wp_delete_file($file);
454 }
455 }
456 // Empty Temp Uploads
457 if (defined('FLUENTFORMPRO')) {
458 $tempDir = wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/temp/';
459 $files = glob($tempDir . '*');
460 if(!empty($files)){
461 foreach ($files as $file) {
462 if (basename($file) !== 'index.php') {
463 wp_delete_file($file);
464 }
465 }
466 }
467 }
468
469 }
470 }
471
472 public function getAttachments($submissionIds, $form)
473 {
474 $submissionIds = (array)$submissionIds;
475
476 if (!$form instanceof Form) {
477 $form = Form::find($form);
478 }
479
480 $fields = FormFieldsParser::getAttachmentInputFields($form, ['element', 'attributes']);
481
482 $attachments = [];
483
484 if ($fields) {
485 $fields = Arr::pluck($fields, 'attributes.name');
486
487 $submissions = $this->model->whereIn('id', $submissionIds)->get();
488
489 foreach ($submissions as $submission) {
490 $response = json_decode($submission->response, true);
491
492 $files = Arr::collapse(Arr::only($response, $fields));
493
494 $attachments = array_merge($attachments, $files);
495 }
496 }
497
498 return $attachments;
499 }
500
501 public function getNotes($submissionId, $attributes)
502 {
503 $formId = (int)Arr::get($attributes, 'form_id');
504 $apiLog = 'yes' === sanitize_text_field(Arr::get($attributes, 'api_log'));
505
506 $metaKeys = ['_notes'];
507
508 if ($apiLog) {
509 $metaKeys[] = 'api_log';
510 }
511
512 $perPage = (int) Arr::get($attributes, 'per_page', 0);
513 $page = (int) Arr::get($attributes, 'page', 1);
514
515 $query = SubmissionMeta::where('response_id', $submissionId)
516 ->whereIn('meta_key', $metaKeys)
517 ->orderBy('id', 'DESC');
518
519 if ($perPage > 0) {
520 $perPage = min($perPage, 100);
521 $notes = $query->forPage($page, $perPage)->get();
522 } else {
523 $notes = $query->get();
524 }
525
526 // Batch-fetch users to avoid N+1 queries
527 $userIds = $notes->pluck('user_id')->filter()->unique()->values()->toArray();
528 $usersMap = [];
529 if (!empty($userIds)) {
530 $users = get_users(['include' => $userIds, 'fields' => ['ID', 'display_name']]);
531 foreach ($users as $user) {
532 $usersMap[$user->ID] = $user->display_name;
533 }
534 }
535
536 foreach ($notes as $note) {
537 if ($note->user_id) {
538 $note->pemalink = get_edit_user_link($note->user_id);
539 if (isset($usersMap[$note->user_id])) {
540 $note->created_by = $usersMap[$note->user_id];
541 } else {
542 $note->created_by = __('Fluent Forms Bot', 'fluentform');
543 }
544 } else {
545 $note->pemalink = false;
546 }
547 }
548
549 apply_filters_deprecated(
550 'fluentform_entry_notes',
551 [
552 $notes,
553 $submissionId,
554 $formId
555 ],
556 FLUENTFORM_FRAMEWORK_UPGRADE,
557 'fluentform/entry_notes',
558 'Use fluentform/entry_notes instead of fluentform_entry_notes'
559 );
560
561 $notes = apply_filters('fluentform/entry_notes', $notes, $submissionId, $formId);
562
563 return apply_filters('fluentform/submission_notes', $notes, $submissionId, $formId);
564 }
565
566 public function storeNote($submissionId, $attributes = [])
567 {
568 // SECURITY (FINDING-20): derive form_id from the route-authorized submission, not the
569 // request body. Authorization is computed from the entry_id, but the note row's form_id
570 // came straight from the body — letting a manager scoped to one form write a note row into
571 // another form's meta namespace (cross-form integrity pollution).
572 $submission = Submission::find($submissionId);
573 $formId = $submission ? intval($submission->form_id) : intval(Arr::get($attributes, 'form_id'));
574
575 $content = sanitize_textarea_field($attributes['note']['content']);
576 $status = sanitize_text_field($attributes['note']['status']);
577 $user = get_user_by('ID', get_current_user_id());
578 $now = current_time('mysql');
579
580 $note = [
581 'response_id' => $submissionId,
582 'form_id' => $formId,
583 'meta_key' => '_notes',
584 'value' => $content,
585 'status' => $status,
586 'user_id' => $user->ID,
587 'name' => $user->display_name,
588 'created_at' => $now,
589 'updated_at' => $now,
590 ];
591
592 $note = apply_filters_deprecated(
593 'fluentform_add_response_note',
594 [$note],
595 FLUENTFORM_FRAMEWORK_UPGRADE,
596 'fluentform/store_submission_note'
597 );
598
599 $note = apply_filters('fluentform/store_submission_note', $note);
600
601 $submissionMeta = new SubmissionMeta;
602
603 $submissionMeta->fill($note)->save();
604
605 do_action_deprecated(
606 'fluentform_new_response_note_added',
607 [$submissionMeta->id, $submissionMeta],
608 FLUENTFORM_FRAMEWORK_UPGRADE,
609 'fluentform/submission_note_stored'
610 );
611
612 do_action('fluentform/submission_note_stored', $submissionMeta->id, $submissionMeta);
613
614 return [
615 'message' => __('Note has been successfully added', 'fluentform'),
616 'note' => $submissionMeta,
617 'insert_id' => $submissionMeta->id,
618 ];
619 }
620
621 public function updateSubmissionUser($userId, $submissionId)
622 {
623 if (!$userId || !$submissionId) {
624 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message, not output
625 throw new Exception(__('Submission ID and User ID is required', 'fluentform'));
626 }
627
628 $submission = Submission::find($submissionId);
629 $user = get_user_by('ID', $userId);
630
631 if (!$submission || $submission->user_id == $userId || !$user) {
632 // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message, not output
633 throw new Exception(__('Invalid Request', 'fluentform'));
634 }
635
636 Submission::where('id', $submission->id)
637 ->update([
638 'user_id' => $userId,
639 'updated_at' => current_time('mysql'),
640 ]);
641
642 if (defined('FLUENTFORMPRO')) {
643 // let's update the corresponding user IDs for transactions
644 \FluentForm\App\Models\Transaction::where('submission_id', $submission->id)
645 ->update([
646 'user_id' => $userId,
647 'updated_at' => current_time('mysql'),
648 ]);
649 }
650
651 do_action('fluentform/log_data', [
652 'parent_source_id' => $submission->form_id,
653 'source_type' => 'submission_item',
654 'source_id' => $submission->id,
655 'component' => 'General',
656 'status' => 'info',
657 'title' => 'Associate user has been changed from ' . $submission->user_id . ' to ' . $userId,
658 ]);
659
660 do_action_deprecated(
661 'fluentform_submission_user_changed',
662 [
663 $submission,
664 $user
665 ],
666 FLUENTFORM_FRAMEWORK_UPGRADE,
667 'fluentform/submission_user_changed',
668 'Use fluentform/submission_user_changed instead of fluentform_submission_user_changed.'
669 );
670
671 do_action('fluentform/submission_user_changed', $submission, $user);
672
673 return ([
674 'message' => __('Selected user has been successfully assigned to this submission', 'fluentform'),
675 'user' => [
676 'name' => $user->display_name,
677 'email' => $user->user_email,
678 'ID' => $user->ID,
679 'permalink' => get_edit_user_link($user->ID),
680 ],
681 'user_id' => $userId,
682 ]);
683 }
684
685 public function updateEntryDiffs($entryId, $formId, $formData)
686 {
687 EntryDetails::where('submission_id', $entryId)
688 ->where('form_id', $formId)
689 ->whereIn('field_name', array_keys($formData))
690 ->delete();
691
692 $entryItems = [];
693 foreach ($formData as $dataKey => $dataValue) {
694 if (!$dataValue) {
695 continue;
696 }
697
698 if (is_array($dataValue)) {
699 foreach ($dataValue as $subKey => $subValue) {
700 $entryItems[] = [
701 'form_id' => $formId,
702 'submission_id' => $entryId,
703 'field_name' => $dataKey,
704 'sub_field_name' => $subKey,
705 'field_value' => maybe_serialize($subValue),
706 ];
707 }
708 } else {
709 $entryItems[] = [
710 'form_id' => $formId,
711 'submission_id' => $entryId,
712 'field_name' => $dataKey,
713 'sub_field_name' => '',
714 'field_value' => $dataValue,
715 ];
716 }
717 }
718
719 if ($entryItems) {
720 EntryDetails::insert($entryItems);
721 }
722
723 return true;
724 }
725
726 public function recordEntryDetails($entryId, $formId, $data)
727 {
728 $formData = Arr::except($data, Helper::getWhiteListedFields($formId));
729
730 $entryItems = [];
731 foreach ($formData as $dataKey => $dataValue) {
732 if ($dataValue === '' || $dataValue === null) {
733 continue;
734 }
735
736 if (is_array($dataValue) || is_object($dataValue)) {
737 foreach ($dataValue as $subKey => $subValue) {
738 if (empty($subValue)) {
739 continue;
740 }
741 $entryItems[] = [
742 'form_id' => $formId,
743 'submission_id' => $entryId,
744 'field_name' => trim($dataKey),
745 'sub_field_name' => $subKey,
746 'field_value' => maybe_serialize($subValue),
747 ];
748 }
749 } else {
750 $entryItems[] = [
751 'form_id' => $formId,
752 'submission_id' => $entryId,
753 'field_name' => trim($dataKey),
754 'sub_field_name' => '',
755 'field_value' => $dataValue,
756 ];
757 }
758 }
759
760 if ($entryItems) {
761 EntryDetails::insert($entryItems);
762 }
763
764 return true;
765 }
766
767 public function getPrintContent($attr)
768 {
769 $content = (new SubmissionPrint())->getContent($attr);
770 return array('success' => true, 'content' => $content);
771 }
772
773 private function setEntryUidLink($submission)
774 {
775 $frontEndSettings = Helper::getFormMeta($submission->form_id, 'front_end_entry_view', []);
776 if (Arr::get($frontEndSettings, 'status') === 'yes') {
777 $submission->entry_uid_link = site_url('?ff_entry=1&hash=' . $submission->_entry_uid_hash);
778 }
779 }
780
781 private function enrichWithUser($submission)
782 {
783 if (!$submission->user_id) {
784 return;
785 }
786
787 $user = get_user_by('ID', $submission->user_id);
788 if (!$user) {
789 return;
790 }
791
792 $userDisplayName = trim($user->first_name . ' ' . $user->last_name);
793 if (!$userDisplayName) {
794 $userDisplayName = $user->display_name;
795 }
796
797 $submission->user = [
798 'ID' => $user->ID,
799 'name' => $userDisplayName,
800 'permalink' => get_edit_user_link($user->ID),
801 ];
802 }
803 }
804