← All changes
|
app/Services/FormBuilder/Components/Checkable.php
+136
-34
3.6.51
→
6.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,19 +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 | |
| 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 = ''; | |
| 65 | 105 | foreach ($formattedOptions as $option) { |
| 66 | - | |
| 67 | 106 | $displayType = isset($data['settings']['display_type']) ? ' ff-el-form-check-' . $data['settings']['display_type'] : ''; |
| 68 | - $parentClass = "ff-el-form-check{$displayType}"; | |
| 107 | + $parentClass = 'ff-el-form-check' . esc_attr($displayType) . ''; | |
| 69 | 108 | |
| 70 | 109 | if (in_array($option['value'], $defaultValues)) { |
| 71 | 110 | $data['attributes']['checked'] = true; |
| 72 | 111 | $parentClass .= ' ff_item_selected'; |
| @@ -73,41 +112,104 @@ | ||
| 73 | 112 | } else { |
| 74 | 113 | $data['attributes']['checked'] = false; |
| 75 | 114 | } |
| 76 | 115 | |
| 77 | - if($firstTabIndex) { | |
| 116 | + if ($firstTabIndex) { | |
| 78 | 117 | $data['attributes']['tabindex'] = $firstTabIndex; |
| 79 | 118 | $firstTabIndex = '-1'; |
| 80 | 119 | } |
| 81 | 120 | |
| 82 | 121 | $data['attributes']['value'] = $option['value']; |
| 83 | - $data['attributes']['data-calc_value'] = ArrayHelper::get($option,'calc_value'); | |
| 122 | + $data['attributes']['data-calc_value'] = ArrayHelper::get($option, 'calc_value'); | |
| 84 | 123 | |
| 85 | 124 | $atts = $this->buildAttributes($data['attributes']); |
| 86 | 125 | |
| 87 | - | |
| 88 | 126 | $id = $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name'])); |
| 89 | 127 | |
| 90 | - | |
| 91 | - if($hasImageOption) { | |
| 128 | + if ($hasImageOption) { | |
| 92 | 129 | $parentClass .= ' ff-el-image-holder'; |
| 93 | 130 | } |
| 94 | 131 | |
| 95 | - $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); | |
| 96 | 138 | // Here we can push the visual items |
| 97 | - if($hasImageOption) { | |
| 98 | - $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>"; | |
| 99 | 141 | } |
| 100 | 142 | |
| 101 | - $elMarkup .= "<label class='ff-el-form-check-label' for={$id}><input {$atts} id='{$id}'> <span>{$option['label']}</span></label>"; | |
| 102 | - $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>'; | |
| 103 | 189 | } |
| 104 | 190 | |
| 105 | - | |
| 106 | - if($hasImageOption) { | |
| 191 | + if ($hasImageOption) { | |
| 107 | 192 | $elMarkup .= '</div>'; |
| 108 | 193 | } |
| 194 | + if ($otherInputHtml) { | |
| 195 | + $elMarkup .= $otherInputHtml; | |
| 196 | + } | |
| 197 | +// $elMarkup .= '</fieldset>'; | |
| 109 | 198 | |
| 110 | 199 | $html = $this->buildElementMarkup($elMarkup, $data, $form); |
| 111 | - 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); | |
| 112 | 214 | } |
| 113 | -} | |
| 215 | +} | |