594 lines
21 KiB
PHP
594 lines
21 KiB
PHP
<?php
|
|
|
|
namespace FluentForm\App\Services\Submission;
|
|
|
|
use Exception;
|
|
use FluentForm\App\Models\EntryDetails;
|
|
use FluentForm\App\Models\Form;
|
|
use FluentForm\App\Helpers\Helper;
|
|
use FluentForm\App\Models\FormMeta;
|
|
use FluentForm\App\Models\Submission;
|
|
use FluentForm\Framework\Support\Arr;
|
|
use FluentForm\App\Models\SubmissionMeta;
|
|
use FluentForm\Framework\Support\Collection;
|
|
use FluentForm\App\Services\Form\FormService;
|
|
use FluentForm\App\Modules\Form\FormDataParser;
|
|
use FluentForm\App\Modules\Form\FormFieldsParser;
|
|
|
|
class SubmissionService
|
|
{
|
|
/**
|
|
* @var \FluentForm\App\Models\Submission|\FluentForm\Framework\Database\Query\Builder|\FluentForm\Framework\Database\Orm\Builder
|
|
*/
|
|
protected $model;
|
|
protected $formService;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->model = new Submission();
|
|
$this->formService = new FormService();
|
|
}
|
|
|
|
public function get($attributes = [])
|
|
{
|
|
if (!defined('FLUENTFORM_RENDERING_ENTRIES')) {
|
|
define('FLUENTFORM_RENDERING_ENTRIES', true);
|
|
}
|
|
|
|
$entries = $this->model->paginateEntries($attributes);
|
|
|
|
if (Arr::get($attributes, 'parse_entry')) {
|
|
$form = Form::find(Arr::get($attributes, 'form_id'));
|
|
|
|
$parsedEntries = FormDataParser::parseFormEntries($entries->items(), $form);
|
|
|
|
$entries->setCollection(Collection::make($parsedEntries));
|
|
}
|
|
|
|
return apply_filters('fluentform/get_submissions', $entries);
|
|
}
|
|
|
|
public function find($submissionId)
|
|
{
|
|
try {
|
|
if (!defined('FLUENTFORM_RENDERING_ENTRY')) {
|
|
define('FLUENTFORM_RENDERING_ENTRY', true);
|
|
}
|
|
|
|
$submission = $this->model->with(['form'])->findOrFail($submissionId);
|
|
|
|
$form = $submission->form;
|
|
|
|
$autoRead = apply_filters_deprecated(
|
|
'fluentform_auto_read',
|
|
[true, $form],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/auto_read_submission'
|
|
);
|
|
|
|
$autoRead = apply_filters('fluentform/auto_read_submission', $autoRead, $form);
|
|
|
|
if ('unread' === $submission->status && $autoRead) {
|
|
$submission->fill(['status' => 'read'])->save();
|
|
}
|
|
|
|
$submission = FormDataParser::parseFormEntry($submission, $form, null, true);
|
|
|
|
|
|
if ($submission->user_id) {
|
|
$user = get_user_by('ID', $submission->user_id);
|
|
$userDisplayName = trim($user->first_name . ' ' . $user->last_name);
|
|
if (!$userDisplayName) {
|
|
$userDisplayName = $user->display_name;
|
|
}
|
|
|
|
if ($user) {
|
|
$submission->user = [
|
|
'ID' => $user->ID,
|
|
'name' => $userDisplayName,
|
|
'permalink' => get_edit_user_link($user->ID)
|
|
];
|
|
}
|
|
}
|
|
|
|
$submission = apply_filters_deprecated(
|
|
'fluentform_single_response_data',
|
|
[$submission, $form->id],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/find_submission'
|
|
);
|
|
|
|
return apply_filters('fluentform/find_submission', $submission, $form->id)->makeHidden('form');
|
|
} catch (Exception $e) {
|
|
throw new Exception(
|
|
__('No Entry found.', 'fluentform')
|
|
);
|
|
}
|
|
}
|
|
|
|
public function resources($attributes)
|
|
{
|
|
$resources = [];
|
|
|
|
$formId = Arr::get($attributes, 'form_id');
|
|
$submissionId = Arr::get($attributes, 'entry_id');
|
|
|
|
if (Arr::get($attributes, 'counts')) {
|
|
$resources['counts'] = $this->model->countByGroup($formId);
|
|
}
|
|
|
|
$formInputsAndLabels = null;
|
|
|
|
$wantsLabels = Arr::get($attributes, 'labels');
|
|
|
|
if ($wantsLabels) {
|
|
$formInputsAndLabels = $this->formService->getInputsAndLabels($formId);
|
|
$resources['labels'] = $formInputsAndLabels['labels'];
|
|
}
|
|
|
|
if (Arr::get($attributes, 'fields')) {
|
|
$formInputsAndLabels = $formInputsAndLabels ? $formInputsAndLabels : $this->formService->getInputsAndLabels($formId);
|
|
$resources['fields'] = $formInputsAndLabels['inputs'];
|
|
}
|
|
|
|
if (Arr::get($attributes, 'visibleColumns')) {
|
|
$resources['visibleColumns'] = Helper::getFormMeta($formId, '_visible_columns', null);
|
|
}
|
|
|
|
if (Arr::get($attributes, 'columnsOrder')) {
|
|
$resources['columnsOrder'] = Helper::getFormMeta($formId, '_columns_order', null);
|
|
}
|
|
|
|
if (Arr::get($attributes, 'next')) {
|
|
$resources['next'] = $this->model->findAdjacentSubmission($attributes);
|
|
}
|
|
|
|
if (Arr::get($attributes, 'previous')) {
|
|
$attributes['direction'] = 'previous';
|
|
$resources['previous'] = $this->model->findAdjacentSubmission($attributes);
|
|
}
|
|
if (count(array_intersect(['orderData', 'widgets', 'cards'], array_keys($attributes))) > 0) {
|
|
try {
|
|
$submission = $this->model->with('form')->findOrFail($submissionId);
|
|
} catch (Exception $e) {
|
|
throw new Exception(
|
|
__('No Entry found.', 'fluentform')
|
|
);
|
|
}
|
|
|
|
if (Arr::get($attributes, 'orderData')) {
|
|
$hasPayment = $submission->payment_status || $submission->payment_total || 'subscription' === $submission->payment_type;
|
|
|
|
if ($hasPayment) {
|
|
$resources['orderData'] = apply_filters(
|
|
'fluentform/submission_order_data',
|
|
false,
|
|
$submission,
|
|
$submission->form
|
|
);
|
|
|
|
if ($wantsLabels) {
|
|
$resources['labels'] = apply_filters(
|
|
'fluentform/submission_labels',
|
|
$resources['labels'],
|
|
$submission,
|
|
$submission->form
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Arr::get($attributes, 'widgets')) {
|
|
$resources['widgets'] = apply_filters(
|
|
'fluentform/submissions_widgets', [], $resources, $submission
|
|
);
|
|
}
|
|
|
|
if (Arr::get($attributes, 'cards')) {
|
|
$resources['cards'] = apply_filters(
|
|
'fluentform/submission_cards', [], $resources, $submission
|
|
);
|
|
}
|
|
}
|
|
|
|
return apply_filters('fluentform/submission_resources', $resources);
|
|
}
|
|
|
|
public function updateStatus($attributes = [])
|
|
{
|
|
$submissionId = intval(Arr::get($attributes, 'entry_id'));
|
|
|
|
$status = sanitize_text_field(Arr::get($attributes, 'status'));
|
|
|
|
$this->model->amend($submissionId, ['status' => $status]);
|
|
|
|
do_action('fluentform/after_submission_status_update', $submissionId, $status);
|
|
|
|
return $status;
|
|
}
|
|
|
|
public function toggleIsFavorite($submissionId)
|
|
{
|
|
try {
|
|
$submission = $this->model->findOrFail($submissionId);
|
|
} catch (Exception $e) {
|
|
throw new Exception(
|
|
__('No Entry found.', 'fluentform')
|
|
);
|
|
}
|
|
|
|
if ($submission->is_favourite) {
|
|
$message = __('The entry has been removed from favorites', 'fluentform');
|
|
} else {
|
|
$message = __('The entry has been marked as favorites', 'fluentform');
|
|
}
|
|
|
|
$submission->fill(['is_favourite' => !$submission->is_favourite])->save();
|
|
|
|
return [$message, $submission->is_favourite];
|
|
}
|
|
|
|
public function storeColumnSettings($attributes = [])
|
|
{
|
|
$formId = Arr::get($attributes, 'form_id');
|
|
$metaKey = sanitize_text_field(Arr::get($attributes, 'meta_key'));
|
|
$metaValue = wp_unslash(Arr::get($attributes, 'settings'));
|
|
|
|
FormMeta::persist($formId, $metaKey, $metaValue);
|
|
}
|
|
|
|
public function handleBulkActions($attributes = [])
|
|
{
|
|
$formId = Arr::get($attributes, 'form_id');
|
|
|
|
$submissionIds = fluentFormSanitizer(Arr::get($attributes, 'entries', []));
|
|
|
|
$actionType = sanitize_text_field(Arr::get($attributes, 'action_type'));
|
|
|
|
if (!$formId || !count($submissionIds)) {
|
|
throw new Exception(__('Please select entries first', 'fluentform'));
|
|
}
|
|
|
|
$query = $this->model->where('form_id', $formId)->whereIn('id', $submissionIds);
|
|
|
|
$statuses = Helper::getEntryStatuses($formId);
|
|
|
|
$message = '';
|
|
|
|
if (isset($statuses[$actionType])) {
|
|
$query->update([
|
|
'status' => $actionType,
|
|
'updated_at' => current_time('mysql'),
|
|
]);
|
|
|
|
$message = 'Selected entries successfully marked as ' . $statuses[$actionType];
|
|
} elseif ('other.delete_permanently' == $actionType) {
|
|
$this->deleteEntries($submissionIds, $formId);
|
|
|
|
$message = __('Selected entries successfully deleted', 'fluentform');
|
|
} elseif ('other.make_favorite' == $actionType) {
|
|
$query->update([
|
|
'is_favourite' => 1,
|
|
]);
|
|
|
|
$message = __('Selected entries successfully marked as favorites', 'fluentform');
|
|
} elseif ('other.unmark_favorite' == $actionType) {
|
|
$query->update([
|
|
'is_favourite' => 0,
|
|
]);
|
|
|
|
$message = __('Selected entries successfully removed from favorites', 'fluentform');
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
|
|
public function deleteEntries($submissionIds, $formId)
|
|
{
|
|
$submissionIds = (array)$submissionIds;
|
|
|
|
do_action('fluentform/before_deleting_entries', $submissionIds, $formId);
|
|
|
|
foreach ($submissionIds as $submissionId) {
|
|
do_action_deprecated(
|
|
'fluentform_before_entry_deleted',
|
|
[$submissionId, $formId],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/before_deleting_entries'
|
|
);
|
|
}
|
|
|
|
$this->deleteFiles($submissionIds, $formId);
|
|
|
|
Submission::remove($submissionIds);
|
|
|
|
do_action('fluentform/after_deleting_submissions', $submissionIds, $formId);
|
|
|
|
foreach ($submissionIds as $submissionId) {
|
|
do_action_deprecated(
|
|
'fluentform_after_entry_deleted',
|
|
[$submissionId, $formId],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/after_deleting_entries'
|
|
);
|
|
}
|
|
}
|
|
|
|
public function deleteFiles($submissionIds, $formId)
|
|
{
|
|
apply_filters_deprecated(
|
|
'fluentform_disable_attachment_delete',
|
|
[
|
|
false,
|
|
$formId
|
|
],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/disable_attachment_delete',
|
|
'Use fluentform/disable_attachment_delete instead of fluentform_disable_attachment_delete'
|
|
);
|
|
|
|
$disableAttachmentDelete = apply_filters(
|
|
'fluentform/disable_attachment_delete', false, $formId
|
|
);
|
|
|
|
$shouldDelete = defined('FLUENTFORMPRO') && $formId && !$disableAttachmentDelete;
|
|
|
|
if ($shouldDelete) {
|
|
$deletables = $this->getAttachments($submissionIds, $formId);
|
|
|
|
foreach ($deletables as $file) {
|
|
$file = wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/' . basename($file);
|
|
|
|
if (is_readable($file) && !is_dir($file)) {
|
|
@unlink($file);
|
|
}
|
|
}
|
|
// Empty Temp Uploads
|
|
if (defined('FLUENTFORMPRO')) {
|
|
$tempDir = wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/temp/';
|
|
$files = glob($tempDir . '*');
|
|
if(!empty($files)){
|
|
foreach ($files as $file) {
|
|
if (basename($file) !== 'index.php') {
|
|
unlink($file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public function getAttachments($submissionIds, $form)
|
|
{
|
|
$submissionIds = (array)$submissionIds;
|
|
|
|
if (!$form instanceof Form) {
|
|
$form = Form::find($form);
|
|
}
|
|
|
|
$fields = FormFieldsParser::getAttachmentInputFields($form, ['element', 'attributes']);
|
|
|
|
$attachments = [];
|
|
|
|
if ($fields) {
|
|
$fields = Arr::pluck($fields, 'attributes.name');
|
|
|
|
$submissions = $this->model->whereIn('id', $submissionIds)->get();
|
|
|
|
foreach ($submissions as $submission) {
|
|
$response = json_decode($submission->response, true);
|
|
|
|
$files = Arr::collapse(Arr::only($response, $fields));
|
|
|
|
$attachments = array_merge($attachments, $files);
|
|
}
|
|
}
|
|
|
|
return $attachments;
|
|
}
|
|
|
|
public function getNotes($submissionId, $attributes)
|
|
{
|
|
$formId = (int)Arr::get($attributes, 'form_id');
|
|
$apiLog = 'yes' === sanitize_text_field(Arr::get($attributes, 'api_log'));
|
|
|
|
$metaKeys = ['_notes'];
|
|
|
|
if ($apiLog) {
|
|
$metaKeys[] = 'api_log';
|
|
}
|
|
|
|
$notes = SubmissionMeta::where('response_id', $submissionId)
|
|
->whereIn('meta_key', $metaKeys)
|
|
->orderBy('id', 'DESC')
|
|
->get();
|
|
|
|
foreach ($notes as $note) {
|
|
if ($note->user_id) {
|
|
$note->pemalink = get_edit_user_link($note->user_id);
|
|
$user = get_user_by('ID', $note->user_id);
|
|
|
|
if ($user) {
|
|
$note->created_by = $user->display_name;
|
|
} else {
|
|
$note->created_by = __('Fluent Forms Bot', 'fluentform');
|
|
}
|
|
} else {
|
|
$note->pemalink = false;
|
|
}
|
|
}
|
|
|
|
apply_filters_deprecated(
|
|
'fluentform_entry_notes',
|
|
[
|
|
$notes,
|
|
$submissionId,
|
|
$formId
|
|
],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/entry_notes',
|
|
'Use fluentform/entry_notes instead of fluentform_entry_notes'
|
|
);
|
|
|
|
$notes = apply_filters('fluentform/entry_notes', $notes, $submissionId, $formId);
|
|
|
|
return apply_filters('fluentform/submission_notes', $notes, $submissionId, $formId);
|
|
}
|
|
|
|
public function storeNote($submissionId, $attributes = [])
|
|
{
|
|
$formId = (int)Arr::get($attributes, 'form_id');
|
|
|
|
$content = sanitize_textarea_field($attributes['note']['content']);
|
|
$status = sanitize_text_field($attributes['note']['status']);
|
|
$user = get_user_by('ID', get_current_user_id());
|
|
$now = current_time('mysql');
|
|
|
|
$note = [
|
|
'response_id' => $submissionId,
|
|
'form_id' => $formId,
|
|
'meta_key' => '_notes',
|
|
'value' => $content,
|
|
'status' => $status,
|
|
'user_id' => $user->ID,
|
|
'name' => $user->display_name,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
];
|
|
|
|
$note = apply_filters_deprecated(
|
|
'fluentform_add_response_note',
|
|
[$note],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/store_submission_note'
|
|
);
|
|
|
|
$note = apply_filters('fluentform/store_submission_note', $note);
|
|
|
|
$submissionMeta = new SubmissionMeta;
|
|
|
|
$submissionMeta->fill($note)->save();
|
|
|
|
do_action_deprecated(
|
|
'fluentform_new_response_note_added',
|
|
[$submissionMeta->id, $submissionMeta],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/submission_note_stored'
|
|
);
|
|
|
|
do_action('fluentform/submission_note_stored', $submissionMeta->id, $submissionMeta);
|
|
|
|
return [
|
|
'message' => __('Note has been successfully added', 'fluentform'),
|
|
'note' => $submissionMeta,
|
|
'insert_id' => $submissionMeta->id,
|
|
];
|
|
}
|
|
|
|
public function updateSubmissionUser($userId, $submissionId)
|
|
{
|
|
if (!$userId || !$submissionId) {
|
|
throw new Exception(__('Submission ID and User ID is required', 'fluentform'));
|
|
}
|
|
|
|
$submission = Submission::find($submissionId);
|
|
$user = get_user_by('ID', $userId);
|
|
|
|
if (!$submission || $submission->user_id == $userId || !$user) {
|
|
throw new Exception(__('Invalid Request', 'fluentform'));
|
|
}
|
|
|
|
Submission::where('id', $submission->id)
|
|
->update([
|
|
'user_id' => $userId,
|
|
'updated_at' => current_time('mysql'),
|
|
]);
|
|
|
|
if (defined('FLUENTFORMPRO')) {
|
|
// let's update the corresponding user IDs for transactions and
|
|
wpFluent()->table('fluentform_transactions')
|
|
->where('submission_id', $submission->id)
|
|
->update([
|
|
'user_id' => $userId,
|
|
'updated_at' => current_time('mysql'),
|
|
]);
|
|
}
|
|
|
|
do_action('fluentform/log_data', [
|
|
'parent_source_id' => $submission->form_id,
|
|
'source_type' => 'submission_item',
|
|
'source_id' => $submission->id,
|
|
'component' => 'General',
|
|
'status' => 'info',
|
|
'title' => 'Associate user has been changed from ' . $submission->user_id . ' to ' . $userId,
|
|
]);
|
|
|
|
do_action_deprecated(
|
|
'fluentform_submission_user_changed',
|
|
[
|
|
$submission,
|
|
$user
|
|
],
|
|
FLUENTFORM_FRAMEWORK_UPGRADE,
|
|
'fluentform/submission_user_changed',
|
|
'Use fluentform/submission_user_changed instead of fluentform_submission_user_changed.'
|
|
);
|
|
|
|
do_action('fluentform/submission_user_changed', $submission, $user);
|
|
|
|
return ([
|
|
'message' => __('Selected user has been successfully assigned to this submission', 'fluentform'),
|
|
'user' => [
|
|
'name' => $user->display_name,
|
|
'email' => $user->user_email,
|
|
'ID' => $user->ID,
|
|
'permalink' => get_edit_user_link($user->ID),
|
|
],
|
|
'user_id' => $userId,
|
|
]);
|
|
}
|
|
|
|
public function recordEntryDetails($entryId, $formId, $data)
|
|
{
|
|
$formData = Arr::except($data, Helper::getWhiteListedFields($formId));
|
|
|
|
$entryItems = [];
|
|
foreach ($formData as $dataKey => $dataValue) {
|
|
if (empty($dataValue)) {
|
|
continue;
|
|
}
|
|
|
|
if (is_array($dataValue) || is_object($dataValue)) {
|
|
foreach ($dataValue as $subKey => $subValue) {
|
|
if (empty($subValue)) {
|
|
continue;
|
|
}
|
|
$entryItems[] = [
|
|
'form_id' => $formId,
|
|
'submission_id' => $entryId,
|
|
'field_name' => trim($dataKey),
|
|
'sub_field_name' => $subKey,
|
|
'field_value' => maybe_serialize($subValue),
|
|
];
|
|
}
|
|
} else {
|
|
$entryItems[] = [
|
|
'form_id' => $formId,
|
|
'submission_id' => $entryId,
|
|
'field_name' => trim($dataKey),
|
|
'sub_field_name' => '',
|
|
'field_value' => $dataValue,
|
|
];
|
|
}
|
|
}
|
|
|
|
foreach ($entryItems as $entryItem) {
|
|
EntryDetails::insert($entryItem);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|