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
← All changes | app/Services/FormBuilder/Components/Checkable.php +137 -38 3.6.416.2.14 View file →
@@ -1,10 +1,8 @@
1 1 <?php
2 2
3 3 namespace FluentForm\App\Services\FormBuilder\Components;
4 4
5 -use FluentForm\App\Helpers\Helper;
6 -use FluentForm\App\Modules\Component\Component;
7 5 use FluentForm\Framework\Helpers\ArrayHelper;
8 6
9 7 class Checkable extends BaseComponent
10 8 {
@@ -9,35 +7,45 @@
9 7 class Checkable extends BaseComponent
10 8 {
11 9 /**
12 10 * Compile and echo the html element
13 - * @param array $data [element data]
14 - * @param stdClass $form [Form Object]
15 - * @return viod
11 + *
12 + * @param array $data [element data]
13 + * @param \stdClass $form [Form Object]
14 + *
15 + * @return void
16 16 */
17 17 public function compile($data, $form)
18 18 {
19 19 $elementName = $data['element'];
20 +
21 + $data = apply_filters_deprecated(
22 + 'fluentform_rendering_field_data_' . $elementName,
23 + [
24 + $data,
25 + $form
26 + ],
27 + FLUENTFORM_FRAMEWORK_UPGRADE,
28 + 'fluentform/rendering_field_data_' . $elementName,
29 + 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName
30 + );
20 31
21 - $data = apply_filters('fluenform_rendering_field_data_'.$elementName, $data, $form);
32 + $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form);
22 33
23 34 $data['attributes']['class'] = trim(
24 35 'ff-el-form-check-input ' .
25 - 'ff-el-form-check-'.$data['attributes']['type'].' '.
36 + 'ff-el-form-check-' . $data['attributes']['type'] . ' ' .
26 37 ArrayHelper::get($data, 'attributes.class')
27 38 );
28 39
29 - if ($data['attributes']['type'] == 'checkbox') {
40 + if ('checkbox' == $data['attributes']['type']) {
30 41 $data['attributes']['name'] = $data['attributes']['name'] . '[]';
31 42 }
32 43
33 - $defaultValues = (array)$this->extractValueFromAttributes($data);
44 + $defaultValues = (array) $this->extractValueFromAttributes($data);
34 45
35 - if($dynamicDefaultValue = ArrayHelper::get($data, 'settings.dynamic_default_value')) {
36 - $parseValue = $this->parseEditorSmartCode($dynamicDefaultValue, $form);
37 - if($parseValue) {
38 - $defaultValues = (array) $parseValue;
39 - }
46 + if ($dynamicValues = $this->extractDynamicValues($data, $form)) {
47 + $defaultValues = $dynamicValues;
40 48 }
41 49
42 50 $elMarkup = '';
43 51
@@ -42,17 +50,17 @@
42 50 $elMarkup = '';
43 51
44 52 $firstTabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex();
45 53
46 - if(!$formattedOptions = ArrayHelper::get($data, 'settings.advanced_options')) {
54 + if (! $formattedOptions = ArrayHelper::get($data, 'settings.advanced_options')) {
47 55 $options = ArrayHelper::get($data, 'options', []);
48 56 $formattedOptions = [];
49 - foreach($options as $value => $label) {
57 + foreach ($options as $value => $label) {
50 58 $formattedOptions[] = [
51 - 'label' => $label,
52 - 'value' => $value,
59 + 'label' => $label,
60 + 'value' => $value,
53 61 'calc_value' => '',
54 - 'image' => ''
62 + 'image' => '',
55 63 ];
56 64 }
57 65 }
58 66
@@ -57,19 +65,47 @@
57 65 }
58 66
59 67 $hasImageOption = ArrayHelper::get($data, 'settings.enable_image_input');
60 68
61 - if($hasImageOption) {
62 - $data['settings']['container_class'] .= '';
69 + if ($hasImageOption) {
70 + if (empty($data['settings']['layout_class'])) {
71 + $data['settings']['layout_class'] = 'ff_list_buttons';
72 + }
63 73 $elMarkup .= '<div class="ff_el_checkable_photo_holders">';
64 74 }
65 75
66 - $data['settings']['container_class'] .= ' '.ArrayHelper::get($data, 'settings.layout_class');
76 + $data['settings']['container_class'] = trim(
77 + ArrayHelper::get($data, 'settings.container_class', '')
78 + . ' ' . ArrayHelper::get($data, 'settings.layout_class', '')
79 + );
67 80
81 + if ('yes' == ArrayHelper::get($data, 'settings.randomize_options')) {
82 + shuffle($formattedOptions);
83 + }
84 +
85 + // Add "Other" option if enabled
86 + $enableOtherOption = ArrayHelper::get($data, 'settings.enable_other_option') === 'yes';
87 + if ($enableOtherOption && in_array($data['attributes']['type'], ['checkbox', 'radio']) && defined('FLUENTFORMPRO')) {
88 + $fieldName = sanitize_text_field(str_replace(['[', ']'], '', $data['attributes']['name']));
89 + $otherLabel = ArrayHelper::get($data, 'settings.other_option_label', __('Other', 'fluentform'));
90 + $formattedOptions[] = [
91 + 'label' => $otherLabel,
92 + 'value' => '__ff_other_' . $fieldName . '__',
93 + 'calc_value' => '',
94 + 'image' => '',
95 + 'is_other' => true,
96 + ];
97 + }
98 +// @todo : Find a alternative screen reader support
99 +// $legendId = $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name']));
100 +// $elMarkup .= '<fieldset role="group" style="border: none!important;margin: 0!important;padding: 0!important;background-color: transparent!important;box-shadow: none!important;outline: none!important; min-inline-size: 100%;" aria-labelledby="legend_' . $legendId . '">';
101 +//
102 +// $elMarkup .= '<legend style=" position: absolute;width: 1px;height: 1px;padding: 0;margin: 0;overflow: hidden;clip: rect(0, 0, 0, 0);border: 0;" role="heading" id="legend_' . $legendId . '" class="ff-sreader-only">' . esc_attr($this->removeShortcode($data['settings']['label'])) . '</legend>';
103 +
104 + $otherInputHtml = '';
68 105 foreach ($formattedOptions as $option) {
69 -
70 106 $displayType = isset($data['settings']['display_type']) ? ' ff-el-form-check-' . $data['settings']['display_type'] : '';
71 - $parentClass = "ff-el-form-check{$displayType}";
107 + $parentClass = 'ff-el-form-check' . esc_attr($displayType) . '';
72 108
73 109 if (in_array($option['value'], $defaultValues)) {
74 110 $data['attributes']['checked'] = true;
75 111 $parentClass .= ' ff_item_selected';
@@ -76,41 +112,104 @@
76 112 } else {
77 113 $data['attributes']['checked'] = false;
78 114 }
79 115
80 - if($firstTabIndex) {
116 + if ($firstTabIndex) {
81 117 $data['attributes']['tabindex'] = $firstTabIndex;
82 118 $firstTabIndex = '-1';
83 119 }
84 120
85 121 $data['attributes']['value'] = $option['value'];
86 - $data['attributes']['data-calc_value'] = ArrayHelper::get($option,'calc_value');
122 + $data['attributes']['data-calc_value'] = ArrayHelper::get($option, 'calc_value');
87 123
88 124 $atts = $this->buildAttributes($data['attributes']);
89 125
90 -
91 126 $id = $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name']));
92 127
93 -
94 - if($hasImageOption) {
128 + if ($hasImageOption) {
95 129 $parentClass .= ' ff-el-image-holder';
96 130 }
97 131
98 - $elMarkup .= "<div class='{$parentClass}'>";
132 + $elMarkup .= "<div class='" . esc_attr($parentClass) . "'>";
133 +
134 + $id = esc_attr($id);
135 +
136 + $label = fluentform_sanitize_html($option['label']);
137 + $ariaLabel = esc_attr($label);
99 138 // Here we can push the visual items
100 - if($hasImageOption) {
101 - $elMarkup .= "<label style='background-image: url({$option['image']})' class='ff-el-image-input-src' for={$id}></label>";
139 + if ($hasImageOption) {
140 + $elMarkup .= "<label style='background-image: url(" . esc_url($option['image']) . ")' class='ff-el-image-input-src' for='{$id}' aria-label='{$this->removeShortcode($ariaLabel)}'></label>";
102 141 }
103 142
104 - $elMarkup .= "<label class='ff-el-form-check-label' for={$id}><input {$atts} id='{$id}'> <span>{$option['label']}</span></label>";
105 - $elMarkup .= "</div>";
143 + $ariaRequired = 'false';
144 + if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) {
145 + $ariaRequired = 'true';
146 + }
147 +
148 + $disabled = ArrayHelper::get($option, 'disabled') ? 'disabled' : '';
149 +
150 + $isOtherOption = ArrayHelper::get($option, 'is_other', false);
151 + $otherClass = $isOtherOption ? ' ff-other-option' : '';
152 +
153 + $elMarkup .= "<label class='ff-el-form-check-label{$otherClass}' for='{$id}'><input {$disabled} {$atts} id='{$id}' aria-label='{$this->removeShortcode($ariaLabel)}' aria-invalid='false' aria-required={$ariaRequired}> <span>" . $label . '</span></label>';
154 +
155 + // Add text input for "Other" option
156 + if ($isOtherOption && defined('FLUENTFORMPRO')) {
157 + $otherPlaceholder = ArrayHelper::get($data, 'settings.other_option_placeholder', __('Please specify...', 'fluentform'));
158 + $fieldName = str_replace(['[', ']'], '', $data['attributes']['name']);
159 + $otherInputName = $fieldName . '__ff_other_input__';
160 + $otherValue = '';
161 +
162 + // Defaulted like the sibling reads above: forms saved before this
163 + // setting existed would otherwise fall through to the field's
164 + // "This field is required", which is wrong on an optional field.
165 + $otherRequiredMessage = trim((string) ArrayHelper::get(
166 + $data,
167 + 'settings.other_option_required_message',
168 + __('Please specify a value for the selected "Other" option', 'fluentform')
169 + ));
170 +
171 + // An "Other" that is already selected (configured or dynamic
172 + // default) must render with its input visible and required —
173 + // otherwise the field is mandatory but invisible and the form
174 + // cannot be submitted at all.
175 + $otherIsSelected = in_array($option['value'], $defaultValues);
176 + $wrapperDisplay = $otherIsSelected ? '' : 'display: none; ';
177 + $otherAriaRequired = $otherIsSelected ? " aria-required='true'" : '';
178 +
179 + $marginTop = $hasImageOption ? '20px' : '8px';
180 + $otherInputHtml .= "<div class='ff-other-input-wrapper' style='{$wrapperDisplay}margin-top: {$marginTop};' data-field='" . esc_attr($fieldName) . "' data-required-message='" . esc_attr($otherRequiredMessage) . "'>";
181 + // The id is what the validator points aria-describedby at when the
182 + // free text is required but empty.
183 + $otherInputId = $this->getUniqueid('ff_other_' . $fieldName);
184 + $otherInputHtml .= "<input type='text' id='" . esc_attr($otherInputId) . "' name='" . esc_attr($otherInputName) . "' class='ff-el-form-control'{$otherAriaRequired} placeholder='" . esc_attr($otherPlaceholder) . "' value='" . esc_attr($otherValue) . "'>";
185 + $otherInputHtml .= "</div>";
186 + }
187 +
188 + $elMarkup .= '</div>';
106 189 }
107 190
108 -
109 - if($hasImageOption) {
191 + if ($hasImageOption) {
110 192 $elMarkup .= '</div>';
111 193 }
194 + if ($otherInputHtml) {
195 + $elMarkup .= $otherInputHtml;
196 + }
197 +// $elMarkup .= '</fieldset>';
112 198
113 199 $html = $this->buildElementMarkup($elMarkup, $data, $form);
114 - echo apply_filters('fluenform_rendering_field_html_'.$elementName, $html, $data, $form);
200 +
201 + $data = apply_filters_deprecated(
202 + 'fluentform_rendering_field_html_' . $elementName,
203 + [
204 + $html,
205 + $data,
206 + $form
207 + ],
208 + FLUENTFORM_FRAMEWORK_UPGRADE,
209 + 'fluentform/rendering_field_html_' . $elementName,
210 + 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_nonce_verify.'
211 + );
212 +
213 + $this->printContent('fluentform/rendering_field_html_' . $elementName, $html, $data, $form);
115 214 }
116 -}
215 +}