--- a/fluentform/app/Api/Form.php
+++ b/fluentform/app/Api/Form.php
@@ -33,6 +33,7 @@
$is_filter_by_conv_or_step_form = $filter_by && ('conv_form' == $filter_by || 'step_form' == $filter_by);
$shortColumn = sanitize_sql_orderby(ArrayHelper::get($atts, 'sort_column', 'id'));
+ $shortColumn = $shortColumn !== false && $shortColumn !== '' ? $shortColumn : 'id';
$sortBy = Helper::sanitizeOrderValue(ArrayHelper::get($atts, 'sort_by', 'DESC'));
$query = FluentFormAppModelsForm::orderBy($shortColumn, $sortBy)->getQuery();
--- a/fluentform/app/Http/Controllers/FormController.php
+++ b/fluentform/app/Http/Controllers/FormController.php
@@ -5,39 +5,52 @@
use Exception;
use FluentFormAppServicesFormFormService;
use FluentFormAppServicesFormHistoryService;
+use FluentFormFrameworkSupportArr;
class FormController extends Controller
{
/**
* Get the paginated forms matching search criteria.
*
- * @param FluentFormAppServicesFormFormService $formService
+ * @param FluentFormAppServicesFormFormService $formService
+ *
* @return WP_REST_Response
*/
public function index(FormService $formService)
{
+ $attributes = $this->request->all();
+
return $this->sendSuccess(
- $formService->get($this->request->all())
+ $formService->get($attributes)
);
}
-
+
/**
* Create a form from backend/editor
*
- * @param FluentFormAppServicesFormFormService $formService
+ * @param FluentFormAppServicesFormFormService $formService
+ *
* @return WP_REST_Response
*/
public function store(FormService $formService)
{
try {
- $form = $formService->store($this->request->all());
-
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'title' => 'sanitize_text_field',
+ 'template_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $form = $formService->store($attributes);
+
return $this->sendSuccess([
'formId' => $form->id,
'redirect_url' => admin_url(
'admin.php?page=fluent_forms&form_id=' . $form->id . '&route=editor'
),
- 'message' => __('Successfully created a form.', 'fluentform'),
+ 'message' => __('Successfully created a form.', 'fluentform'),
]);
} catch (Exception $e) {
return $this->sendError([
@@ -45,12 +58,19 @@
], 422);
}
}
-
+
public function duplicate(FormService $formService)
{
try {
- $form = $formService->duplicate($this->request->all());
-
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'form_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $form = $formService->duplicate($attributes);
+
return $this->sendSuccess([
'message' => __('Form has been successfully duplicated.', 'fluentform'),
'form_id' => $form->id,
@@ -62,14 +82,14 @@
], 422);
}
}
-
+
public function find(FormService $formService)
{
try {
- $id = $this->request->get('form_id');
-
+ $id = (int)$this->request->get('form_id');
+
$form = $formService->find($id);
-
+
return $this->sendSuccess($form, 200);
} catch (Exception $e) {
return $this->sendError([
@@ -77,14 +97,14 @@
], 422);
}
}
-
+
public function delete(FormService $formService)
{
try {
- $id = $this->request->get('form_id');
-
+ $id = (int)$this->request->get('form_id');
+
$formService->delete($id);
-
+
return $this->sendSuccess([
'message' => __('Successfully deleted the form.', 'fluentform'),
], 200);
@@ -94,12 +114,14 @@
], 422);
}
}
-
+
public function update(FormService $formService)
{
try {
- $formService->update($this->request->all());
-
+ $attributes = $this->request->all();
+
+ $formService->update($attributes);
+
return $this->sendSuccess([
'message' => __('The form is successfully updated.', 'fluentform'),
], 200);
@@ -109,12 +131,13 @@
], 422);
}
}
-
+
public function convert(FormService $formService)
{
try {
- $formService->convert($this->request->get('form_id'));
-
+ $formId = (int)$this->request->get('form_id');
+ $formService->convert($formId);
+
return $this->sendSuccess([
'message' => __('The form is successfully converted.', 'fluentform'),
], 200);
@@ -124,7 +147,7 @@
], 422);
}
}
-
+
public function templates(FormService $formService)
{
try {
@@ -135,13 +158,13 @@
], 422);
}
}
-
+
public function resources(FormService $formService, $formId)
{
$components = $formService->components($formId);
-
+
$disabledComponents = $formService->getDisabledComponents();
-
+
return $this->sendSuccess([
'components' => $components,
'disabled_components' => $disabledComponents,
@@ -149,21 +172,22 @@
'edit_history' => HistoryService::get($formId)
]);
}
-
+
public function fields(FormService $formService, $formId)
{
return $this->sendSuccess($formService->fields($formId));
}
-
+
public function shortcodes(FormService $formService, $formId)
{
return $this->sendSuccess($formService->shortcodes($formId));
}
-
+
public function pages(FormService $formService)
{
return $this->sendSuccess($formService->pages());
}
+
public function findShortCodePage(FormService $formService, $formId)
{
return $this->sendSuccess($formService->findShortCodePage($formId));
@@ -172,13 +196,13 @@
public function formEditHistory(HistoryService $historyService, $formId)
{
return $this->sendSuccess($historyService::get($formId));
-
}
+
public function clearEditHistory(HistoryService $historyService)
{
try {
- $id = (int)$this->request->get('form_id');
-
+ $id = (int)$this->request->get('form_id');
+
$historyService->delete($id);
return $this->sendSuccess([
'message' => __('Successfully deleted edit history.', 'fluentform'),
@@ -188,8 +212,8 @@
'message' => $e->getMessage(),
], 422);
}
-
}
+
public function ping()
{
return ['message' => 'pong'];
--- a/fluentform/app/Http/Controllers/FormIntegrationController.php
+++ b/fluentform/app/Http/Controllers/FormIntegrationController.php
@@ -47,7 +47,7 @@
public function delete(FormIntegrationService $integrationService)
{
try {
- $id = $this->request->get('integration_id');
+ $id = intval($this->request->get('integration_id'));
$integrationService->delete($id);
return $this->sendSuccess([
'message' => __('Successfully deleted the Integration.', 'fluentform'),
@@ -62,9 +62,17 @@
public function integrationListComponent()
{
try {
- $integrationName = $this->request->get('integration_name');
- $formId = intval($this->request->get('form_id'));
- $listId = $this->request->get('list_id');
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'integration_name' => 'sanitize_text_field',
+ 'list_id' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $integrationName = $attributes['integration_name'];
+ $formId = (int)$attributes['form_id'];
+ $listId = $attributes['list_id'];
$merge_fields = false;
$merge_fields = apply_filters_deprecated(
'fluentform_get_integration_merge_fields_' . $integrationName,
--- a/fluentform/app/Http/Controllers/IntegrationManagerController.php
+++ b/fluentform/app/Http/Controllers/IntegrationManagerController.php
@@ -37,9 +37,10 @@
$this->priority = $priority;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Constructor, nonce verified in route handlers
- if(isset($_REQUEST['form_id'])) {
+ $formId = $this->app->request->get('form_id');
+ if($formId) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Constructor, nonce verified in route handlers
- $formId = (int)$_REQUEST['form_id'];
+ $formId = (int)$formId;
parent::__construct(
$this->settingsKey, $formId, true
);
--- a/fluentform/app/Http/Controllers/LogController.php
+++ b/fluentform/app/Http/Controllers/LogController.php
@@ -10,8 +10,19 @@
public function get(Logger $logger)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'form_id' => 'intval',
+ 'page' => 'intval',
+ 'per_page' => 'intval',
+ 'search' => 'sanitize_text_field',
+ 'log_type' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $logger->get($this->request->all())
+ $logger->get($attributes)
);
} catch (Exception $e) {
return $this->sendError([
@@ -24,8 +35,15 @@
public function getFilters(Logger $logger)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'form_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $logger->getFilters($this->request->all())
+ $logger->getFilters($attributes)
);
} catch (Exception $e) {
return $this->sendError([
@@ -38,8 +56,15 @@
public function remove(Logger $logger)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'log_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $logger->remove($this->request->all())
+ $logger->remove($attributes)
);
} catch (Exception $e) {
return $this->sendError([
--- a/fluentform/app/Http/Controllers/ManagersController.php
+++ b/fluentform/app/Http/Controllers/ManagersController.php
@@ -9,14 +9,28 @@
{
public function index(ManagerService $managerService)
{
- $result = $managerService->getManagers($this->request->all());
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'search' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $result = $managerService->getManagers($attributes);
return $this->sendSuccess($result);
}
public function addManager(ManagerService $managerService)
{
try {
- $result = $managerService->addManager($this->request->all());
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'user_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $result = $managerService->addManager($attributes);
return $this->sendSuccess($result);
} catch (ValidationException $exception) {
return $this->sendError($exception->errors(), 422);
@@ -26,7 +40,14 @@
public function removeManager(ManagerService $managerService)
{
try {
- $result = $managerService->removeManager($this->request->all());
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'user_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $result = $managerService->removeManager($attributes);
return $this->sendSuccess($result);
} catch (ValidationException $exception) {
return $this->sendError($exception->errors(), 422);
--- a/fluentform/app/Http/Controllers/RolesController.php
+++ b/fluentform/app/Http/Controllers/RolesController.php
@@ -9,14 +9,29 @@
{
public function index(RolesService $rolesService)
{
- $result = $rolesService->getRoles($this->request->all());
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'search' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $result = $rolesService->getRoles($attributes);
return $this->sendSuccess($result);
}
public function addCapability(RolesService $rolesService)
{
try {
- $result = $rolesService->setCapability($this->request->all());
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'role' => 'sanitize_text_field',
+ 'capability' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $result = $rolesService->setCapability($attributes);
return $this->sendSuccess($result);
} catch (ValidationException $exception) {
return $this->sendError($exception->errors(), 422);
--- a/fluentform/app/Http/Controllers/SubmissionController.php
+++ b/fluentform/app/Http/Controllers/SubmissionController.php
@@ -5,14 +5,42 @@
use Exception;
use FluentFormAppModelsSubmission;
use FluentFormAppServicesSubmissionSubmissionService;
+use FluentFormFrameworkSupportArr;
class SubmissionController extends Controller
{
public function index(SubmissionService $submissionService)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'search' => 'sanitize_text_field',
+ 'status' => 'sanitize_text_field',
+ 'entry_type' => 'sanitize_text_field',
+ 'form_id' => 'intval',
+ 'per_page' => 'intval',
+ 'page' => 'intval',
+ 'is_favourite' => 'rest_sanitize_boolean',
+ ];
+
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+
+ // If frontend sends `entry_type` (used by some components), map it to `status`
+ if (isset($attributes['entry_type']) && !isset($attributes['status'])) {
+ $attributes['status'] = $attributes['entry_type'];
+ }
+
+ if (isset($attributes['date_range']) && is_array($attributes['date_range'])) {
+ $attributes['date_range'] = array_map('sanitize_text_field', $attributes['date_range']);
+ }
+ if (isset($attributes['payment_statuses']) && is_array($attributes['payment_statuses'])) {
+ $attributes['payment_statuses'] = array_map('sanitize_text_field', $attributes['payment_statuses']);
+ }
+
return $this->sendSuccess(
- $submissionService->get($this->request->all())
+ $submissionService->get($attributes)
);
} catch (Exception $e) {
return $this->sendError([
@@ -37,8 +65,15 @@
public function resources(SubmissionService $submissionService)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'form_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $submissionService->resources($this->request->all())
+ $submissionService->resources($attributes)
);
} catch (Exception $e) {
return $this->sendError([
@@ -166,8 +201,36 @@
public function all(Submission $submission)
{
try {
+ $attributes = $this->request->all();
+
+ // Use backend sanitizer map for scalar fields (preserves expected types)
+ $sanitizeMap = [
+ 'search' => 'sanitize_text_field',
+ 'status' => 'sanitize_text_field',
+ 'entry_type' => 'sanitize_text_field',
+ 'form_id' => 'intval',
+ 'per_page' => 'intval',
+ 'page' => 'intval',
+ 'is_favourite' => 'rest_sanitize_boolean',
+ ];
+
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ // Handle frontend `entry_type` param (sanitize and map to `status` if needed)
+ if (isset($attributes['entry_type']) && !isset($attributes['status'])) {
+ $attributes['status'] = $attributes['entry_type'];
+ }
+
+ // Sanitize array fields explicitly (sanitizer recurses but won't apply parent's key sanitizer to numeric child keys)
+ if (isset($attributes['date_range']) && is_array($attributes['date_range'])) {
+ $attributes['date_range'] = array_map('sanitize_text_field', $attributes['date_range']);
+ }
+ if (isset($attributes['payment_statuses']) && is_array($attributes['payment_statuses'])) {
+ $attributes['payment_statuses'] = array_map('sanitize_text_field', $attributes['payment_statuses']);
+ }
+
return $this->sendSuccess(
- $submission->allSubmissions($this->request->all())
+ $submission->allSubmissions($attributes)
);
} catch (Exception $e) {
return $this->sendError([
@@ -183,8 +246,21 @@
public function print(SubmissionService $submissionService)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'entry_ids' => function($value) {
+ if (is_array($value)) {
+ return array_map('intval', $value);
+ }
+ return [];
+ },
+ 'form_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $submissionService->getPrintContent($this->request->all())
+ $submissionService->getPrintContent($attributes)
);
} catch (Exception $e) {
return $this->sendError([
--- a/fluentform/app/Http/Controllers/SubmissionLogController.php
+++ b/fluentform/app/Http/Controllers/SubmissionLogController.php
@@ -10,8 +10,16 @@
public function get(Logger $logger, $submissionId)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'page' => 'intval',
+ 'per_page' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $logger->getSubmissionLogs($submissionId, $this->request->all())
+ $logger->getSubmissionLogs($submissionId, $attributes)
);
} catch (Exception $e) {
return $this->sendError([
@@ -23,8 +31,16 @@
public function remove(Logger $logger)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'log_id' => 'intval',
+ 'submission_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $logger->remove($this->request->all())
+ $logger->remove($attributes)
);
} catch (Exception $e) {
return $this->sendError([
--- a/fluentform/app/Http/Controllers/SubmissionNoteController.php
+++ b/fluentform/app/Http/Controllers/SubmissionNoteController.php
@@ -10,8 +10,16 @@
public function get(SubmissionService $submissionService, $submissionId)
{
try {
+ $attributes = $this->request->all();
+
+ $sanitizeMap = [
+ 'page' => 'intval',
+ 'per_page' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
return $this->sendSuccess(
- $submissionService->getNotes($submissionId, $this->request->all())
+ $submissionService->getNotes($submissionId, $attributes)
);
} catch (Exception $exception) {
return $this->sendError([
@@ -23,8 +31,10 @@
public function store(SubmissionService $submissionService, $submissionId)
{
try {
+ $attributes = $this->request->all();
+
return $this->sendSuccess(
- $submissionService->storeNote($submissionId, $this->request->all())
+ $submissionService->storeNote($submissionId, $attributes)
);
} catch (Exception $exception) {
return $this->sendError([
--- a/fluentform/app/Modules/Ai/AiFormBuilder.php
+++ b/fluentform/app/Modules/Ai/AiFormBuilder.php
@@ -27,7 +27,7 @@
public function buildForm()
{
try {
- Acl::verifyNonce();
+ Acl::verify('fluentform_forms_manager');
$form = $this->generateForm($this->app->request->all());
$form = $this->prepareAndSaveForm($form);
wp_send_json_success([
@@ -440,8 +440,18 @@
throw new Exception(esc_html__('Query is empty!', 'fluentform'));
}
+ // Validate query length to prevent abuse (max 2000 characters)
+ if (strlen($query) > 2000) {
+ throw new Exception(esc_html__('Query is too long. Please limit your prompt to 2000 characters.', 'fluentform'));
+ }
+
$additionalQuery = Sanitizer::sanitizeTextField(Arr::get($args, 'additional_query'));
+ // Validate additional query length (max 1000 characters)
+ if ($additionalQuery && strlen($additionalQuery) > 1000) {
+ throw new Exception(esc_html__('Additional query is too long. Please limit to 1000 characters.', 'fluentform'));
+ }
+
if ($additionalQuery) {
$query .= "n including questions for information like " . $additionalQuery . ".";
}
--- a/fluentform/app/Modules/Payments/AjaxEndpoints.php
+++ b/fluentform/app/Modules/Payments/AjaxEndpoints.php
@@ -79,7 +79,14 @@
public function updateGlobalSettings()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, sanitized in updatePaymentSettings()
- $settings = isset($_REQUEST['settings']) ? wp_unslash($_REQUEST['settings']) : [];
+ $request = wpFluentForm()->request;
+ $settings = wp_unslash($request->get('settings', []));
+
+ $sanitizeMap = [
+ 'status' => 'sanitize_text_field',
+ 'currency' => 'sanitize_text_field',
+ ];
+ $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
// Update settings
$settings = PaymentHelper::updatePaymentSettings($settings);
@@ -96,7 +103,8 @@
public function getPaymentMethodSettings()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $method = isset($_REQUEST['method']) ? sanitize_text_field(wp_unslash($_REQUEST['method'])) : '';
+ $request = wpFluentForm()->request;
+ $method = sanitize_text_field($request->get('method', ''));
$paymentSettings = apply_filters_deprecated(
'fluentform_payment_settings_' . $method,
@@ -118,9 +126,16 @@
public function savePaymentMethodSettings()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $method = isset($_REQUEST['method']) ? sanitize_text_field(wp_unslash($_REQUEST['method'])) : '';
+ $request = wpFluentForm()->request;
+ $method = sanitize_text_field($request->get('method', ''));
+ $settings = wp_unslash($request->get('settings', []));
+
+ $sanitizeMap = [
+ 'status' => 'sanitize_text_field',
+ ];
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, sanitized in validation filter
- $settings = isset($_REQUEST['settings']) ? wp_unslash($_REQUEST['settings']) : [];
+ $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
+
$settingsValidation = apply_filters_deprecated(
'fluentform_payment_method_settings_validation_' . $method,
@@ -163,8 +178,8 @@
public function getFormSettings()
{
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $formId = isset($_REQUEST['form_id']) ? (int) $_REQUEST['form_id'] : 0;
+ $request = wpFluentForm()->request;
+ $formId = intval($request->get('form_id', 0));
$settings = PaymentHelper::getFormSettings($formId, 'admin');
$form = wpFluent()->table('fluentform_forms')->find($formId);
$addressFields = array_values(FormFieldsParser::getAddressFields($form));
@@ -184,9 +199,17 @@
public function saveFormSettings()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $formId = isset($_REQUEST['form_id']) ? (int) $_REQUEST['form_id'] : 0;
+ $request = wpFluentForm()->request;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, sanitized in setFormMeta()
- $settings = isset($_REQUEST['settings']) ? wp_unslash($_REQUEST['settings']) : [];
+ $formId = intval($request->get('form_id', 0));
+ $settings = wp_unslash($request->get('settings', []));
+
+ $sanitizeMap = [
+ 'enabled' => 'rest_sanitize_boolean',
+ 'currency' => 'sanitize_text_field',
+ ];
+ $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
+
Helper::setFormMeta($formId, '_payment_settings', $settings);
wp_send_json_success([
@@ -197,8 +220,35 @@
public function updateTransaction()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Nonce verified in route registration, data sanitized below
- $transactionData = isset($_REQUEST['transaction']) ? $_REQUEST['transaction'] : [];
- $transactionId = (int) $transactionData['id'];
+ $request = wpFluentForm()->request;
+ $transactionData = $request->get('transaction', []);
+ if (is_array($transactionData)) {
+ $transactionData['id'] = intval(ArrayHelper::get($transactionData, 'id'));
+ $transactionData['status'] = sanitize_text_field(ArrayHelper::get($transactionData, 'status'));
+ $transactionData['payer_name'] = sanitize_text_field(ArrayHelper::get($transactionData, 'payer_name'));
+ $transactionData['payer_email'] = sanitize_email(ArrayHelper::get($transactionData, 'payer_email'));
+ $transactionData['charge_id'] = sanitize_text_field(ArrayHelper::get($transactionData, 'charge_id'));
+ $transactionData['refund_amount'] = floatval(ArrayHelper::get($transactionData, 'refund_amount'));
+ $transactionData['refund_note'] = sanitize_text_field(ArrayHelper::get($transactionData, 'refund_note'));
+ $transactionData['should_run_actions'] = sanitize_text_field(ArrayHelper::get($transactionData, 'should_run_actions'));
+
+ // Handle billing_address and shipping_address
+ if (isset($transactionData['billing_address'])) {
+ $transactionData['billing_address'] = is_array($transactionData['billing_address'])
+ ? array_map('sanitize_text_field', $transactionData['billing_address'])
+ : sanitize_text_field($transactionData['billing_address']);
+ }
+ if (isset($transactionData['shipping_address'])) {
+ $transactionData['shipping_address'] = is_array($transactionData['shipping_address'])
+ ? array_map('sanitize_text_field', $transactionData['shipping_address'])
+ : sanitize_text_field($transactionData['shipping_address']);
+ }
+ }
+
+ // Sanitize subscription_id separately
+ $subscriptionId = intval($request->get('subscription_id', 0));
+
+ $transactionId = $transactionData['id'];
$oldTransaction = wpFluent()->table('fluentform_transactions')
->find($transactionId);
@@ -220,7 +270,6 @@
->update($updateData);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $subscriptionId = (int) ArrayHelper::get($_REQUEST, 'subscription_id', '0');
if ($subscriptionId) {
$existingSubscription = wpFluent()->table('fluentform_subscriptions')
->find($subscriptionId);
@@ -314,7 +363,15 @@
public function disconnectStripeConnect()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- return ConnectConfig::disconnect($_REQUEST, true);
+ $request = wpFluentForm()->request;
+ $attributes = $request->all();
+
+ $sanitizeMap = [
+ 'mode' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ return ConnectConfig::disconnect($attributes, true);
}
public function getWpPages()
@@ -334,7 +391,17 @@
public function cancelSubscription()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $subscriptionId = (int) ArrayHelper::get($_REQUEST, 'subscription_id');
+ $request = wpFluentForm()->request;
+ $attributes = $request->all();
+
+ $sanitizeMap = [
+ 'subscription_id' => 'intval',
+ 'transaction_id' => 'intval',
+ 'submission_id' => 'intval',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $subscriptionId = ArrayHelper::get($attributes, 'subscription_id');
$subscription = fluentFormApi('submissions')->getSubscription($subscriptionId);
@@ -345,9 +412,9 @@
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $transactionId = (int) ArrayHelper::get($_REQUEST, 'transaction_id', '0');
+ $transactionId = ArrayHelper::get($attributes, 'transaction_id', 0);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $submissionId = (int) ArrayHelper::get($_REQUEST, 'submission_id', '0');
+ $submissionId = ArrayHelper::get($attributes, 'submission_id', 0);
$oldTransaction = wpFluent()->table('fluentform_transactions')
->find($transactionId);
--- a/fluentform/app/Modules/Payments/Classes/PaymentEntries.php
+++ b/fluentform/app/Modules/Payments/Classes/PaymentEntries.php
@@ -42,10 +42,23 @@
public function getPayments()
{
+ $request = wpFluentForm()->request;
+ $attributes = $request->all();
+
+ // Sanitize request data
+ $sanitizeMap = [
+ 'form_id' => 'intval',
+ 'per_page' => 'intval',
+ 'payment_statuses' => 'sanitize_text_field',
+ 'payment_types' => 'sanitize_text_field',
+ 'payment_methods' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify() below
- Acl::verify('fluentform_view_payments', ArrayHelper::get($_REQUEST, 'form_id'));
+ Acl::verify('fluentform_view_payments', ArrayHelper::get($attributes, 'form_id'));
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify() above
- $perPage = isset($_REQUEST['per_page']) ? intval($_REQUEST['per_page']) : 10;
+ $perPage = ArrayHelper::get($attributes, 'per_page', 10);
if(!$perPage) {
$perPage = 10;
}
@@ -69,26 +82,22 @@
->join('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_transactions.form_id')
->orderBy('fluentform_transactions.id', 'DESC');
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify() at line 46
- if ($selectedFormId = ArrayHelper::get($_REQUEST, 'form_id')) {
- $paymentsQuery = $paymentsQuery->where('fluentform_transactions.form_id', intval($selectedFormId));
+ if ($selectedFormId = ArrayHelper::get($attributes, 'form_id')) {
+ $paymentsQuery = $paymentsQuery->where('fluentform_transactions.form_id', $selectedFormId);
}
$allowFormIds = apply_filters('fluentform/current_user_allowed_forms', false);
if ($allowFormIds && is_array($allowFormIds)) {
$paymentsQuery = $paymentsQuery->whereIn('fluentform_transactions.form_id', $allowFormIds);
}
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify() at line 46
- if ($paymentStatus = ArrayHelper::get($_REQUEST, 'payment_statuses')) {
- $paymentsQuery = $paymentsQuery->where('fluentform_transactions.status', sanitize_text_field($paymentStatus));
- }
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify() at line 46
- if ($paymentTypes = ArrayHelper::get($_REQUEST, 'payment_types')) {
- $paymentsQuery = $paymentsQuery->where('fluentform_transactions.transaction_type', sanitize_text_field($paymentTypes));
- }
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Acl::verify() at line 46
- if ($paymentMethods = ArrayHelper::get($_REQUEST, 'payment_methods')) {
- $paymentsQuery = $paymentsQuery->where('fluentform_transactions.payment_method', sanitize_text_field($paymentMethods));
+ if ($paymentStatus = ArrayHelper::get($attributes, 'payment_statuses')) {
+ $paymentsQuery = $paymentsQuery->where('fluentform_transactions.status', $paymentStatus);
+ }
+ if ($paymentTypes = ArrayHelper::get($attributes, 'payment_types')) {
+ $paymentsQuery = $paymentsQuery->where('fluentform_transactions.transaction_type', $paymentTypes);
+ }
+ if ($paymentMethods = ArrayHelper::get($attributes, 'payment_methods')) {
+ $paymentsQuery = $paymentsQuery->where('fluentform_transactions.payment_method', $paymentMethods);
}
$paymentsPaginate = $paymentsQuery->paginate($perPage);
@@ -114,10 +123,22 @@
{
Acl::verify('fluentform_forms_manager');
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified in route registration, data sanitized below
- $entries = isset($_REQUEST['entries']) ? wp_unslash($_REQUEST['entries']) : [];
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in route registration
- $actionType = isset($_REQUEST['action_type']) ? sanitize_text_field(wp_unslash($_REQUEST['action_type'])) : '';
+ $request = wpFluentForm()->request;
+ $attributes = $request->all();
+
+ $sanitizeMap = [
+ 'entries' => function($value) {
+ if (is_array($value)) {
+ return array_map('intval', $value);
+ }
+ return [];
+ },
+ 'action_type' => 'sanitize_text_field',
+ ];
+ $attributes = fluentform_backend_sanitizer($attributes, $sanitizeMap);
+
+ $entries = ArrayHelper::get($attributes, 'entries', []);
+ $actionType = ArrayHelper::get($attributes, 'action_type');
if (!$actionType || !count($entries)) {
wp_send_json_error([
'message' => __('Please select entries & action first', 'fluentform')
--- a/fluentform/app/Modules/Payments/PaymentMethods/Stripe/StripeInlineProcessor.php
+++ b/fluentform/app/Modules/Payments/PaymentMethods/Stripe/StripeInlineProcessor.php
@@ -171,6 +171,9 @@
}
$this->processScaBeforeVerification($submission->form_id, $submission->id, $transactionId, $invoice->payment_intent->id);
+ $nonceAction = 'fluentform_sca_confirm_' . $submission->id;
+ $nonce = wp_create_nonce($nonceAction);
+
wp_send_json_success([
'nextAction' => 'payment',
'actionName' => 'stripeSetupIntent',
@@ -181,6 +184,7 @@
'customer_name' => ($transaction) ? $transaction->payer_name : '',
'customer_email' => ($transaction) ? $transaction->payer_email : '',
'client_secret' => $invoice->payment_intent->client_secret,
+ '_ff_stripe_nonce' => $nonce,
'message' => __('Verifying your card details. Please wait...', 'fluentform'),
'result' => [
'insert_id' => $submission->id
@@ -286,12 +290,17 @@
) {
$this->processScaBeforeVerification($submission->form_id, $submission->id, $transaction->id, $intent->id);
+ // Generate nonce for secure SCA confirmation
+ $nonceAction = 'fluentform_sca_confirm_' . $submission->id;
+ $nonce = wp_create_nonce($nonceAction);
+
# Tell the client to handle the action
wp_send_json_success([
'nextAction' => 'payment',
'actionName' => 'initStripeSCAModal',
'submission_id' => $submission->id,
'client_secret' => $intent->client_secret,
+ '_ff_stripe_nonce' => $nonce,
'message' => apply_filters('fluentform/stripe_strong_customer_verify_waiting_message', __('Verifying strong customer authentication. Please wait...', 'fluentform')),
'result' => [
'insert_id' => $submission->id
@@ -367,15 +376,89 @@
$this->sendSuccess($submission);
}
+ /**
+ * Validate SCA payment confirmation request
+ *
+ * @param int $submissionId Submission ID
+ * @param string $paymentIntentId Payment Intent ID
+ * @param object|null $submission Submission object
+ * @param object|null $transaction Transaction object
+ * @return array|WP_Error Array with validation result or WP_Error on strict mode failure
+ */
+ protected function validateScaRequest($submissionId, $paymentIntentId, $submission = null, $transaction = null)
+ {
+ $strictMode = apply_filters('fluentform/stripe_sca_strict_security', false);
+ $warnings = [];
+
+ // Validate nonce (optional in non-strict mode for backward compatibility)
+ $nonce = isset($_REQUEST['_ff_stripe_nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['_ff_stripe_nonce'])) : '';
+
+ if ($nonce) {
+ $nonceAction = 'fluentform_sca_confirm_' . $submissionId;
+ if (!wp_verify_nonce($nonce, $nonceAction)) {
+ $error = __('Security verification failed. Invalid nonce.', 'fluentform');
+ if ($strictMode) {
+ return new WP_Error('invalid_nonce', $error);
+ }
+ $warnings[] = 'Invalid nonce provided';
+ }
+ } else {
+ $warning = 'No nonce provided for SCA payment confirmation';
+ if ($strictMode) {
+ return new WP_Error('missing_nonce', __('Security verification failed. Nonce required.', 'fluentform'));
+ }
+ $warnings[] = $warning;
+ }
+
+ // Validate submission exists
+ if (!$submission || !$submission->id) {
+ return new WP_Error('invalid_submission', __('Invalid submission.', 'fluentform'));
+ }
+
+
+ if ($submission->payment_status === 'paid') {
+ return new WP_Error(
+ 'already_paid',
+ __('This payment has already been completed and cannot be modified.', 'fluentform')
+ );
+ }
+
+ // stores it in transaction.charge_id, and frontend sends it back.
+ // Mismatch only occurs during attack attempts.
+ if ($transaction && $transaction->charge_id) {
+ if ($transaction->charge_id !== $paymentIntentId) {
+ return new WP_Error(
+ 'payment_intent_mismatch',
+ __('Payment verification failed. Payment intent does not match.', 'fluentform')
+ );
+ }
+ }
+
+ // Log warnings for monitoring
+ if (!empty($warnings) && defined('WP_DEBUG') && WP_DEBUG) {
+ $logData = [
+ 'parent_source_id' => $submission->form_id,
+ 'source_type' => 'submission_item',
+ 'source_id' => $submission->id,
+ 'component' => 'Payment',
+ 'status' => 'warning',
+ 'title' => __('Stripe SCA Security Warning', 'fluentform'),
+ 'description' => implode('; ', $warnings)
+ ];
+ do_action('fluentform/log_data', $logData);
+ }
+
+ return [
+ 'valid' => true,
+ 'warnings' => $warnings
+ ];
+ }
+
public function confirmScaPayment()
{
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
- $formId = isset($_REQUEST['form_id']) ? intval($_REQUEST['form_id']) : 0;
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
- $submissionId = isset($_REQUEST['submission_id']) ? intval($_REQUEST['submission_id']) : 0;
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
+ $formId = isset($_REQUEST['form_id']) ? (int)$_REQUEST['form_id'] : 0;
+ $submissionId = isset($_REQUEST['submission_id']) ? (int)$_REQUEST['submission_id'] : 0;
$paymentMethod = isset($_REQUEST['payment_method']) ? sanitize_text_field(wp_unslash($_REQUEST['payment_method'])) : '';
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
$paymentIntentId = isset($_REQUEST['payment_intent_id']) ? sanitize_text_field(wp_unslash($_REQUEST['payment_intent_id'])) : '';
$this->setSubmissionId($submissionId);
@@ -384,6 +467,14 @@
$transaction = $this->getLastTransaction($submissionId);
+ $validation = $this->validateScaRequest($submissionId, $paymentIntentId, $submission, $transaction);
+
+ if (is_wp_error($validation)) {
+ wp_send_json([
+ 'errors' => $validation->get_error_message()
+ ], 423);
+ }
+
$confirmation = SCA::confirmPayment($paymentIntentId, [
'payment_method' => $paymentMethod
], $formId);
@@ -403,17 +494,24 @@
public function confirmScaSetupIntentsPayment()
{
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
$formId = isset($_REQUEST['form_id']) ? intval($_REQUEST['form_id']) : 0;
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
$submissionId = isset($_REQUEST['submission_id']) ? intval($_REQUEST['submission_id']) : 0;
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by Stripe webhook signature
$intentId = isset($_REQUEST['payment_intent_id']) ? sanitize_text_field(wp_unslash($_REQUEST['payment_intent_id'])) : '';
$this->setSubmissionId($submissionId);
$this->form = $this->getForm();
$submission = $this->getSubmission();
+ $transaction = $this->getLastTransaction($submissionId);
+
+ // Validate the request with backward compatibility
+ $validation = $this->validateScaRequest($submissionId, $intentId, $submission, $transaction);
+
+ if (is_wp_error($validation)) {
+ wp_send_json([
+ 'errors' => $validation->get_error_message()
+ ], 423);
+ }
// Let's retrieve the intent
$intent = SCA::retrievePaymentIntent($intentId, [
--- a/fluentform/app/Services/ConditionAssesor.php
+++ b/fluentform/app/Services/ConditionAssesor.php
@@ -4,11 +4,12 @@
use FluentFormAppHelpersHelper;
use FluentFormAppHelpersStr;
+use FluentFormAppServicesFormBuilderEditorShortcodeParser;
use FluentFormFrameworkHelpersArrayHelper as Arr;
class ConditionAssesor
{
- public static function evaluate(&$field, &$inputs)
+ public static function evaluate(&$field, &$inputs, $form = null)
{
$status = Arr::get($field, 'conditionals.status');
if (!$status) {
@@ -19,22 +20,22 @@
// Handle group conditions
if ($type === 'group' && $conditionGroups = Arr::get($field, 'conditionals.condition_groups')) {
- return self::evaluateGroupConditions($conditionGroups, $inputs);
+ return self::evaluateGroupConditions($conditionGroups, $inputs, $form);
}
// Handle 'any', 'all' conditions
if ($type !== 'group' && $conditions = Arr::get($field, 'conditionals.conditions')) {
- return self::evaluateConditions($conditions, $inputs, $type);
+ return self::evaluateConditions($conditions, $inputs, $type, $form);
}
return true;
}
- private static function evaluateGroupConditions($conditionGroups, &$inputs)
+ private static function evaluateGroupConditions($conditionGroups, &$inputs, $form = null)
{
$hasGroupConditionsMet = true;
foreach ($conditionGroups as $group) {
if ($conditions = Arr::get($group, 'rules')) {
- $hasGroupConditionsMet = self::evaluateConditions($conditions, $inputs, 'all');
+ $hasGroupConditionsMet = self::evaluateConditions($conditions, $inputs, 'all', $form);
if ($hasGroupConditionsMet) {
return true;
}
@@ -43,7 +44,7 @@
return $hasGroupConditionsMet;
}
- private static function evaluateConditions($conditions, &$inputs, $type)
+ private static function evaluateConditions($conditions, &$inputs, $type, $form = null)
{
$hasConditionMet = true;
@@ -52,7 +53,7 @@
continue;
}
- $hasConditionMet = static::assess($condition, $inputs);
+ $hasConditionMet = static::assess($condition, $inputs, $form);
if ($hasConditionMet && $type == 'any') {
return true;
@@ -66,7 +67,7 @@
return $hasConditionMet;
}
- public static function assess(&$conditional, &$inputs)
+ public static function assess(&$conditional, &$inputs, $form = null)
{
if ($conditional['field']) {
$accessor = rtrim(str_replace(['[', ']', '*'], ['.'], $conditional['field']), '.');
@@ -79,75 +80,144 @@
if ($numericFormatter = Arr::get($conditional, 'numeric_formatter')) {
$inputValue = Helper::getNumericValue($inputValue, $numericFormatter);
}
+ $conditionValue = Arr::get($conditional, 'value');
+ $isArrayAcceptable = in_array($conditional['operator'], ['=', '!=']);
+ if (!empty($conditionValue) && is_string($conditionValue)) {
+ $conditionValue = self::processSmartCodesInValue($conditionValue, $inputs, $form, $isArrayAcceptable);
+ }
+ $conditionValue = is_null($conditionValue) ? '' : $conditionValue;
+
switch ($conditional['operator']) {
case '=':
- if(is_array($inputValue)) {
- return in_array($conditional['value'], $inputValue);
+ if (is_array($inputValue) && is_array($conditionValue)) {
+ $flatInput = Arr::flatten($inputValue);
+ $flatCondition = Arr::flatten($conditionValue);
+ sort($flatInput);
+ sort($flatCondition);
+ return $flatInput == $flatCondition;
+ }
+
+ if (is_array($conditionValue)) {
+ return in_array($inputValue, Arr::flatten($conditionValue));
+ }
+ if (is_array($inputValue)) {
+ return in_array($conditionValue, Arr::flatten($inputValue));
}
- return $inputValue == $conditional['value'];
- break;
+ return $inputValue == $conditionValue;
case '!=':
- if(is_array($inputValue)) {
- return !in_array($conditional['value'], $inputValue);
+ if (is_array($inputValue) && is_array($conditionValue)) {
+ return count(array_intersect(Arr::flatten($inputValue), Arr::flatten($conditionValue))) == 0;
+ }
+ if (is_array($conditionValue)) {
+ return !in_array($inputValue, Arr::flatten($conditionValue));
}
- return $inputValue != $conditional['value'];
- break;
+ if (is_array($inputValue)) {
+ return !in_array($conditionValue, Arr::flatten($inputValue));
+ }
+ return $inputValue != $conditionValue;
case '>':
- return $inputValue > $conditional['value'];
- break;
+ return $inputValue > $conditionValue;
case '<':
- return $inputValue < $conditional['value'];
- break;
+ return $inputValue < $conditionValue;
case '>=':
- return $inputValue >= $conditional['value'];
- break;
+ return $inputValue >= $conditionValue;
case '<=':
- return $inputValue <= $conditional['value'];
- break;
+ return $inputValue <= $conditionValue;
case 'startsWith':
- return Str::startsWith($inputValue, $conditional['value']);
- break;
+ return Str::startsWith($inputValue, $conditionValue);
case 'endsWith':
- return Str::endsWith($inputValue, $conditional['value']);
- break;
+ return Str::endsWith($inputValue, $conditionValue);
case 'contains':
- return Str::contains($inputValue, $conditional['value']);
- break;
+ return Str::contains($inputValue, $conditionValue);
case 'doNotContains':
- return !Str::contains($inputValue, $conditional['value']);
- break;
+ return !Str::contains($inputValue, $conditionValue);
case 'length_equal':
- if(is_array($inputValue)) {
- return count($inputValue) == $conditional['value'];
+ if (is_array($inputValue)) {
+ return count($inputValue) == $conditionValue;
}
- $inputValue = strval($inputValue);
- return strlen($inputValue) == $conditional['value'];
- break;
+ $inputValue = (string)$inputValue;
+ return strlen($inputValue) == $conditionValue;
case 'length_less_than':
- if(is_array($inputValue)) {
- return count($inputValue) < $conditional['value'];
+ if (is_array($inputValue)) {
+ return count($inputValue) < $conditionValue;
}
- $inputValue = strval($inputValue);
- return strlen($inputValue) < $conditional['value'];
- break;
+ $inputValue = (string)$inputValue;
+ return strlen($inputValue) < $conditionValue;
case 'length_greater_than':
- if(is_array($inputValue)) {
- return count($inputValue) > $conditional['value'];
+ if (is_array($inputValue)) {
+ return count($inputValue) > $conditionValue;
}
- $inputValue = strval($inputValue);
- return strlen($inputValue) > $conditional['value'];
- break;
+ $inputValue = (string)$inputValue;
+ return strlen($inputValue) > $conditionValue;
case 'test_regex':
- if(is_array($inputValue)) {
+ if (is_array($inputValue)) {
$inputValue = implode(' ', $inputValue);
}
- $result = preg_match('/'.$conditional['value'].'/', $inputValue);
- return !!$result;
- break;
+ $pattern = '/' . $conditionValue . '/';
+ $result = @preg_match($pattern, $inputValue);
+ if ($result === false) {
+ // Invalid regex pattern, handle gracefully
+ return false;
+ }
+ return (bool) $result;
}
}
return false;
}
+
+ private static function processSmartCodesInValue($value, &$inputs, $form = null, $isArrayAcceptable = true)
+ {
+ if (strpos($value, '{') === false) {
+ return $value;
+ }
+
+ if (preg_match('/^{inputs.([^}]+)}$/', $value, $inputMatches)) {
+ $fieldName = $inputMatches[1];
+ $fieldKey = str_replace(['[', ']'], ['.', ''], $fieldName);
+
+ $resolvedValue = Arr::get($inputs, $fieldKey);
+
+ if ($resolvedValue === null && $fieldKey !== $fieldName) {
+ $resolvedValue = Arr::get($inputs, $fieldName);
+ }
+
+ // Return array if it's an array
+ if (is_array($resolvedValue) && $isArrayAcceptable) {
+ return $resolvedValue;
+ }
+ }
+
+ try {
+ $processedValue = preg_replace_callback('/{+(.*?)}/', function ($matches) use ($inputs, $form) {
+ $smartCode = $matches[1];
+
+ if (false !== strpos($smartCode, 'inputs.')) {
+ $fieldName = substr($smartCode, strlen('inputs.'));
+
+ $fieldKey = str_replace(['[', ']'], ['.', ''], $fieldName);
+
+ $value = Arr::get($inputs, $fieldKey, '');
+
+ if ($value === '' && $fieldKey !== $fieldName) {
+ $value = Arr::get($inputs, $fieldName, '');
+ }
+
+ if (is_array($value)) {
+ $value = fluentImplodeRecursive(', ', $value);
+ }
+
+ return $value !== null && $value !== '' ? $value : '';
+ }
+
+ // @todo Support general shortcodes in future
+ return '';
+ }, $value);
+
+ return $processedValue;
+ } catch (Exception $e) {
+ return $value;
+ }
+ }
}
--- a/fluentform/app/Services/Form/SubmissionHandlerService.php
+++ b/fluentform/app/Services/Form/SubmissionHandlerService.php
@@ -219,6 +219,7 @@
if ($insertId) {
ob_start();
+ $formData = apply_filters('fluentform/submission_form_data', $formData, $insertId, $form);
$this->submissionService->recordEntryDetails($insertId, $form->id, $formData);
$isError = ob_get_clean();
if ($isError) {
@@ -227,6 +228,8 @@
}
$error = '';
try {
+ $formData = apply_filters('fluentform/submission_form_data', $formData, $insertId, $form);
+
do_action('fluentform_submission_inserted', $insertId, $formData, $form);
do_action('fluentform/submission_inserted', $insertId, $formData, $form);
--- a/fluentform/app/Services/Form/Updater.php
+++ b/fluentform/app/Services/Form/Updater.php
@@ -13,9 +13,9 @@
{
public function update($attributes = [])
{
- $formId = Arr::get($attributes, 'form_id');
+ $formId = (int)Arr::get($attributes, 'form_id');
$formFields = Arr::get($attributes, 'formFields');
- $status = Arr::get($attributes, 'status', 'published');
+ $status = sanitize_text_field(Arr::get($attributes, 'status', 'published'));
$title = sanitize_text_field(Arr::get($attributes, 'title'));
$this->validate([
--- a/fluentform/app/Services/GlobalSettings/GlobalSettingsService.php
+++ b/fluentform/app/Services/GlobalSettings/GlobalSettingsService.php
@@ -36,7 +36,7 @@
public function store($attributes = [])
{
- $key = Arr::get($attributes, 'key');
+ $key = sanitize_text_field(Arr::get($attributes, 'key'));
$globalSettingsHelper = new GlobalSettingsHelper(