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 +133 -35 3.6.646.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,31 +7,44 @@
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($dynamicValues = $this->extractDynamicValues($data, $form)) {
46 + if ($dynamicValues = $this->extractDynamicValues($data, $form)) {
36 47 $defaultValues = $dynamicValues;
37 48 }
38 49
39 50 $elMarkup = '';
@@ -39,17 +50,17 @@
39 50 $elMarkup = '';
40 51
41 52 $firstTabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex();
42 53
43 - if(!$formattedOptions = ArrayHelper::get($data, 'settings.advanced_options')) {
54 + if (! $formattedOptions = ArrayHelper::get($data, 'settings.advanced_options')) {
44 55 $options = ArrayHelper::get($data, 'options', []);
45 56 $formattedOptions = [];
46 - foreach($options as $value => $label) {
57 + foreach ($options as $value => $label) {
47 58 $formattedOptions[] = [
48 - 'label' => $label,
49 - 'value' => $value,
59 + 'label' => $label,
60 + 'value' => $value,
50 61 'calc_value' => '',
51 - 'image' => ''
62 + 'image' => '',
52 63 ];
53 64 }
54 65 }
55 66
@@ -54,23 +65,47 @@
54 65 }
55 66
56 67 $hasImageOption = ArrayHelper::get($data, 'settings.enable_image_input');
57 68
58 - if($hasImageOption) {
59 - $data['settings']['container_class'] .= '';
69 + if ($hasImageOption) {
70 + if (empty($data['settings']['layout_class'])) {
71 + $data['settings']['layout_class'] = 'ff_list_buttons';
72 + }
60 73 $elMarkup .= '<div class="ff_el_checkable_photo_holders">';
61 74 }
62 75
63 - $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 + );
64 80
65 - if(ArrayHelper::get($data, 'settings.randomize_options') == 'yes') {
81 + if ('yes' == ArrayHelper::get($data, 'settings.randomize_options')) {
66 82 shuffle($formattedOptions);
67 83 }
68 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 = '';
69 105 foreach ($formattedOptions as $option) {
70 -
71 106 $displayType = isset($data['settings']['display_type']) ? ' ff-el-form-check-' . $data['settings']['display_type'] : '';
72 - $parentClass = "ff-el-form-check{$displayType}";
107 + $parentClass = 'ff-el-form-check' . esc_attr($displayType) . '';
73 108
74 109 if (in_array($option['value'], $defaultValues)) {
75 110 $data['attributes']['checked'] = true;
76 111 $parentClass .= ' ff_item_selected';
@@ -77,41 +112,104 @@
77 112 } else {
78 113 $data['attributes']['checked'] = false;
79 114 }
80 115
81 - if($firstTabIndex) {
116 + if ($firstTabIndex) {
82 117 $data['attributes']['tabindex'] = $firstTabIndex;
83 118 $firstTabIndex = '-1';
84 119 }
85 120
86 121 $data['attributes']['value'] = $option['value'];
87 - $data['attributes']['data-calc_value'] = ArrayHelper::get($option,'calc_value');
122 + $data['attributes']['data-calc_value'] = ArrayHelper::get($option, 'calc_value');
88 123
89 124 $atts = $this->buildAttributes($data['attributes']);
90 125
91 -
92 126 $id = $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name']));
93 127
94 -
95 - if($hasImageOption) {
128 + if ($hasImageOption) {
96 129 $parentClass .= ' ff-el-image-holder';
97 130 }
98 131
99 - $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);
100 138 // Here we can push the visual items
101 - if($hasImageOption) {
102 - $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>";
103 141 }
104 142
105 - $elMarkup .= "<label class='ff-el-form-check-label' for={$id}><input {$atts} id='{$id}'> <span>{$option['label']}</span></label>";
106 - $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>';
107 189 }
108 190
109 -
110 - if($hasImageOption) {
191 + if ($hasImageOption) {
111 192 $elMarkup .= '</div>';
112 193 }
194 + if ($otherInputHtml) {
195 + $elMarkup .= $otherInputHtml;
196 + }
197 +// $elMarkup .= '</fieldset>';
113 198
114 199 $html = $this->buildElementMarkup($elMarkup, $data, $form);
115 - 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);
116 214 }
117 -}
215 +}