PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.15
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.15
6.2.15 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 All 197 releases
← All changes | app/Services/Parser/Extractor.php +167 -64 3.6.22 → 6.2.15 View file →
@@ -1,8 +1,10 @@
1 1 <?php
2 2
3 3 namespace FluentForm\App\Services\Parser;
4 4
5 +use FluentForm\App\Helpers\Helper;
6 +use FluentForm\App\Services\ConditionAssesor;
5 7 use FluentForm\Framework\Helpers\ArrayHelper as Arr;
6 8
7 9 class Extractor
8 10 {
@@ -20,9 +22,9 @@
20 22 */
21 23 protected $with;
22 24
23 25 /**
24 - * The supported form input types defined for Fluent Form.
26 + * The supported form input types defined for Fluent Forms.
25 27 *
26 28 * @var array
27 29 */
28 30 protected $inputTypes;
@@ -86,11 +88,13 @@
86 88 {
87 89 foreach ($fields as $field) {
88 90 // If the field is a Container (collection of other fields)
89 91 // then we will recursively call this function to resolve.
90 - if ($field['element'] === 'container') {
91 - foreach ($field['columns'] as $item) {
92 - $this->looper($item['fields']);
92 + if (Arr::get($field, 'element') === 'container') {
93 + $columns = Arr::get($field, 'columns', []);
94 + foreach ($columns as $item) {
95 + $itemFields = Arr::get($item, 'fields', []);
96 + $this->looper($itemFields);
93 97 }
94 98 }
95 99
96 100 // Now the field is supposed to be a flat field.
@@ -95,9 +99,10 @@
95 99
96 100 // Now the field is supposed to be a flat field.
97 101 // We can extract the desired keys as we want.
98 102 else {
99 - if (in_array($field['element'], $this->inputTypes)) {
103 + $element = Arr::get($field, 'element');
104 + if ($element && in_array($element, $this->inputTypes)) {
100 105 $this->extractField($field);
101 106 }
102 107 }
103 108 }
@@ -103,8 +108,58 @@
103 108 }
104 109 }
105 110
106 111 /**
112 + * The extractor initializer for getting the extracted data.
113 + *
114 + * @return array
115 + */
116 + public function extractEssentials($formData)
117 + {
118 + $this->looperEssential($formData, $this->fields);
119 +
120 + return $this->result;
121 + }
122 +
123 + /**
124 + * The recursive looper method to loop each
125 + * of the fields and extract it's data.
126 + *
127 + * @param array $fields
128 + */
129 + protected function looperEssential($formData, $fields = [])
130 + {
131 + foreach ($fields as $field) {
132 + $field['conditionals'] = Arr::get($field, 'settings.conditional_logics', []);
133 +
134 + $matched = ConditionAssesor::evaluate($field, $formData);
135 +
136 + if (!$matched) {
137 + continue;
138 + }
139 +
140 + // If the field is a Container (collection of other fields)
141 + // then we will recursively call this function to resolve.
142 + if (Arr::get($field, 'element') === 'container') {
143 + $columns = Arr::get($field, 'columns', []);
144 + foreach ($columns as $item) {
145 + $itemFields = Arr::get($item, 'fields', []);
146 + $this->looperEssential($formData, $itemFields);
147 + }
148 + }
149 +
150 + // Now the field is supposed to be a flat field.
151 + // We can extract the desired keys as we want.
152 + else {
153 + $element = Arr::get($field, 'element');
154 + if ($element && in_array($element, $this->inputTypes)) {
155 + $this->extractField($field);
156 + }
157 + }
158 + }
159 + }
160 +
161 + /**
107 162 * Extract the form field.
108 163 *
109 164 * @param array $field
110 165 * @return $this
@@ -155,9 +210,9 @@
155 210 * @return $this
156 211 */
157 212 protected function setElement()
158 213 {
159 - $this->result[$this->attribute]['element'] = $this->field['element'];
214 + $this->result[$this->attribute]['element'] = Arr::get($this->field, 'element', '');
160 215 return $this;
161 216 }
162 217
163 218
@@ -201,15 +256,34 @@
201 256 */
202 257 protected function setOptions()
203 258 {
204 259 if (in_array('options', $this->with)) {
205 - $options = Arr::get($this->field, 'options', []);
206 - if(!$options) {
207 - $newOptions = Arr::get($this->field, 'settings.advanced_options', []);
260 + $options = Arr::get($this->field, 'options', []);
261 +
262 + if(!$options) {
263 + $newOptions = \FluentForm\App\Helpers\Helper::flattenAdvancedOptions(
264 + Arr::get($this->field, 'settings.advanced_options', [])
265 + );
266 +
267 + if(
268 + !$newOptions
269 + && Arr::get($this->field,'element') == 'multi_payment_component'
270 + && Arr::get($this->field,'attributes.type') != 'single'
271 + ) {
272 + $pricingOptions = Arr::get($this->field, 'settings.pricing_options', []);
273 + foreach ($pricingOptions as $pricingOption) {
274 + $newOptions[] = [
275 + 'value' => $pricingOption['label'],
276 + 'label' => $pricingOption['label']
277 + ];
278 + }
279 + }
280 +
208 281 $options = [];
209 282 if($newOptions) {
210 283 foreach ($newOptions as $option) {
211 - $options[$option['value']] = $option['label'];
284 + $value = sanitize_text_field($option['value']);
285 + $options[$value] = sanitize_text_field($option['label']);
212 286 }
213 287 }
214 288 }
215 289 $this->result[$this->attribute]['options'] = $options;
@@ -265,8 +339,10 @@
265 339 $this->field,
266 340 'settings.validation_rules'
267 341 );
268 342
343 + $this->handleMaxLengthValidation();
344 +
269 345 $this->result[$this->attribute]['conditionals'] = Arr::get(
270 346 $this->field,
271 347 'settings.conditional_logics'
272 348 );
@@ -274,68 +350,95 @@
274 350
275 351 return $this;
276 352 }
277 353
278 - /**
279 - * Handle the child fields of the custom field.
280 - *
281 - * @return $this
282 - */
283 - protected function handleCustomField()
354 + protected function handleMaxLengthValidation()
284 355 {
285 - // If this field is a custom field we'll assume it has it's child fields
286 - // under the `fields` key. Then we are gonna modify those child fields'
287 - // attribute `name`, `label` & `conditional_logics` properties using
288 - // the parent field. The current implementation will modify those
289 - // properties in a way so that we can use dot notation to access.
290 - $customFields = Arr::get($this->field, 'fields');
356 + $maxLength = Arr::get($this->field, 'attributes.maxlength');
357 + $fieldHasMaxValidation = Arr::get($this->field, 'settings.validation_rules.max');
358 + $shouldSetMaxValidation = $maxLength && !$fieldHasMaxValidation;
291 359
292 - if ($customFields) {
293 - $parentAttribute = Arr::get($this->field, 'attributes.name');
294 -
295 - $parentConditionalLogics = Arr::get($this->field, 'settings.conditional_logics', []);
296 -
297 - $isAddressOrNameField = in_array(Arr::get($this->field, 'element'), ['address', 'input_name']);
298 -
299 - $isRepeatField = Arr::get($this->field, 'element') === 'input_repeat' || Arr::get($this->field, 'element') == 'repeater_field';
300 -
301 - foreach ($customFields as $index => $customField) {
302 - // If the current field is in fact `address` || `name` field
303 - // then we have to only keep the enabled child fields
304 - // by the user from the form editor settings.
305 - if ($isAddressOrNameField) {
306 - if (!Arr::get($customField, 'settings.visible', false)) {
307 - unset($customFields[$index]);
308 - continue;
309 - }
310 - }
311 -
312 - // Depending on whether the parent field is a repeat field or not
313 - // the modified attribute name of the child field will vary.
314 - if ($isRepeatField) {
315 - $modifiedAttribute = $parentAttribute.'['.$index.'].*';
316 - } else {
317 - $modifiedAttribute = $parentAttribute.'['.Arr::get($customField, 'attributes.name').']';
318 - }
319 -
320 - $modifiedLabel = $parentAttribute.'['.Arr::get($customField, 'settings.label').']';
321 -
322 - $customField['attributes']['name'] = $modifiedAttribute;
323 -
324 - $customField['settings']['label'] = $modifiedLabel;
325 -
326 - // Now, we'll replace the `conditional_logics` property
327 - $customField['settings']['conditional_logics'] = $parentConditionalLogics;
328 -
329 - // Now that this field's properties are handled we can pass
330 - // it to the extract field method to extract it's data.
331 - $this->extractField($customField);
360 + if ($shouldSetMaxValidation) {
361 + $message = Helper::getGlobalDefaultMessage('max');
362 + if (!$message) {
363 + $message = __('Validation fails for maximum value', 'fluentform');
332 364 }
365 + $this->result[$this->attribute]['rules']['max'] = [
366 + 'value' => $maxLength,
367 + 'message' => $message,
368 + ];
333 369 }
334 370
335 371 return $this;
336 372 }
337 -
373 +
374 + /**
375 + * Handle the child fields of complex form fields (address, name, repeater).
376 + *
377 + * This method processes fields that have sub-fields (like address field having
378 + * address_line_1, city, state, etc.) and prepares them for shortcode generation.
379 + *
380 + * @return $this
381 + */
382 + protected function handleCustomField()
383 + {
384 + // If this field is a custom field we'll assume it has it's child fields
385 + // under the `fields` key. Then we are gonna modify those child fields'
386 + // attribute `name`, `label` & `conditional_logics` properties using
387 + // the parent field. The current implementation will modify those
388 + // properties in a way so that we can use dot notation to access.
389 + $customFields = Arr::get($this->field, 'fields');
390 +
391 + if ($customFields) {
392 + $parentAttribute = Arr::get($this->field, 'attributes.name');
393 +
394 + $parentConditionalLogics = Arr::get($this->field, 'settings.conditional_logics', []);
395 +
396 + $isAddressOrNameField = in_array(Arr::get($this->field, 'element'), ['address', 'input_name']);
397 +
398 + $isRepeatField = Arr::get($this->field, 'element') === 'input_repeat' || Arr::get($this->field, 'element') == 'repeater_field';
399 +
400 + // Allow plugins to modify custom fields before processing
401 + $customFields = apply_filters('fluentform/extractor_parser_custom_fields', $customFields, $this->field);
402 +
403 + foreach ($customFields as $index => $customField) {
404 + // If the current field is in fact `address` || `name` field
405 + // then we have to only keep the enabled child fields
406 + // by the user from the form editor settings.
407 + if ($isAddressOrNameField) {
408 + $subFieldName = Arr::get($customField, 'attributes.name');
409 + if (!Arr::get($customField, 'settings.visible', false) && !in_array($subFieldName, ['latitude', 'longitude'])) {
410 + unset($customFields[$index]);
411 + continue;
412 + }
413 + }
414 +
415 + // Depending on whether the parent field is a repeat field or not
416 + // the modified attribute name of the child field will vary.
417 + if ($isRepeatField) {
418 + $modifiedAttribute = $parentAttribute.'['.$index.'].*';
419 + } else {
420 + $modifiedAttribute = $parentAttribute.'['.Arr::get($customField, 'attributes.name').']';
421 + }
422 +
423 + $modifiedLabel = $parentAttribute.'['.Arr::get($customField, 'settings.label').']';
424 +
425 + $customField['attributes']['name'] = $modifiedAttribute;
426 +
427 + $customField['settings']['label'] = $modifiedLabel;
428 +
429 + // Now, we'll replace the `conditional_logics` property
430 + $customField['settings']['conditional_logics'] = $parentConditionalLogics;
431 +
432 + // Now that this field's properties are handled we can pass
433 + // it to the extract field method to extract it's data.
434 + $this->extractField($customField);
435 + }
436 + }
437 +
438 + return $this;
439 + }
440 +
338 441 /**
339 442 * Set the raw field of the form field.
340 443 *
341 444 * @return $this
@@ -344,8 +447,8 @@
344 447 {
345 448 if (in_array('raw', $this->with)) {
346 449 $this->result[$this->attribute]['raw'] = $this->field;
347 450 }
348 -
451 +
349 452 return $this;
350 453 }
351 454 }