PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.61
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.61
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 / Modules / Entries / Entries.php

Entries.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 3.6.61, at app/Modules/Entries/Entries.php

758 lines 24.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\Modules\Entries;
4
5 use FluentForm\App\Helpers\Helper;
6 use FluentForm\App\Modules\Form\FormDataParser;
7 use FluentForm\App\Modules\Form\FormFieldsParser;
8 use FluentForm\Framework\Helpers\ArrayHelper;
9 use FluentForm\View;
10
11 class Entries extends EntryQuery
12 {
13 /**
14 * The form response model.
15 *
16 * @var \WpFluent\QueryBuilder\QueryBuilderHandler $responseMetaModel
17 */
18 protected $responseMetaModel;
19
20 /**
21 * Entries constructor.
22 *
23 * @throws \Exception
24 */
25 public function __construct()
26 {
27 parent::__construct();
28
29 $this->responseMetaModel = wpFluent()->table('fluentform_submission_meta');
30 }
31
32 public function getAllFormEntries()
33 {
34 $formId = intval($this->request->get('form_id'));
35
36
37 $limit = $this->request->get('per_page', 10);
38 $page = $this->request->get('page', 1);
39 $offset = ($page - 1) * $limit;
40
41 $search = $this->request->get('search');
42 $status = $this->request->get('entry_status');
43
44 $query = wpFluent()->table('fluentform_submissions')
45 ->select([
46 'fluentform_submissions.id',
47 'fluentform_submissions.form_id',
48 'fluentform_submissions.status',
49 'fluentform_submissions.created_at',
50 'fluentform_submissions.browser',
51 'fluentform_submissions.currency',
52 'fluentform_submissions.total_paid',
53 'fluentform_forms.title',
54 ])
55 ->join('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_submissions.form_id')
56 ->orderBy('fluentform_submissions.id', 'DESC')
57 ->limit($limit)
58 ->offset($offset);
59
60 if ($formId) {
61 $query->where('fluentform_submissions.form_id', $formId);
62 }
63
64 if ($status) {
65 $query->where('fluentform_submissions.status', $status);
66 } else {
67 $query->where('fluentform_submissions.status', '!=', 'trashed');
68 }
69
70 if ($search) {
71 $query->where('fluentform_submissions.response', 'LIKE', '%' . $search . '%');
72 }
73
74 $total = $query->count();
75 $entries = $query->get();
76 foreach ($entries as $entry) {
77 $entry->entry_url = admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $entry->form_id . '#/entries/' . $entry->id);
78 $entry->human_date = human_time_diff(strtotime($entry->created_at), strtotime(current_time('mysql')));
79 }
80 wp_send_json_success([
81 'entries' => $entries,
82 'total' => $total,
83 'last_page' => ceil($total / $limit)
84 ]);
85 }
86
87 public function getEntriesReport()
88 {
89 $from = date('Y-m-d H:i:s', strtotime('-30 days'));
90 $to = date('Y-m-d H:i:s', strtotime('+1 days'));
91 $period = new \DatePeriod(new \DateTime($from), new \DateInterval('P1D'), new \DateTime($to));
92
93 $range = [];
94
95 foreach ($period as $date) {
96 $range[$date->format('Y-m-d')] = 0;
97 }
98 $itemsQuery = wpFluent()->table('fluentform_submissions')->select([
99 wpFluent()->raw('DATE(created_at) AS date'),
100 wpFluent()->raw('COUNT(id) AS count'),
101 ])
102 ->whereBetween('created_at', $from, $to)
103 ->groupBy('date')
104 ->orderBy('date', 'ASC');
105
106 $formId = $this->request->get('form_id');
107
108 if ($formId) {
109 $itemsQuery = $itemsQuery->where('form_id', $formId);
110 }
111
112 $items = $itemsQuery->get();
113 foreach ($items as $item) {
114 $range[$item->date] = $item->count; //Filling value in the array
115 }
116
117 wp_send_json_success([
118 'stats' => $range
119 ]);
120
121 }
122
123 public function renderEntries($form_id)
124 {
125 wp_enqueue_script('fluentform_form_entries');
126
127 $forms = wpFluent()
128 ->table('fluentform_forms')
129 ->select(['id', 'title'])
130 ->orderBy('id', 'DESC')
131 ->get();
132
133 $emailNotifications = wpFluent()
134 ->table('fluentform_form_meta')
135 ->where('form_id', $form_id)
136 ->where('meta_key', 'notifications')
137 ->get();
138
139 $formattedNotification = [];
140
141 foreach ($emailNotifications as $notification) {
142 $value = \json_decode($notification->value, true);
143 $formattedNotification[] = [
144 'id' => $notification->id,
145 'name' => ArrayHelper::get($value, 'name')
146 ];
147 }
148
149 $form = wpFluent()->table('fluentform_forms')->find($form_id);
150
151
152 $app = wpFluentForm();
153
154 $fluentFormEntriesVars = apply_filters('fluent_form_entries_vars', [
155 'all_forms_url' => admin_url('admin.php?page=fluent_forms'),
156 'forms' => $forms,
157 'form_id' => $form->id,
158 'enabled_auto_delete' => Helper::isEntryAutoDeleteEnabled($form_id),
159 'current_form_title' => $form->title,
160 'entry_statuses' => Helper::getEntryStatuses($form_id),
161 'entries_url_base' => admin_url('admin.php?page=fluent_forms&route=entries&form_id='),
162 'no_found_text' => __('Sorry! No entries found. All your entries will be shown here once you start getting form submissions', 'fluentform'),
163 'has_pro' => defined('FLUENTFORMPRO'),
164 'printStyles' => [fluentformMix('css/settings_global.css')],
165 'email_notifications' => $formattedNotification,
166 'available_countries' => $app->load(
167 $app->appPath('Services/FormBuilder/CountryNames.php')
168 ),
169 'upgrade_url' => fluentform_upgrade_url()
170 ], $form);
171
172 wp_localize_script(
173 'fluentform_form_entries', 'fluent_form_entries_vars', $fluentFormEntriesVars
174 );
175
176 View::render('admin.form.entries', [
177 'form_id' => $form_id,
178 'has_pdf' => defined('FLUENTFORM_PDF_VERSION') ? 'true' : 'false'
179 ]);
180 }
181
182 public function getEntriesGroup()
183 {
184 $formId = intval($this->request->get('form_id'));
185 $counts = $this->groupCount($formId);
186 wp_send_json_success([
187 'counts' => $counts
188 ], 200);
189 }
190
191 public function _getEntries(
192 $formId,
193 $currentPage,
194 $perPage,
195 $sortBy,
196 $entryType,
197 $search,
198 $wheres = []
199 )
200 {
201 $this->formId = $formId;
202 $this->per_page = $perPage;
203 $this->sort_by = $sortBy;
204 $this->page_number = $currentPage;
205 $this->search = $search;
206 $this->wheres = $wheres;
207
208 if ($entryType == 'favorite') {
209 $this->is_favourite = true;
210 } elseif ($entryType != 'all' && $entryType) {
211 $this->status = $entryType;
212 }
213
214 $dateRange = $this->request->get('date_range');
215 if ($dateRange) {
216 $this->startDate = $dateRange[0];
217 $this->endDate = $dateRange[1];
218 }
219
220 $form = $this->formModel->find($formId);
221 $formMeta = $this->getFormInputsAndLabels($form);
222 $formLabels = $formMeta['labels'];
223 $formLabels = apply_filters('fluentfoform_entry_lists_labels', $formLabels, $form);
224 $submissions = $this->getResponses();
225 $submissions['data'] = FormDataParser::parseFormEntries($submissions['data'], $form);
226
227 return compact('submissions', 'formLabels');
228 }
229
230 public function getEntries()
231 {
232 if (!defined('FLUENTFORM_RENDERING_ENTRIES')) {
233 define('FLUENTFORM_RENDERING_ENTRIES', true);
234 }
235
236 $wheres = [];
237
238 if ($paymentStatuses = $this->request->get('payment_statuses')) {
239 if (is_array($paymentStatuses)) {
240 $wheres[] = ['payment_status', $paymentStatuses];
241 }
242 }
243
244 $entries = $this->_getEntries(
245 intval($this->request->get('form_id')),
246 intval($this->request->get('current_page', 1)),
247 intval($this->request->get('per_page', 10)),
248 sanitize_text_field($this->request->get('sort_by', 'DESC')),
249 sanitize_text_field($this->request->get('entry_type', 'all')),
250 sanitize_text_field($this->request->get('search')),
251 $wheres
252 );
253
254
255 $labels = apply_filters(
256 'fluentform_all_entry_labels', $entries['formLabels'], $this->request->get('form_id')
257 );
258
259 $form = $this->formModel->find($this->request->get('form_id'));
260
261 if ($form->has_payment) {
262 $labels = apply_filters(
263 'fluentform_all_entry_labels_with_payment', $entries['formLabels'], false, $form
264 );
265 }
266
267 wp_send_json_success([
268 'submissions' => apply_filters('fluentform_all_entries', $entries['submissions']),
269 'labels' => $labels
270 ], 200);
271 }
272
273 public function _getEntry()
274 {
275 $this->formId = intval($this->request->get('form_id'));
276
277 $entryId = intval($this->request->get('entry_id'));
278
279 $entry_type = sanitize_text_field($this->request->get('entry_type', 'all'));
280
281 if ($entry_type === 'favorite') {
282 $this->is_favourite = true;
283 } elseif ($entry_type !== 'all') {
284 $this->status = $entry_type;
285 }
286
287 $this->sort_by = sanitize_text_field($this->request->get('sort_by', 'ASC'));
288
289 $this->search = sanitize_text_field($this->request->get('search'));
290
291 $submission = $this->getResponse($entryId);
292
293 if (!$submission) {
294 wp_send_json_error([
295 'message' => 'No Entry found.'
296 ], 422);
297 }
298
299 $form = $this->formModel->find($this->formId);
300
301 if ($submission->status == 'unread' && apply_filters('fluentform_auto_read', true, $form)) {
302 wpFluent()->table('fluentform_submissions')
303 ->where('id', $entryId)
304 ->update([
305 'status' => 'read'
306 ]);
307
308 $submission->status = 'read';
309 }
310
311 $formMeta = $this->getFormInputsAndLabels($form);
312
313 $submission = FormDataParser::parseFormEntry($submission, $form, $formMeta['inputs'], true);
314
315 if ($submission->user_id) {
316 $user = get_user_by('ID', $submission->user_id);
317 $user_data = [
318 'name' => $user->display_name,
319 'email' => $user->user_email,
320 'ID' => $user->ID,
321 'permalink' => get_edit_user_link($user->ID)
322 ];
323 $submission->user = $user_data;
324 }
325
326 $submission = apply_filters('fluentform_single_response_data', $submission, $this->formId);
327
328 $fields = apply_filters(
329 'fluentform_single_response_input_fields', $formMeta['inputs'], $this->formId
330 );
331
332 $labels = apply_filters(
333 'fluentform_single_response_input_labels', $formMeta['labels'], $this->formId
334 );
335
336 $order_data = false;
337
338 if ($submission->payment_status || $submission->payment_total) {
339 $order_data = apply_filters(
340 'fluentform_submission_order_data', false, $submission, $form
341 );
342
343 $labels = apply_filters(
344 'fluentform_submission_entry_labels_with_payment', $labels, $submission, $form
345 );
346 }
347
348 $nextSubmissionId = $this->getNextResponse($entryId);
349
350 $previousSubmissionId = $this->getPrevResponse($entryId);
351
352 return [
353 'submission' => $submission,
354 'next' => $nextSubmissionId,
355 'prev' => $previousSubmissionId,
356 'labels' => $labels,
357 'fields' => $fields,
358 'order_data' => $order_data
359 ];
360 }
361
362 public function getEntry()
363 {
364 $entryData = $this->_getEntry();
365
366 $entryData['widgets'] = apply_filters('fluentform_single_entry_widgets', [], $entryData);
367
368 wp_send_json_success($entryData, 200);
369 }
370
371 /**
372 * @param $form
373 * @param array $with
374 *
375 * @return array
376 * @todo: Implement Caching mechanism so we don't have to parse these things for every request
377 */
378 private function getFormInputsAndLabels($form, $with = ['admin_label', 'raw'])
379 {
380 $formInputs = FormFieldsParser::getEntryInputs($form, $with);
381 $inputLabels = FormFieldsParser::getAdminLabels($form, $formInputs);
382 return [
383 'inputs' => $formInputs,
384 'labels' => $inputLabels
385 ];
386 }
387
388 public function getNotes()
389 {
390 $formId = intval($this->request->get('form_id'));
391 $entry_id = intval($this->request->get('entry_id'));
392 $apiLog = sanitize_text_field($this->request->get('api_log')) == 'yes';
393
394 $metaKeys = ['_notes'];
395
396 if ($apiLog) {
397 $metaKeys[] = 'api_log';
398 }
399
400 $notes = $this->responseMetaModel
401 ->where('form_id', $formId)
402 ->where('response_id', $entry_id)
403 ->whereIn('meta_key', $metaKeys)
404 ->orderBy('id', 'DESC')
405 ->get();
406
407 foreach ($notes as $note) {
408 if ($note->user_id) {
409 $note->pemalink = get_edit_user_link($note->user_id);
410 $user = get_user_by('ID', $note->user_id);
411 if ($user) {
412 $note->created_by = $user->display_name;
413 } else {
414 $note->created_by = __('Fluent Forms Bot', 'fluentform');
415 }
416 } else {
417 $note->pemalink = false;
418 }
419 }
420
421 $notes = apply_filters('fluentform_entry_notes', $notes, $entry_id, $formId);
422
423 wp_send_json_success([
424 'notes' => $notes
425 ], 200);
426 }
427
428 public function addNote()
429 {
430 $entryId = intval($this->request->get('entry_id'));
431 $formId = intval($this->request->get('form_id'));
432 $note = $this->request->get('note');
433 $note_content = sanitize_textarea_field($note['content']);
434 $note_status = sanitize_text_field($note['status']);
435 $user = get_user_by('ID', get_current_user_id());
436
437 $response_note = [
438 'response_id' => $entryId,
439 'form_id' => $formId,
440 'meta_key' => '_notes',
441 'value' => $note_content,
442 'status' => $note_status,
443 'user_id' => $user->ID,
444 'name' => $user->display_name,
445 'created_at' => current_time('mysql'),
446 'updated_at' => current_time('mysql')
447 ];
448
449 $response_note = apply_filters('fluentform_add_response_note', $response_note);
450
451 $insertId = $this->responseMetaModel->insert($response_note);
452
453 $added_note = $this->responseMetaModel->find($insertId);
454
455 do_action('fluentform_new_response_note_added', $insertId, $added_note);
456
457 wp_send_json_success([
458 'message' => __('Note has been successfully added', 'fluentform'),
459 'note' => $added_note,
460 'insert_id' => $insertId
461 ], 200);
462 }
463
464 public function changeEntryStatus()
465 {
466 $formId = intval($this->request->get('form_id'));
467 $entryId = intval($this->request->get('entry_id'));
468 $newStatus = sanitize_text_field($this->request->get('status'));
469
470 $this->responseModel
471 ->where('form_id', $formId)
472 ->where('id', $entryId)
473 ->update(['status' => $newStatus]);
474
475 wp_send_json_success([
476 'message' => __('Item has been marked as ' . $newStatus, 'fluentform'),
477 'status' => $newStatus
478 ], 200);
479 }
480
481 public function deleteEntry()
482 {
483 $formId = intval($this->request->get('form_id'));
484 $entryId = intval($this->request->get('entry_id'));
485 $newStatus = sanitize_text_field($this->request->get('status'));
486
487 $this->deleteEntryById($entryId, $formId);
488
489 wp_send_json_success([
490 'message' => __('Item Successfully deleted', 'fluentform'),
491 'status' => $newStatus
492 ], 200);
493 }
494
495 public function deleteEntryById($entryId, $formId = false)
496 {
497 do_action('fluentform_before_entry_deleted', $entryId, $formId);
498
499 $disableAttachmentDelete = apply_filters('fluentform_disable_attachment_delete', false, $formId);
500 if (defined('FLUENTFORMPRO') && $formId && !$disableAttachmentDelete) {
501 if (is_numeric($formId)) {
502 $form = wpFluent()->table('fluentform_forms')->find($formId);
503 } else {
504 $form = $formId;
505 }
506 $deletableFiles = $this->getSubmissionAttachments($entryId, $form);
507 if ($deletableFiles) {
508 foreach ($deletableFiles as $eachFile) {
509 $file = wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/' . basename($eachFile);
510 if (is_readable($file) && !is_dir($file)) {
511 @unlink($file);
512 }
513 }
514 }
515 }
516
517
518 wpFluent()->table('fluentform_submissions')
519 ->where('id', $entryId)
520 ->delete();
521 wpFluent()->table('fluentform_submission_meta')
522 ->where('response_id', $entryId)
523 ->delete();
524
525 wpFluent()->table('fluentform_logs')
526 ->where('source_id', $entryId)
527 ->where('source_type', 'submission_item')
528 ->delete();
529
530 wpFluent()->table('fluentform_entry_details')
531 ->where('submission_id', $entryId)
532 ->delete();
533
534 ob_start();
535 if (defined('FLUENTFORMPRO')) {
536 try {
537 wpFluent()->table('fluentform_order_items')
538 ->where('submission_id', $entryId)
539 ->delete();
540
541 wpFluent()->table('fluentform_subscriptions')
542 ->where('submission_id', $entryId)
543 ->delete();
544
545 wpFluent()->table('fluentform_transactions')
546 ->where('submission_id', $entryId)
547 ->delete();
548
549 wpFluent()->table('ff_scheduled_actions')
550 ->where('origin_id', $entryId)
551 ->where('type', 'submission_action')
552 ->delete();
553
554 } catch (\Exception $exception) {
555 // ...
556 }
557 }
558
559
560 $errors = ob_get_clean();
561
562
563 do_action('fluentform_after_entry_deleted', $entryId, $formId);
564
565 return true;
566 }
567
568 private function getSubmissionAttachments($submissionId, $form)
569 {
570 $fields = FormFieldsParser::getAttachmentInputFields($form, ['element', 'attributes']);
571
572 $deletableFiles = [];
573 if ($fields) {
574 $submission = wpFluent()->table('fluentform_submissions')
575 ->where('id', $submissionId)
576 ->first();
577
578 $data = json_decode($submission->response, true);
579
580 foreach ($fields as $field) {
581 if (!empty($data[$field['attributes']['name']])) {
582 $files = $data[$field['attributes']['name']];
583 if (is_array($files)) {
584 $deletableFiles = array_merge($deletableFiles, $files);
585 } else {
586 $deletableFiles = $files;
587 }
588
589 }
590 }
591 }
592
593 return $deletableFiles;
594 }
595
596 public function favoriteChange()
597 {
598 $formId = intval($this->request->get('form_id'));
599 $entryId = intval($this->request->get('entry_id'));
600 $newStatus = intval($this->request->get('is_favourite'));
601 if ($newStatus) {
602 $message = __('Item has been added to favorites', 'fluentform');
603 } else {
604 $message = __('Item has been removed from favorites', 'fluentform');
605 }
606 $this->responseModel
607 ->where('form_id', $formId)
608 ->where('id', $entryId)
609 ->update(['is_favourite' => $newStatus]);
610
611 wp_send_json_success([
612 'message' => $message,
613 'is_favourite' => $newStatus
614 ], 200);
615 }
616
617 public function handleBulkAction()
618 {
619 $formId = intval($this->request->get('form_id'));
620 $entries = fluentFormSanitizer($this->request->get('entries', []));
621
622 $actionType = sanitize_text_field($this->request->get('action_type'));
623
624 // check if it's status change or not
625 $statuses = Helper::getEntryStatuses($formId);
626
627 if (!$formId || !count($entries)) {
628 wp_send_json_error([
629 'message' => __('Please select entries first', 'fluentform')
630 ], 400);
631 }
632
633 $bulkQuery = wpFluent()->table('fluentform_submissions')
634 ->where('form_id', $formId)
635 ->whereIn('id', $entries);
636
637 if (isset($statuses[$actionType])) {
638 // it's status change
639 $bulkQuery->update([
640 'status' => $actionType,
641 'updated_at' => current_time('mysql')
642 ]);
643
644 wp_send_json_success([
645 'message' => 'Selected entries successfully marked as ' . $statuses[$actionType]
646 ], 200);
647 }
648
649 // now other action handler
650 if ($actionType == 'other.delete_permanently') {
651 $form = wpFluent()->table('fluentform_forms')->find($formId);
652 foreach ($entries as $entryId) {
653 $this->deleteEntryById($entryId, $form);
654 }
655 $message = __('Selected entries successfully deleted', 'fluentform');
656
657 } elseif ($actionType == 'other.make_favorite') {
658 $bulkQuery->update([
659 'is_favourite' => 1
660 ]);
661 $message = __('Selected entries successfully marked as Favorite', 'fluentform');
662 } elseif ($actionType == 'other.unmark_favorite') {
663 $bulkQuery->update([
664 'is_favourite' => 0
665 ]);
666 $message = __('Selected entries successfully remove from favorite', 'fluentform');
667 }
668
669 wp_send_json_success([
670 'message' => $message
671 ], 200);
672 }
673
674 public function recordEntryDetails($entryId, $formId, $data)
675 {
676 $formData = ArrayHelper::except($data, [
677 '__fluent_form_embded_post_id',
678 '_fluentform_' . $formId . '_fluentformnonce',
679 '_wp_http_referer'
680 ]);
681
682 $entryItems = [];
683 foreach ($formData as $dataKey => $dataValue) {
684 if (!$dataValue) {
685 continue;
686 }
687
688 if (is_array($dataValue)) {
689 foreach ($dataValue as $subKey => $subValue) {
690 $entryItems[] = [
691 'form_id' => $formId,
692 'submission_id' => $entryId,
693 'field_name' => $dataKey,
694 'sub_field_name' => $subKey,
695 'field_value' => maybe_serialize($subValue)
696 ];
697 }
698 } else {
699 $entryItems[] = [
700 'form_id' => $formId,
701 'submission_id' => $entryId,
702 'field_name' => $dataKey,
703 'sub_field_name' => '',
704 'field_value' => $dataValue
705 ];
706 }
707 }
708
709 foreach ($entryItems as $entryItem) {
710 wpFluent()->table('fluentform_entry_details')->insert($entryItem);
711 }
712
713 return true;
714 }
715
716 public function updateEntryDiffs($entryId, $formId, $formData)
717 {
718 wpFluent()->table('fluentform_entry_details')
719 ->where('submission_id', $entryId)
720 ->where('form_id', $formId)
721 ->whereIn('field_name', array_keys($formData))
722 ->delete();
723
724 $entryItems = [];
725 foreach ($formData as $dataKey => $dataValue) {
726 if (!$dataValue) {
727 continue;
728 }
729
730 if (is_array($dataValue)) {
731 foreach ($dataValue as $subKey => $subValue) {
732 $entryItems[] = [
733 'form_id' => $formId,
734 'submission_id' => $entryId,
735 'field_name' => $dataKey,
736 'sub_field_name' => $subKey,
737 'field_value' => maybe_serialize($subValue)
738 ];
739 }
740 } else {
741 $entryItems[] = [
742 'form_id' => $formId,
743 'submission_id' => $entryId,
744 'field_name' => $dataKey,
745 'sub_field_name' => '',
746 'field_value' => $dataValue
747 ];
748 }
749 }
750
751 foreach ($entryItems as $entryItem) {
752 wpFluent()->table('fluentform_entry_details')->insert($entryItem);
753 }
754
755 return true;
756 }
757 }
758