PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.9
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.9
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.9, at app/Services/Parser/Validations.php

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