PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.60
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.60
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.60, at app/Modules/Entries/Entries.php

759 lines 24.6 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 wpFluent()->table('fluentform_submissions')
500 ->where('id', $entryId)
501 ->delete();
502 wpFluent()->table('fluentform_submission_meta')
503 ->where('response_id', $entryId)
504 ->delete();
505
506 wpFluent()->table('fluentform_logs')
507 ->where('source_id', $entryId)
508 ->where('source_type', 'submission_item')
509 ->delete();
510
511 wpFluent()->table('fluentform_entry_details')
512 ->where('submission_id', $entryId)
513 ->delete();
514
515 ob_start();
516 if (defined('FLUENTFORMPRO')) {
517 try {
518 if($formId) {
519 if(is_numeric($formId)) {
520 $form = wpFluent()->table('fluentform_forms')->find($formId);
521 } else {
522 $form = $formId;
523 }
524 $deletableFiles = $this->getSubmissionAttachments($entryId, $form);
525 if ($deletableFiles) {
526 foreach ($deletableFiles as $eachFile) {
527 $file = wp_upload_dir()['basedir'].FLUENTFORM_UPLOAD_DIR.'/'.basename($eachFile);
528 if(is_readable($file) && !is_dir($file)) {
529 vddd(unlink($file));
530 }
531 }
532 }
533 }
534
535 wpFluent()->table('fluentform_order_items')
536 ->where('submission_id', $entryId)
537 ->delete();
538
539 wpFluent()->table('fluentform_subscriptions')
540 ->where('submission_id', $entryId)
541 ->delete();
542
543 wpFluent()->table('fluentform_transactions')
544 ->where('submission_id', $entryId)
545 ->delete();
546
547 wpFluent()->table('ff_scheduled_actions')
548 ->where('origin_id', $entryId)
549 ->where('type', 'submission_action')
550 ->delete();
551
552 } catch (\Exception $exception) {
553 // ...
554 }
555 }
556
557
558 $errors = ob_get_clean();
559
560
561 do_action('fluentform_after_entry_deleted', $entryId, $formId);
562
563 return true;
564 }
565
566 private function getSubmissionAttachments($submissionId, $form)
567 {
568 $fields = FormFieldsParser::getAttachmentInputFields($form, ['element', 'attributes']);
569
570 $deletableFiles = [];
571
572 if ($fields) {
573 $submission = wpFluent()->table('fluentform_submissions')
574 ->where('id', $submissionId)
575 ->first();
576
577 $data = json_decode($submission->response, true);
578
579 foreach ($fields as $field) {
580 if (!empty($data[$field['attributes']['name']])) {
581
582 $files = $data[$field['attributes']['name']];
583
584 if (is_array($files)) {
585 $deletableFiles = array_merge($deletableFiles, $files);
586 } else {
587 $deletableFiles = $files;
588 }
589
590 }
591 }
592 }
593
594 return $deletableFiles;
595 }
596
597 public function favoriteChange()
598 {
599 $formId = intval($this->request->get('form_id'));
600 $entryId = intval($this->request->get('entry_id'));
601 $newStatus = intval($this->request->get('is_favourite'));
602 if ($newStatus) {
603 $message = __('Item has been added to favorites', 'fluentform');
604 } else {
605 $message = __('Item has been removed from favorites', 'fluentform');
606 }
607 $this->responseModel
608 ->where('form_id', $formId)
609 ->where('id', $entryId)
610 ->update(['is_favourite' => $newStatus]);
611
612 wp_send_json_success([
613 'message' => $message,
614 'is_favourite' => $newStatus
615 ], 200);
616 }
617
618 public function handleBulkAction()
619 {
620 $formId = intval($this->request->get('form_id'));
621 $entries = fluentFormSanitizer($this->request->get('entries', []));
622
623 $actionType = sanitize_text_field($this->request->get('action_type'));
624
625 // check if it's status change or not
626 $statuses = Helper::getEntryStatuses($formId);
627
628 if (!$formId || !count($entries)) {
629 wp_send_json_error([
630 'message' => __('Please select entries first', 'fluentform')
631 ], 400);
632 }
633
634 $bulkQuery = wpFluent()->table('fluentform_submissions')
635 ->where('form_id', $formId)
636 ->whereIn('id', $entries);
637
638 if (isset($statuses[$actionType])) {
639 // it's status change
640 $bulkQuery->update([
641 'status' => $actionType,
642 'updated_at' => current_time('mysql')
643 ]);
644
645 wp_send_json_success([
646 'message' => 'Selected entries successfully marked as ' . $statuses[$actionType]
647 ], 200);
648 }
649
650 // now other action handler
651 if ($actionType == 'other.delete_permanently') {
652 $form = wpFluent()->table('fluentform_forms')->find($formId);
653 foreach ($entries as $entryId) {
654 $this->deleteEntryById($entryId, $form);
655 }
656 $message = __('Selected entries successfully deleted', 'fluentform');
657
658 } elseif ($actionType == 'other.make_favorite') {
659 $bulkQuery->update([
660 'is_favourite' => 1
661 ]);
662 $message = __('Selected entries successfully marked as Favorite', 'fluentform');
663 } elseif ($actionType == 'other.unmark_favorite') {
664 $bulkQuery->update([
665 'is_favourite' => 0
666 ]);
667 $message = __('Selected entries successfully remove from favorite', 'fluentform');
668 }
669
670 wp_send_json_success([
671 'message' => $message
672 ], 200);
673 }
674
675 public function recordEntryDetails($entryId, $formId, $data)
676 {
677 $formData = ArrayHelper::except($data, [
678 '__fluent_form_embded_post_id',
679 '_fluentform_' . $formId . '_fluentformnonce',
680 '_wp_http_referer'
681 ]);
682
683 $entryItems = [];
684 foreach ($formData as $dataKey => $dataValue) {
685 if (!$dataValue) {
686 continue;
687 }
688
689 if (is_array($dataValue)) {
690 foreach ($dataValue as $subKey => $subValue) {
691 $entryItems[] = [
692 'form_id' => $formId,
693 'submission_id' => $entryId,
694 'field_name' => $dataKey,
695 'sub_field_name' => $subKey,
696 'field_value' => maybe_serialize($subValue)
697 ];
698 }
699 } else {
700 $entryItems[] = [
701 'form_id' => $formId,
702 'submission_id' => $entryId,
703 'field_name' => $dataKey,
704 'sub_field_name' => '',
705 'field_value' => $dataValue
706 ];
707 }
708 }
709
710 foreach ($entryItems as $entryItem) {
711 wpFluent()->table('fluentform_entry_details')->insert($entryItem);
712 }
713
714 return true;
715 }
716
717 public function updateEntryDiffs($entryId, $formId, $formData)
718 {
719 wpFluent()->table('fluentform_entry_details')
720 ->where('submission_id', $entryId)
721 ->where('form_id', $formId)
722 ->whereIn('field_name', array_keys($formData))
723 ->delete();
724
725 $entryItems = [];
726 foreach ($formData as $dataKey => $dataValue) {
727 if (!$dataValue) {
728 continue;
729 }
730
731 if (is_array($dataValue)) {
732 foreach ($dataValue as $subKey => $subValue) {
733 $entryItems[] = [
734 'form_id' => $formId,
735 'submission_id' => $entryId,
736 'field_name' => $dataKey,
737 'sub_field_name' => $subKey,
738 'field_value' => maybe_serialize($subValue)
739 ];
740 }
741 } else {
742 $entryItems[] = [
743 'form_id' => $formId,
744 'submission_id' => $entryId,
745 'field_name' => $dataKey,
746 'sub_field_name' => '',
747 'field_value' => $dataValue
748 ];
749 }
750 }
751
752 foreach ($entryItems as $entryItem) {
753 wpFluent()->table('fluentform_entry_details')->insert($entryItem);
754 }
755
756 return true;
757 }
758 }
759