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

Updater.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.2, at app/Services/Form/Updater.php

396 lines 14.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Services\Form;
4
5 use Exception;
6 use FluentForm\App\Models\Form;
7 use FluentForm\App\Helpers\Helper;
8 use FluentForm\App\Models\FormMeta;
9 use FluentForm\Framework\Support\Arr;
10 use FluentForm\App\Modules\Form\FormFieldsParser;
11
12 class Updater
13 {
14 public function update($attributes = [])
15 {
16 $formId = (int)Arr::get($attributes, 'form_id');
17 $formFields = Arr::get($attributes, 'formFields');
18 $status = sanitize_text_field(Arr::get($attributes, 'status', 'published'));
19 $title = sanitize_text_field(Arr::get($attributes, 'title'));
20
21 $this->validate([
22 'title' => $title,
23 'formFields' => $formFields,
24 ]);
25
26 try {
27 $form = Form::findOrFail($formId);
28 } catch (Exception $e) {
29 throw new \Exception("The form couldn't be found.");
30 }
31
32 $data = [
33 'title' => $title,
34 'status' => $status,
35 'updated_at' => current_time('mysql'),
36 ];
37
38 if ($formFields) {
39 $formFields = apply_filters_deprecated(
40 'fluentform_form_fields_update',
41 [
42 $formFields,
43 $formId
44 ],
45 FLUENTFORM_FRAMEWORK_UPGRADE,
46 'fluentform/form_fields_update',
47 'Use fluentform/form_fields_update instead of fluentform_form_fields_update.'
48 );
49 $formFields = apply_filters('fluentform/form_fields_update', $formFields, $formId);
50 $formFields = $this->sanitizeFields($formFields);
51 $data['form_fields'] = $formFields;
52 /**
53 * Fires before a Form is updated.
54 * @since 5.2.1
55 */
56 do_action('fluentform/before_updating_form', $form, $data);
57
58 $form->fill($data);
59
60 if (FormFieldsParser::hasPaymentFields($form)) {
61 $data['has_payment'] = 1;
62 } elseif ($form->has_payment) {
63 $data['has_payment'] = 0;
64 }
65
66 $this->updatePrimaryEmail($form);
67
68 }
69
70 $form->fill($data)->save();
71
72 return $form;
73 }
74
75 private function validate($attributes)
76 {
77 if ($attributes['formFields']) {
78 $duplicates = Helper::getDuplicateFieldNames($attributes['formFields']);
79
80 if ($duplicates) {
81 $duplicateString = implode(', ', $duplicates);
82
83 throw new Exception(
84 sprintf('Name attribute %s has duplicate value.', esc_html($duplicateString))
85 );
86 }
87 }
88
89 if (!$attributes['title']) {
90 throw new Exception('The title field is required.');
91 }
92 }
93
94 private function sanitizeFields($formFields)
95 {
96 if (fluentformCanUnfilteredHTML()) {
97 return $formFields;
98 }
99
100 $fieldsArray = json_decode($formFields, true);
101
102 if (isset($fieldsArray['submitButton'])) {
103 $fieldsArray['submitButton']['settings']['button_ui']['text'] = fluentform_sanitize_html(
104 $fieldsArray['submitButton']['settings']['button_ui']['text']
105 );
106
107 if (!empty($fieldsArray['submitButton']['settings']['button_ui']['img_url'])) {
108 $fieldsArray['submitButton']['settings']['button_ui']['img_url'] = sanitize_url(
109 $fieldsArray['submitButton']['settings']['button_ui']['img_url']
110 );
111 }
112 }
113 $fieldsArray['fields'] = $this->sanitizeFieldMaps($fieldsArray['fields']);
114 $fieldsArray['fields'] = $this->sanitizeCustomSubmit($fieldsArray['fields']);
115 if ($stepsWrapper = Arr::get($fieldsArray, 'stepsWrapper')) {
116 $fieldsArray['stepsWrapper'] = $this->sanitizeStepsWrapper($stepsWrapper);
117 }
118
119 return json_encode($fieldsArray);
120 }
121
122 private function sanitizeFieldMaps($fields)
123 {
124 if (!is_array($fields)) {
125 return $fields;
126 }
127
128 $attributesMap = [
129 'name' => 'sanitize_key',
130 'value' => 'sanitize_textarea_field',
131 'id' => 'sanitize_key',
132 'class' => 'sanitize_text_field',
133 'placeholder' => 'sanitize_text_field',
134 ];
135
136 $attributesKeys = array_keys($attributesMap);
137
138 $settingsMap = [
139 'container_class' => 'sanitize_text_field',
140 'label' => 'fluentform_sanitize_html',
141 'tnc_html' => 'fluentform_sanitize_html',
142 'label_placement' => 'sanitize_text_field',
143 'help_message' => 'wp_kses_post',
144 'admin_field_label' => 'sanitize_text_field',
145 'prefix_label' => 'sanitize_text_field',
146 'suffix_label' => 'sanitize_text_field',
147 'unique_validation_message' => 'sanitize_text_field',
148 'advanced_options' => 'fluentform_options_sanitize',
149 'html_codes' => 'fluentform_sanitize_html',
150 'description' => 'fluentform_sanitize_html',
151 'grid_columns' => [Helper::class, 'sanitizeArrayKeysAndValues'],
152 'grid_rows' => [Helper::class, 'sanitizeArrayKeysAndValues'],
153 ];
154
155
156 $settingsKeys = array_keys($settingsMap);
157
158 $stylePrefMap = [
159 'layout' => 'sanitize_key',
160 'media' => 'sanitize_url',
161 'alt_text' => 'sanitize_text_field',
162 ];
163 $stylePrefKeys = array_keys($stylePrefMap);
164
165 foreach ($fields as $fieldIndex => &$field) {
166 $element = Arr::get($field, 'element');
167
168 if ('container' == $element) {
169 $columns = $field['columns'];
170 foreach ($columns as $columnIndex => $column) {
171 $fields[$fieldIndex]['columns'][$columnIndex]['fields'] = $this->sanitizeFieldMaps($column['fields']);
172 }
173 continue;
174 }
175
176 if ('welcome_screen' == $element) {
177 if ($value = Arr::get($field, 'settings.button_ui.text')) {
178 $field['settings']['button_ui']['text'] = fluentform_sanitize_html($value);
179 }
180 }
181
182 if ('form_step' == $element) {
183 foreach (['next_btn', 'prev_btn'] as $buttonKey) {
184 $buttonSettings = Arr::get($field, 'settings.' . $buttonKey);
185 if (!is_array($buttonSettings)) {
186 continue;
187 }
188
189 if (isset($buttonSettings['type'])) {
190 $field['settings'][$buttonKey]['type'] = sanitize_text_field($buttonSettings['type']);
191 }
192
193 if (isset($buttonSettings['text'])) {
194 $field['settings'][$buttonKey]['text'] = fluentform_sanitize_html($buttonSettings['text']);
195 }
196
197 if (isset($buttonSettings['img_url'])) {
198 $field['settings'][$buttonKey]['img_url'] = esc_url_raw($buttonSettings['img_url']);
199 }
200
201 if (isset($buttonSettings['img_alt'])) {
202 $field['settings'][$buttonKey]['img_alt'] = sanitize_text_field($buttonSettings['img_alt']);
203 }
204 }
205 }
206
207 if ('save_progress_button' == $element) {
208 $buttonUi = Arr::get($field, 'settings.button_ui');
209 if (is_array($buttonUi)) {
210 if (isset($buttonUi['type'])) {
211 $field['settings']['button_ui']['type'] = sanitize_text_field($buttonUi['type']);
212 }
213
214 if (isset($buttonUi['text'])) {
215 $field['settings']['button_ui']['text'] = fluentform_sanitize_html($buttonUi['text']);
216 }
217
218 if (isset($buttonUi['img_url'])) {
219 $field['settings']['button_ui']['img_url'] = esc_url_raw($buttonUi['img_url']);
220 }
221 }
222 }
223
224
225 if (!empty($field['attributes'])) {
226 $attributes = array_filter(Arr::only($field['attributes'], $attributesKeys));
227
228 foreach ($attributes as $key => $value) {
229 $fields[$fieldIndex]['attributes'][$key] = call_user_func($attributesMap[$key], $value);
230 }
231 }
232
233 if (!empty($field['settings'])) {
234 $settings = array_filter(Arr::only($field['settings'], array_values($settingsKeys)));
235 foreach ($settings as $key => $value) {
236 $fields[$fieldIndex]['settings'][$key] = call_user_func($settingsMap[$key], $value);
237 }
238 }
239 /*
240 * Handle Name or address fields
241 */
242 if (!empty($field['fields'])) {
243 $fields[$fieldIndex]['fields'] = $this->sanitizeFieldMaps($field['fields']);
244 continue;
245 }
246
247 if (!empty($field['style_pref'])) {
248 $settings = array_filter(Arr::only($field['style_pref'], $stylePrefKeys));
249
250 foreach ($settings as $key => $value) {
251 $fields[$fieldIndex]['style_pref'][$key] = call_user_func($stylePrefMap[$key], $value);
252 }
253 }
254
255 $validationRules = Arr::get($field, 'settings.validation_rules');
256 if (!empty($validationRules)) {
257 foreach ($validationRules as $key => $rule) {
258 if (isset($rule['message'])) {
259 $message = $rule['message'];
260 $field['settings']['validation_rules'][$key]['message'] = wp_kses_post($message);
261 continue;
262 }
263 }
264 }
265 }
266
267 return $fields;
268 }
269
270 private function updatePrimaryEmail($form)
271 {
272 $emailInputs = FormFieldsParser::getElement($form, ['input_email'], ['element', 'attributes']);
273
274 if ($emailInputs) {
275 $emailInput = array_shift($emailInputs);
276 $emailInputName = Arr::get($emailInput, 'attributes.name');
277 } else {
278 $emailInputName = '';
279 }
280
281 FormMeta::persist($form->id, '_primary_email_field', $emailInputName);
282 }
283
284 private function sanitizeCustomSubmit($fields)
285 {
286 $customSubmitSanitizationMap = [
287 'hover_styles' => [
288 'backgroundColor' => [$this, 'sanitizeRgbColor'],
289 'borderColor' => [$this, 'sanitizeRgbColor'],
290 'color' => [$this, 'sanitizeRgbColor'],
291 'borderRadius' => 'sanitize_text_field',
292 'minWidth' => [$this, 'sanitizeMinWidth']
293 ],
294 'normal_styles' => [
295 'backgroundColor' => [$this, 'sanitizeRgbColor'],
296 'borderColor' => [$this, 'sanitizeRgbColor'],
297 'color' => [$this, 'sanitizeRgbColor'],
298 'borderRadius' => 'sanitize_text_field',
299 'minWidth' => [$this, 'sanitizeMinWidth']
300 ],
301 'button_ui' => [
302 'type' => 'sanitize_text_field',
303 'text' => 'fluentform_sanitize_html',
304 'img_url' => 'esc_url_raw',
305 ],
306 ];
307 foreach ($fields as $fieldIndex => $field) {
308 $element = Arr::get($field, 'element');
309
310 if ('custom_submit_button' == $element) {
311 $styleAttr = ['hover_styles', 'normal_styles', 'button_ui'];
312 foreach ($styleAttr as $attr) {
313 if ($styleConfigs = Arr::get($field, 'settings.' . $attr)) {
314 foreach ($styleConfigs as $key => $value) {
315 if (isset($customSubmitSanitizationMap[$attr][$key])) {
316 $sanitizeFunction = $customSubmitSanitizationMap[$attr][$key];
317 $fields[$fieldIndex]['settings'][$attr][$key] = $sanitizeFunction($value);
318 }
319 }
320 }
321 }
322 }
323 elseif ('container' == $element) {
324 $columns = $field['columns'];
325 foreach ($columns as $columnIndex => $column) {
326 $fields[$fieldIndex]['columns'][$columnIndex]['fields'] = $this->sanitizeCustomSubmit($column['fields']);
327 }
328 return $fields;
329 }
330 }
331 return $fields;
332 }
333
334 private function sanitizeStepsWrapper($stepWrapper)
335 {
336 $stepsSanitizationMap = [
337 'prev_btn' => [
338 'type' => 'sanitize_text_field',
339 'text' => 'fluentform_sanitize_html',
340 'img_url' => 'esc_url_raw',
341 ],
342 ];
343
344 foreach ($stepWrapper as $fieldIndex => $field) {
345 $element = Arr::get($field, 'element');
346
347 if ($element === 'step_start' || $element === 'step_end') {
348 if (!empty($field['settings']['step_titles']) && is_array($field['settings']['step_titles'])) {
349 foreach ($field['settings']['step_titles'] as $index => $title) {
350 $field['settings']['step_titles'][$index] = fluentform_sanitize_html($title);
351 }
352 }
353
354 if (!empty($field['settings']['prev_btn']) && is_array($field['settings']['prev_btn'])) {
355 foreach ($field['settings']['prev_btn'] as $key => $value) {
356 if (isset($stepsSanitizationMap['prev_btn'][$key])) {
357 $sanitizeFunction = $stepsSanitizationMap['prev_btn'][$key];
358 $field['settings']['prev_btn'][$key] = $sanitizeFunction($value);
359 }
360 }
361 }
362
363 if (!empty($field['attributes']['class'])) {
364 $field['attributes']['class'] = sanitize_text_field($field['attributes']['class']);
365 }
366 if (!empty($field['attributes']['id'])) {
367 $field['attributes']['id'] = sanitize_text_field($field['attributes']['id']);
368 }
369 }
370
371 if ($element === 'step_start' && isset($field['fields'])) {
372 $field['fields'] = $this->sanitizeStepsWrapper($field['fields']);
373 }
374
375 $stepWrapper[$fieldIndex] = $field;
376 }
377
378 return $stepWrapper;
379 }
380
381 public function sanitizeMinWidth($value)
382 {
383 if (is_string($value) && preg_match('/^\d+%$/', $value)) {
384 return $value;
385 }
386 return '';
387 }
388
389 public function sanitizeRgbColor($value) {
390 if (preg_match('/^rgba?\((\d{1,3}\s*,\s*){2,3}(0|1|0?\.\d+)\)$/', $value)) {
391 return $value;
392 }
393 return '';
394 }
395 }
396