PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / trunk
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder vtrunk
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
fluentform / app / Services / FormBuilder / Components / BaseComponent.php

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

373 lines 12.8 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\Components;
4
5 use FluentForm\Framework\Helpers\ArrayHelper;
6 use FluentForm\App\Services\FormBuilder\AutocompleteTokens;
7 use FluentForm\App\Modules\Component\Component;
8 use FluentForm\Framework\Support\Helper;
9 use stdClass;
10
11 class BaseComponent
12 {
13 public $app;
14
15 public function __construct($key = '', $title = '', $tags = [], $position = 'advanced')
16 {
17 $this->app = wpFluentForm();
18 }
19
20 /**
21 * Build unique ID concatenating form id and name attribute
22 *
23 * @param array $data $form
24 *
25 * @return string for id value
26 */
27 protected function makeElementId($data, $form)
28 {
29 if (isset($data['attributes']['name'])) {
30 $formInstance = \FluentForm\App\Helpers\Helper::$formInstance;
31 if (!empty($data['attributes']['id'])) {
32 return $data['attributes']['id'];
33 }
34 $elementName = $data['attributes']['name'];
35 $elementName = str_replace(['[', ']', ' '], '_', $elementName);
36
37 $suffix = esc_attr($form->id);
38 if ($formInstance > 1) {
39 $suffix = $suffix . '_' . $formInstance;
40 }
41
42 $suffix .= '_' . $elementName;
43
44 return 'ff_' . esc_attr($suffix);
45 }
46 }
47
48 /**
49 * Build attributes for any html element
50 *
51 * @param array $attributes
52 *
53 * @return string [Compiled key='value' attributes]
54 */
55 protected function buildAttributes($attributes, $form = null)
56 {
57 $atts = '';
58
59 $attributes = AutocompleteTokens::normalizeAttributes($attributes);
60
61 foreach ($attributes as $key => $value) {
62
63 if ($value || 0 === $value || '0' === $value) {
64 $value = htmlspecialchars($value);
65 $atts .= esc_attr($key) . '="' . $value . '" ';
66 }
67 }
68
69 return $atts;
70 }
71
72 /**
73 * Extract value attribute from attribute list
74 *
75 * @param array &$element
76 *
77 * @return string
78 */
79 protected function extractValueFromAttributes(&$element)
80 {
81 $value = '';
82
83 if (isset($element['attributes']['value'])) {
84 $value = $element['attributes']['value'];
85 unset($element['attributes']['value']);
86 }
87
88 return $value;
89 }
90
91 protected function extractDynamicValues($data, $form)
92 {
93 $defaultValues = [];
94 if ($dynamicDefaultValue = ArrayHelper::get($data, 'settings.dynamic_default_value')) {
95 $parseValue = $this->parseEditorSmartCode($dynamicDefaultValue, $form);
96 if (is_array($parseValue)) {
97 $defaultValues = $parseValue;
98 } elseif (!empty($parseValue) && is_string($parseValue)) {
99 $defaultValues = explode(',', $parseValue);
100 $defaultValues = array_map('trim', $defaultValues);
101 }
102 }
103 return $defaultValues;
104 }
105
106 /**
107 * Determine if the given element has conditions bound
108 *
109 * @param array $element [Html element being compiled]
110 *
111 * @return bool
112 */
113 protected function hasConditions($element)
114 {
115 $conditionals = ArrayHelper::get($element, 'settings.conditional_logics');
116
117 if (isset($conditionals['status']) && $conditionals['status']) {
118 if (isset($conditionals['type']) && $conditionals['type'] === 'group') {
119 $groups = ArrayHelper::get($conditionals, 'condition_groups');
120 if (!is_array($groups)) {
121 return false;
122 }
123
124 $groups = array_filter($groups, function ($group) {
125 $rules = ArrayHelper::get($group, 'rules', []);
126 return !empty(array_filter($rules, fn($rule) => !empty($rule['field']) && !empty($rule['operator'])));
127 });
128 return !!$groups;
129 }
130
131 return !!array_filter($conditionals['conditions'], function ($item) {
132 return $item['field'] && $item['operator'];
133 });
134 }
135 return false;
136 }
137
138 /**
139 * Generate a unique id for an element
140 *
141 * @param string $str [preix]
142 *
143 * @return string [Unique id]
144 */
145 protected function getUniqueId($str)
146 {
147 return $str . '_' . md5(uniqid(wp_rand(), true));
148 }
149
150 /**
151 * Get a default class for each form element wrapper
152 * @return string
153 */
154 protected function getDefaultContainerClass()
155 {
156 return 'ff-el-group ';
157 }
158
159 /**
160 * Get required class for form element wrapper
161 *
162 * @param array $rules [Validation rules]
163 *
164 * @return mixed
165 */
166 protected function getRequiredClass($rules)
167 {
168 if (isset($rules['required'])) {
169 return $rules['required']['value'] ? 'ff-el-is-required ' : '';
170 }
171 }
172
173 /**
174 * Get asterisk placement for the required form elements
175 * @return string
176 */
177 protected function getAsteriskPlacement($form)
178 {
179 // for older version compatibility
180 $asteriskPlacement = 'asterisk-right';
181
182 if (isset($form->settings['layout']['asteriskPlacement'])) {
183 $asteriskPlacement = $form->settings['layout']['asteriskPlacement'];
184 }
185
186 return $asteriskPlacement . ' ';
187 }
188
189 /**
190 * Generate a label for any element
191 *
192 * @param array $data
193 *
194 * @return string [label Html element]
195 */
196 protected function buildElementLabel($data, $form)
197 {
198 $helpMessage = '';
199 $helpMessagePlacement = ArrayHelper::get($form->settings, 'layout.helpMessagePlacement', 'with_label');
200 if ('with_label' == $helpMessagePlacement) {
201 $helpMessage = $this->getLabelHelpMessage($data);
202 }
203
204 $id = isset($data['attributes']['id']) ? $data['attributes']['id'] : '';
205 $label = isset($data['settings']['label']) ? $data['settings']['label'] : '';
206 $requiredClass = $this->getRequiredClass(ArrayHelper::get($data, 'settings.validation_rules', []));
207 $classes = trim('ff-el-input--label ' . $requiredClass . $this->getAsteriskPlacement($form));
208
209 return "<div class='" . esc_attr($classes) . "'><label aria-label='" . esc_attr($this->removeShortcode($label)) . "' for='" . esc_attr($id) . "'>" . fluentform_sanitize_html($label) . '</label>' . $helpMessage . '</div>';
210 }
211
212 /**
213 * Generate html/markup for any element
214 *
215 * @param string $elMarkup [Predifined partial markup]
216 * @param array $data
217 * @param stdClass $form [Form object]
218 *
219 * @return string [Compiled markup]
220 */
221 protected function buildElementMarkup($elMarkup, $data, $form)
222 {
223 $hasConditions = $this->hasConditions($data) ? 'has-conditions ' : '';
224
225 $labelPlacement = ArrayHelper::get($data, 'settings.label_placement');
226
227 $labelPlacementClass = $labelPlacement ? 'ff-el-form-' . $labelPlacement . ' ' : '';
228
229 $validationRules = ArrayHelper::get($data, 'settings.validation_rules');
230
231 $requiredClass = $this->getRequiredClass($validationRules);
232
233 $labelClass = trim(
234 'ff-el-input--label ' .
235 $requiredClass .
236 $this->getAsteriskPlacement($form)
237 );
238
239 $formGroupClass = trim(
240 $this->getDefaultContainerClass() .
241 $labelPlacementClass .
242 $hasConditions .
243 ArrayHelper::get($data, 'settings.container_class')
244 );
245
246 $labelHelpText = $inputHelpText = '';
247
248 $labelPlacement = ArrayHelper::get($form->settings, 'layout.helpMessagePlacement', 'with_label');
249 if ('with_label' == $labelPlacement) {
250 $labelHelpText = $this->getLabelHelpMessage($data);
251 } elseif ('on_focus' == $labelPlacement) {
252 $inputHelpText = $this->getInputHelpMessage($data, 'ff-hidden');
253 } elseif ('after_label' == $labelPlacement) {
254 $inputHelpText = $this->getInputHelpMessage($data, 'ff_ahm');
255 } else {
256 $inputHelpText = $this->getInputHelpMessage($data);
257 }
258
259 $forStr = '';
260 $LabelId = '';
261 if (isset($data['attributes']['id'])) {
262 $forStr = "for='" . esc_attr($data['attributes']['id']) . "'";
263 $LabelId = "id='" . esc_attr('label_' . $data['attributes']['id']) . "'";
264 }
265
266 $labelMarkup = '';
267
268 if (!empty($data['settings']['label'])) {
269 $label = ArrayHelper::get($data, 'settings.label');
270 $ariaLabel = $label;
271
272 $hasShortCodeIndex = strpos($label, '{dynamic.');
273
274 //Handle name field duplicate label accessibility
275 $isNameField = strpos(ArrayHelper::get($data, 'attributes.name', ''), 'name') !== false;
276 if ($isNameField) {
277 $ariaLabel = '';
278 } elseif ($hasShortCodeIndex !== false) {
279 $ariaLabel = trim(substr($label, 0, $hasShortCodeIndex));
280 } else {
281 $ariaLabel = $label;
282 }
283
284 $labelMarkup = sprintf(
285 '<div class="%1$s"><label %2$s %3$s %4$s>%5$s</label>%6$s</div>',
286 esc_attr($labelClass),
287 $forStr,
288 $LabelId,
289 $ariaLabel != '' ? 'aria-label="' . esc_attr($this->removeShortcode($label)) . '"' : '',
290 fluentform_sanitize_html($label),
291 fluentform_sanitize_html($labelHelpText)
292 );
293 }
294
295 $inputHelpText = fluentform_sanitize_html($inputHelpText);
296
297 if ('after_label' == $labelPlacement) {
298 $elMarkup = $inputHelpText . $elMarkup;
299 $inputHelpText = '';
300 }
301
302 return sprintf(
303 "<div class='%s'>%s<div class='ff-el-input--content'>%s%s</div></div>",
304 esc_attr($formGroupClass),
305 $labelMarkup,
306 $elMarkup,
307 $inputHelpText
308 );
309 }
310
311 /**
312 * Generate a help message for any element beside label
313 *
314 * @param array $data
315 *
316 * @return string [Html]
317 */
318 protected function getLabelHelpMessage($data)
319 {
320 if (isset($data['settings']['help_message']) && '' != $data['settings']['help_message']) {
321 $text = htmlspecialchars($data['settings']['help_message']);
322 $icon = '<svg width="16" height="16" viewBox="0 0 25 25"><path d="m329 393l0-46c0-2-1-4-2-6-2-2-4-3-7-3l-27 0 0-146c0-3-1-5-3-7-2-1-4-2-7-2l-91 0c-3 0-5 1-7 2-1 2-2 4-2 7l0 46c0 2 1 5 2 6 2 2 4 3 7 3l27 0 0 91-27 0c-3 0-5 1-7 3-1 2-2 4-2 6l0 46c0 3 1 5 2 7 2 1 4 2 7 2l128 0c3 0 5-1 7-2 1-2 2-4 2-7z m-36-256l0-46c0-2-1-4-3-6-2-2-4-3-7-3l-54 0c-3 0-5 1-7 3-2 2-3 4-3 6l0 46c0 3 1 5 3 7 2 1 4 2 7 2l54 0c3 0 5-1 7-2 2-2 3-4 3-7z m182 119c0 40-9 77-29 110-20 34-46 60-80 80-33 20-70 29-110 29-40 0-77-9-110-29-34-20-60-46-80-80-20-33-29-70-29-110 0-40 9-77 29-110 20-34 46-60 80-80 33-20 70-29 110-29 40 0 77 9 110 29 34 20 60 46 80 80 20 33 29 70 29 110z" transform="scale(0.046875 0.046875)"></path></svg>';
323 return sprintf('<div class="ff-el-tooltip" data-content="%s">%s</div>', $text, $icon);
324 }
325 }
326
327 /**
328 * Generate a help message for any element beside form element
329 *
330 * @param array $data
331 *
332 * @return string [Html]
333 */
334 protected function getInputHelpMessage($data, $hideClass = '')
335 {
336 $class = trim('ff-el-help-message ' . $hideClass);
337
338 if (isset($data['settings']['help_message']) && !empty($data['settings']['help_message'])) {
339 return "<div class='" . esc_attr($class) . "'>" . fluentform_sanitize_html($data['settings']['help_message']) . '</div>';
340 }
341 return false;
342 }
343
344 protected function parseEditorSmartCode($text, $form)
345 {
346 return (new Component($this->app))->replaceEditorSmartCodes($text, $form);
347 }
348
349 protected function printContent($hook, $html, $data, $form)
350 {
351 echo apply_filters($hook, $html, $data, $form); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound,WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic hook name for component content filter. $html is escaped before being passed in.
352 }
353
354 /**
355 * A helper method for remove shortcode from aria label
356 *
357 * @param string $label
358 *
359 * @return string $label
360 */
361 protected function removeShortcode($label)
362 {
363 // Find all occurrences of text enclosed in curly braces.
364 preg_match_all('/{(.*?)}/', $label, $matches);
365
366 // If there are matches, remove them from the label.
367 if ($matches[0]) {
368 $label = trim(str_replace($matches[0], '', $label));
369 }
370 return wp_strip_all_tags($label);
371 }
372 }
373