PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
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 / Components / BaseComponent.php

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

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