PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.12
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.12
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 / Parser / Validations.php

Validations.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.12, at app/Services/Parser/Validations.php

253 lines 6.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\Parser;
4
5 use FluentForm\Framework\Helpers\ArrayHelper as Arr;
6
7 class Validations
8 {
9 /**
10 * Form fields that were defined when the form was created.
11 *
12 * @var array
13 */
14 protected $fields;
15
16 /**
17 * Form inputs that were submited by the user.
18 *
19 * @var array
20 */
21 protected $inputs;
22
23 /**
24 * The current field accessor of the fields' iteration.
25 *
26 * @var string
27 */
28 protected $accessor;
29
30 /**
31 * The repeater field settings. It is being set if the
32 * field in iteration is indeed a repeater field.
33 *
34 * @var array
35 */
36 protected $repeater = [
37 'status' => false,
38 'attribute' => '',
39 'length' => 0,
40 'rule' => ''
41 ];
42
43 /**
44 * The extracted validation rules.
45 *
46 * @var array
47 */
48 protected $rules = [];
49
50 /**
51 * The extracted validation messages.
52 *
53 * @var array
54 */
55 protected $messages = [];
56
57 /**
58 * The validation extractor constructor.
59 *
60 * @param array $formFields
61 * @param array $formData
62 */
63 public function __construct($formFields = [], $formData = [])
64 {
65 $this->fields = $formFields;
66 $this->inputs = $formData;
67 }
68
69 /**
70 * Get the extracted validation rules and messages.
71 *
72 * @return array
73 */
74 public function get()
75 {
76 foreach ($this->fields as $fieldName => $field) {
77 $this->setFieldAccessor($fieldName);
78
79 $fieldValue = $this->getFieldValue();
80
81 $rules = (array) $field['rules'];
82
83 $hasRequiredRule = Arr::get($rules, 'required.value');
84
85 // If the field is a repeater we'll set some settings here.
86 $this->setRepeater($fieldName, $field);
87
88 foreach ($rules as $ruleName => $rule) {
89 if ($this->shouldNotSkipThisRule($rule, $fieldValue, $hasRequiredRule)) {
90 $this->prepareValidations($fieldName, $ruleName, $rule);
91 }
92 }
93
94 $this->ensureStringTypeForSizeRules($fieldName, $rules);
95 }
96
97
98 return [$this->rules, $this->messages];
99 }
100
101 /**
102 * Set the field accessor by replacing the `[]`, `*` by `.`
103 * so that dot notation can be used to access the inputs.
104 *
105 * @param string $fieldName
106 * @return $this
107 */
108 protected function setFieldAccessor($fieldName)
109 {
110 $this->accessor = rtrim(str_replace(['[', ']', '*'], ['.'], $fieldName), '.');
111
112 return $this;
113 }
114
115 /**
116 * Get the field value from the form data.
117 *
118 * @return mixed
119 */
120 protected function getFieldValue()
121 {
122 return Arr::get($this->inputs, $this->accessor);
123 }
124
125 /**
126 * Set the repeater settings if the field in
127 * iteration is indeed a repeater field.
128 *
129 * @param string $fieldName
130 * @param array $field
131 * @return $this
132 */
133 protected function setRepeater($fieldName, $field)
134 {
135 $isRepeater = Arr::get($field, 'element') === 'input_repeat' || Arr::get($field, 'element') == 'repeater_field';
136
137 if ($isRepeater) {
138 $attribute = Arr::get($field, 'attributes.name');
139 $length = isset($attribute[0]) ? count($attribute[0]) : 0;
140 $this->repeater = [
141 'status' => true,
142 'attribute' => $attribute,
143 'length' => $length,
144 'rule' => rtrim($fieldName, '.*')
145 ];
146 } else {
147 $this->repeater['status'] = false;
148 }
149
150 return $this;
151 }
152
153 /**
154 * Determines if the iteration should skip this rule or not.
155 *
156 * @param array $rule
157 * @return boolean
158 */
159 protected function shouldNotSkipThisRule($rule, $fieldValue, $hasRequiredRule)
160 {
161 // If the rule is enabled and the field is not empty and
162 // it does have at least one required rule then we
163 // should validate it for other rules. Else, we
164 // will skip this rule meaning enabling empty
165 // submission for this field.
166 return $rule['value'] && !($fieldValue === '' && !$hasRequiredRule);
167 }
168
169 /**
170 * Prepare the validation extraction.
171 *
172 * @param string $fieldName
173 * @param string $ruleName
174 * @param array $rule
175 */
176 protected function prepareValidations($fieldName, $ruleName, $rule)
177 {
178 $logic = $this->getLogic($ruleName, $rule);
179
180 if ($this->repeater['status']) {
181 for ($i = 0; $i < $this->repeater['length']; $i++) {
182 // We need to modify the field name for repeater field.
183 $fieldName = $this->repeater['rule'].'['.$i.']';
184
185 $this->setValidations($fieldName, $ruleName, $rule, $logic);
186 }
187 } else {
188 $this->setValidations($fieldName, $ruleName, $rule, $logic);
189 }
190 }
191
192 /**
193 * Set the validation rules & messages
194 *
195 * @param string $fieldName
196 * @param string $ruleName
197 * @param array $rule
198 * @param string $logic
199 */
200 protected function setValidations($fieldName, $ruleName, $rule, $logic)
201 {
202 // if there is already a rule for this field we need to
203 // concat current rule to it. else assign current rule.
204 $this->rules[$fieldName] = isset($this->rules[$fieldName]) ?
205 $this->rules[$fieldName].'|'.$logic : $logic;
206
207 $this->messages[$fieldName.'.'.$ruleName] = $rule['message'];
208 }
209
210 /**
211 * Get the logic name for the current rule.
212 *
213 * @param string $ruleName
214 * @param array $rule
215 * @return string
216 */
217 protected function getLogic($ruleName, $rule)
218 {
219 // The file type input has rule values in an array. For
220 // that we are taking arrays into consideration.
221 $ruleValue = is_array($rule['value']) ?
222 implode(',', array_filter(array_values(str_replace('|', ',', $rule['value'])))) :
223 $rule['value'];
224
225 return $ruleName.':'.$ruleValue;
226 }
227
228 /**
229 * Ensure fields with max/min rules but no numeric rule
230 * are treated as strings for character-length validation.
231 *
232 * Without this, the WPFluent validator treats numeric-looking
233 * input (e.g. phone "123456") as a number and compares the
234 * numeric value against max/min instead of string length.
235 *
236 * @param string $fieldName
237 * @param array $rules
238 */
239 protected function ensureStringTypeForSizeRules($fieldName, $rules)
240 {
241 if (!isset($this->rules[$fieldName])) {
242 return;
243 }
244
245 $hasSizeRule = !empty($rules['max']['value']) || !empty($rules['min']['value']);
246 $hasNumericRule = !empty($rules['numeric']['value']);
247
248 if ($hasSizeRule && !$hasNumericRule && !is_array($this->getFieldValue())) {
249 $this->rules[$fieldName] = 'string|' . $this->rules[$fieldName];
250 }
251 }
252 }
253