PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.31
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.31
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 / FormBuilder / FormBuilder.php

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

326 lines 10.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\FormBuilder;
4
5 use FluentForm\App\Helpers\Helper;
6 use FluentForm\Framework\Helpers\ArrayHelper;
7
8 class FormBuilder
9 {
10 /**
11 * The Applivcation instance
12 * @var Framework\Foundation\Application
13 */
14 protected $app = null;
15
16 /**
17 * Conditional logic for elements
18 * @var array
19 */
20 public $conditions = array();
21
22 /**
23 * Validation rules for elements
24 * @var array
25 */
26 public $validationRules = array();
27
28 public $tabIndex = 1;
29
30 public $fieldLists = [];
31
32 public $containerCounter;
33
34 /**
35 * Construct the form builder instance
36 * @param Framework\Foundation\Application $app
37 */
38 public function __construct($app)
39 {
40 $this->app = $app;
41 $this->containerCounter = 1;
42 }
43
44 /**
45 * Render the form
46 * @param \StdClass $form [Form entry from database]
47 * @return mixed
48 */
49 public function build($form, $extraCssClass = '', $instanceCssClass = '')
50 {
51 $hasStepWrapper = isset($form->fields['stepsWrapper']) && $form->fields['stepsWrapper'];
52
53 $labelPlacement = $form->settings['layout']['labelPlacement'];
54
55 $formClass = "frm-fluent-form fluent_form_{$form->id} ff-el-form-{$labelPlacement}";
56
57 if ($extraCssClass) $formClass .= " {$extraCssClass}";
58
59 if ($hasStepWrapper) {
60 $formClass .= ' ff-form-has-steps';
61 }
62
63 if ($extraFormClass = Helper::formExtraCssClass($form)) {
64 $formClass .= ' ' . $extraFormClass;
65 }
66
67 $formBody = $this->buildFormBody($form);
68
69 $formClass = apply_filters('fluentform_form_class', $formClass, $form);
70
71 if ($form->has_payment) {
72 $formClass .= ' fluentform_has_payment';
73 }
74
75 $formAttributes = apply_filters('fluent_form_html_attributes', [
76 'data-form_id' => $form->id,
77 'id' => 'fluentform_'.$form->id,
78 'class' => $formClass,
79 'data-form_instance' => $instanceCssClass
80 ], $form);
81
82 $formAtts = $this->buildAttributes($formAttributes);
83
84 ob_start();
85
86 echo "<div class='fluentform fluentform_wrapper_".$form->id."'>";
87
88 do_action('fluentform_before_form_render', $form);
89
90 echo "<form ".$formAtts.">";
91
92 do_action('fluentform_form_element_start', $form);
93
94 echo "<input type='hidden' name='__fluent_form_embded_post_id' value='" . get_the_ID() . "' />";
95
96 wp_nonce_field(
97 'fluentform-submit-form',
98 '_fluentform_' . $form->id . '_fluentformnonce',
99 true,
100 true
101 );
102
103 echo $formBody;
104
105 echo "</form><div id='fluentform_" . $form->id . "_errors' class='ff-errors-in-stack ";
106
107 echo $extraCssClass . "_errors " . $instanceCssClass . "_errors'></div></div>";
108
109 do_action('fluentform_after_form_render', $form);
110
111 return ob_get_clean();
112 }
113
114
115 public function buildFormBody($form)
116 {
117 $hasStepWrapper = isset($form->fields['stepsWrapper']) && $form->fields['stepsWrapper'];
118
119 ob_start();
120
121 $stepCounter = 1;
122
123 foreach ($form->fields['fields'] as $item) {
124
125 if ($hasStepWrapper && $item['element'] == 'form_step') {
126 $stepCounter++;
127 }
128
129 $this->setUniqueIdentifier($item);
130
131 $item = apply_filters('fluentform_before_render_item', $item, $form);
132
133 do_action('fluentform_render_item_' . $item['element'], $item, $form);
134
135 $this->extractValidationRules($item);
136
137 $this->extractConditionalLogic($item);
138 }
139
140 if ($hasStepWrapper) {
141 do_action('fluentform_render_item_step_end', $form->fields['stepsWrapper']['stepEnd'], $form);
142 } else {
143 do_action('fluentform_render_item_submit_button', $form->fields['submitButton'], $form);
144 }
145
146 $content = ob_get_clean();
147
148 if ($hasStepWrapper) {
149 $startElement = $form->fields['stepsWrapper']['stepStart'];
150
151 $steps = ArrayHelper::get($startElement, 'settings.step_titles');
152
153 // check if $stepCounter == count()
154 if ($stepCounter > count($steps)) {
155 $fillCount = $stepCounter - count($steps);
156 foreach (range(1, $fillCount) as $item) {
157 $steps[] = '';
158 }
159 $startElement['settings']['step_titles'] = $steps;
160 }
161
162 $this->setUniqueIdentifier($startElement);
163
164 ob_start();
165
166 do_action('fluentform_render_item_step_start', $startElement, $form);
167
168 $stepStatrt = ob_get_clean();
169
170 $content = $stepStatrt.$content;
171 }
172
173 return $content;
174 }
175
176 /**
177 * Set unique name/data-name for an element
178 * @param array &$item
179 * @return void
180 */
181 protected function setUniqueIdentifier(&$item)
182 {
183 if (isset($item['columns'])) {
184 $item['attributes']['data-name'] = 'ff_cn_id_'.$this->containerCounter;
185 $this->containerCounter++;
186 foreach ($item['columns'] as &$column) {
187 foreach ($column['fields'] as &$field) {
188 $this->setUniqueIdentifier($field);
189 }
190 }
191 } else {
192 if (!isset($item['attributes']['name'])) {
193 $item['attributes']['name'] = $item['element'] . '-' . uniqid(rand(), true);
194 }
195 $item['attributes']['data-name'] = $item['attributes']['name'];
196 $this->fieldLists[] = $item['element'];
197 }
198 }
199
200 /**
201 * Recursively extract validation rules from a given element
202 * @param array $item
203 * @return void
204 */
205 protected function extractValidationRules($item)
206 {
207 if (isset($item['columns'])) {
208 foreach ($item['columns'] as $column) {
209 foreach ($column['fields'] as $field) {
210 $this->extractValidationRules($field);
211 }
212 }
213 } elseif (isset($item['fields'])) {
214 $rootName = $item['attributes']['name'];
215 foreach ($item['fields'] as $key => $innerItem) {
216 if ($item['element'] == 'address' || $item['element'] == 'input_name') {
217 $itemName = $innerItem['attributes']['name'];
218 $innerItem['attributes']['name'] = $rootName . '[' . $itemName . ']';
219 } else {
220 if ($item['element'] == 'input_repeat' || $item['element'] == 'repeater_field') {
221 if(!empty($innerItem['settings']['validation_rules']['email'])) {
222 unset($innerItem['settings']['validation_rules']['email']);
223 }
224 $innerItem['attributes']['name'] = $rootName . '[' . $key . ']';
225 } else {
226 $innerItem['attributes']['name'] = $rootName;
227 }
228 }
229 $this->extractValidationRule($innerItem);
230 }
231 } elseif ($item['element'] == 'tabular_grid') {
232 $gridName = $item['attributes']['name'];
233 $gridRows = $item['settings']['grid_rows'];
234 $gridType = $item['settings']['tabular_field_type'];
235 foreach ($gridRows as $rowKey => $rowValue) {
236 if ($gridType == 'radio') {
237 $item['attributes']['name'] = $gridName . '[' . $rowKey . ']';
238 $this->extractValidationRule($item);
239 } else {
240 $item['attributes']['name'] = $gridName . '[' . $rowKey . ']';
241 $this->extractValidationRule($item);
242 }
243 }
244 } elseif ($item['element'] == 'chained_select') {
245 $chainedSelectName = $item['attributes']['name'];
246 foreach ($item['settings']['data_source']['headers'] as $select) {
247 $item['attributes']['name'] = $chainedSelectName . '[' . $select . ']';
248 $this->extractValidationRule($item);
249 }
250 } else {
251 $this->extractValidationRule($item);
252 }
253 }
254
255 /**
256 * Extract validation rules from a given element
257 * @param array $item
258 * @return void
259 */
260 protected function extractValidationRule($item)
261 {
262 if (isset($item['settings']['validation_rules'])) {
263 $rules = $item['settings']['validation_rules'];
264 foreach ($rules as $ruleName => $rule) {
265 if(isset($rule['message'])) {
266 $rules[$ruleName]['message'] = apply_filters('fluentform_validation_message_'.$ruleName, $rule['message'], $item);
267 $rules[$ruleName]['message'] = apply_filters('fluentform_validation_message_'.$item['element'].'_'.$ruleName, $rule['message'], $item);
268 }
269 }
270 $rules = apply_filters('fluentform_item_rules_' . $item['element'], $rules, $item);
271 $this->validationRules[ $item['attributes']['name'] ] = $rules;
272 }
273 }
274
275 /**
276 * Extract conditipnal logic from a given element
277 * @param array $item
278 * @return void
279 */
280 protected function extractConditionalLogic($item)
281 {
282 // If container like element, then recurse
283 if (isset($item['columns'])) {
284
285 if (isset($item['settings']['conditional_logics'])) {
286 $conditionals = $item['settings']['conditional_logics'];
287 if (isset($conditionals['status'])) {
288 if ($conditionals['status'] && $conditionals['conditions']) {
289 $this->conditions[$item['attributes']['data-name']] = $item['settings']['conditional_logics'];
290 }
291 }
292 }
293
294 foreach ($item['columns'] as $column) {
295 foreach ($column['fields'] as $field) {
296 $this->extractConditionalLogic($field);
297 }
298 }
299 } elseif (isset($item['settings']['conditional_logics'])) {
300 $conditionals = $item['settings']['conditional_logics'];
301 if (isset($conditionals['status'])) {
302 if ($conditionals['status'] && $conditionals['conditions']) {
303 $this->conditions[$item['attributes']['data-name']] = $item['settings']['conditional_logics'];
304 }
305 }
306 }
307 }
308
309 /**
310 * Build attributes for any html element
311 * @param array $attributes
312 * @return string [Compiled key='value' attributes]
313 */
314 protected function buildAttributes($attributes, $form = null)
315 {
316 $atts = '';
317 foreach ($attributes as $key => $value) {
318 if ($value || $value === 0 || $value === '0') {
319 $value = htmlspecialchars($value);
320 $atts .= $key.'="'.$value.'" ';
321 }
322 }
323 return $atts;
324 }
325 }
326