PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.21
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.21
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.21, at app/Services/FormBuilder/FormBuilder.php

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