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/TabularGrid.php +122 -87 3.6.646.2.14 View file →
@@ -5,120 +5,155 @@
5 5 use FluentForm\Framework\Helpers\ArrayHelper;
6 6
7 7 class TabularGrid extends BaseComponent
8 8 {
9 - /**
10 - * Compile and echo the html element
11 - * @param array $data [element data]
12 - * @param stdClass $form [Form Object]
13 - * @return viod
14 - */
15 - public function compile($data, $form)
16 - {
9 + /**
10 + * Compile and echo the html element
11 + *
12 + * @param array $data [element data]
13 + * @param \stdClass $form [Form Object]
14 + *
15 + * @return void
16 + */
17 + public function compile($data, $form)
18 + {
17 19 $elementName = $data['element'];
18 - $data = apply_filters('fluenform_rendering_field_data_'.$elementName, $data, $form);
20 + $data = apply_filters_deprecated(
21 + 'fluentform_rendering_field_data_' . $elementName,
22 + [
23 + $data,
24 + $form
25 + ],
26 + FLUENTFORM_FRAMEWORK_UPGRADE,
27 + 'fluentform/rendering_field_data_' . $elementName,
28 + 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName
29 + );
30 + $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form);
19 31
20 32 $checked = $data['settings']['selected_grids'];
21 - $columnLabels = $data['settings']['grid_columns'];
33 + $columnLabels = $data['settings']['grid_columns'];
22 34
35 + $fieldType = $data['settings']['tabular_field_type'];
36 + $columnHeaders = implode('</th><th>', array_values($columnLabels));
37 + $elementHelpMessage = $this->getElementHelpMessage($data, $form);
38 + $elementLabel = $this->setClasses($data)->buildElementLabel($data, $form);
23 39
24 - $fieldType = $data['settings']['tabular_field_type'];
25 - $columnHeaders = implode('</th><th>', array_values($columnLabels));
26 - $elementHelpMessage = $this->getElementHelpMessage($data, $form);
27 - $elementLabel = $this->setClasses($data)->buildElementLabel($data, $form);
28 -
40 + $elMarkup = "<table class='ff-table ff-checkable-grids ff_flexible_table' role='table'><thead><tr><th></th><th>" . fluentform_sanitize_html($columnHeaders) . '</th></tr></thead><tbody>';
29 41
30 - $elMarkup = "<table class='ff-table ff-checkable-grids ff_flexible_table'><thead><tr><th></th><th>{$columnHeaders}</th></tr></thead><tbody>";
31 -
32 42 $tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex();
33 - foreach ($this->makeTabularData($data) as $index => $row) {
34 - $elMarkup .= "<tr>";
35 - $elMarkup .= "<td class='ff_grid_header'>{$row['label']}</td>";
36 - $isRowChecked = in_array($row['name'], $checked) ? 'checked' : '';
37 - foreach ($row['columns'] as $column) {
38 - $name = $data['attributes']['name'] . '['.$row['name'].']';
39 - $name = $fieldType == 'checkbox' ? ($name.'[]') : $name;
40 - $isColChecked = in_array($column['name'], $checked) ? 'checked' : '';
41 - $isChecked = $isRowChecked ? $isRowChecked : $isColChecked;
43 + foreach ($this->makeTabularData($data) as $index => $row) {
44 + $elMarkup .= '<tr role="row"">';
45 + $elMarkup .= "<td class='ff_grid_header' role='cell'>" . fluentform_sanitize_html($row['label']) . '</td>';
46 + $isRowChecked = in_array($row['name'], $checked) ? 'checked' : '';
47 + foreach ($row['columns'] as $column) {
48 + $name = $data['attributes']['name'] . '[' . $row['name'] . ']';
49 + $name = 'checkbox' == $fieldType ? ($name . '[]') : $name;
50 + $isColChecked = in_array($column['name'], $checked) ? 'checked' : '';
51 + $isChecked = $isRowChecked ? $isRowChecked : $isColChecked;
42 52
43 - $atts = [
44 - 'name' => $name,
45 - 'type' => $fieldType,
46 - 'value' => $column['name']
53 + $atts = [
54 + 'name' => $name,
55 + 'type' => $fieldType,
56 + 'value' => $column['name'],
47 57 ];
48 - if($tabIndex) {
58 + if ($tabIndex) {
49 59 $atts['tabindex'] = $tabIndex;
50 60 }
51 - $attributes = $this->buildAttributes($atts, $form);
61 + $attributes = $this->buildAttributes($atts, $form);
52 62
53 - $input = "<input ".$attributes." {$isChecked}>";
54 - $elMarkup .= "<td data-label='".$column['label']."'>{$input}</td>";
55 - }
56 - $elMarkup .= "</tr>";
57 - }
63 + $ariaRequired = 'false';
64 + if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) {
65 + $ariaRequired = 'true';
66 + }
58 67
59 - $elMarkup .= "</tbody></table>";
68 + // SECURITY (FINDING-12): esc_attr the row/column labels before interpolating them
69 + // into the double-quoted aria-label; save-time sanitizers do not encode quotes.
70 + $input = '<input aria-label="'. esc_attr($row['name']) .'-'. esc_attr($column['label']) . '" ' . $attributes . " {$isChecked} aria-invalid='false' aria-required={$ariaRequired}>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $attributes is escaped before being passed in.
71 + $responsiveLabel = esc_attr(wp_strip_all_tags($column['label']));
72 + $elMarkup .= "<td data-label='{$responsiveLabel}'>{$input}</td>";
73 + }
74 + $elMarkup .= '</tr>';
75 + }
60 76
61 - $elMarkup = "<div class='ff-el-input--content'>{$elMarkup}{$elementHelpMessage}</div>";
77 + $elMarkup .= '</tbody></table>';
62 78
63 - $html = sprintf(
64 - "<div data-type='%s' data-name='%s' class='%s'>{$elementLabel}{$elMarkup}</div>",
65 - $data['attributes']['data-type'],
66 - $data['attributes']['name'],
67 - $data['attributes']['class']
68 - );
79 + $elMarkup = "<div class='ff-el-input--content'>{$elMarkup}" . fluentform_sanitize_html($elementHelpMessage) . '</div>';
69 80
70 - echo apply_filters('fluenform_rendering_field_html_'.$elementName, $html, $data, $form);
81 + // SECURITY (FINDING-12): esc_attr the attribute values interpolated into the single-quoted
82 + // data-type / data-name / class attributes; sanitize_text_field at save does not encode quotes.
83 + $html = sprintf(
84 + "<div data-type='%s' data-name='%s' class='%s'>%s",
85 + esc_attr($data['attributes']['data-type']),
86 + esc_attr($data['attributes']['name']),
87 + esc_attr($data['attributes']['class']),
88 + $elementLabel
89 + ) . $elMarkup . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $elementLabel is escaped before being passed in.
90 +
91 + $html = apply_filters_deprecated(
92 + 'fluentform_rendering_field_html_' . $elementName,
93 + [
94 + $html,
95 + $data,
96 + $form
97 + ],
98 + FLUENTFORM_FRAMEWORK_UPGRADE,
99 + 'fluentform/rendering_field_html_' . $elementName,
100 + 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName
101 + );
102 + $this->printContent('fluentform/rendering_field_html_' . $elementName, $html, $data, $form);
71 103 }
72 104
73 - public function makeTabularData($data)
74 - {
75 - $table = [];
76 - $rows = $data['settings']['grid_rows'];
77 - $columns = $data['settings']['grid_columns'];
105 + public function makeTabularData($data)
106 + {
107 + $table = [];
108 + $rows = $data['settings']['grid_rows'];
109 + $columns = $data['settings']['grid_columns'];
78 110
79 - foreach ($rows as $rowKey => $rowValue) {
80 - $table[$rowKey] = [
81 - 'name' => $rowKey,
82 - 'label' => $rowValue,
83 - 'columns' => []
84 - ];
111 + foreach ($rows as $rowKey => $rowValue) {
112 + $rowKey = trim(sanitize_text_field($rowKey));
113 + $table[$rowKey] = [
114 + 'name' => $rowKey,
115 + 'label' => $rowValue,
116 + 'columns' => [],
117 + ];
85 118
86 - foreach ($columns as $columnKey => $columnValue) {
87 - $table[$rowKey]['columns'][] = [
88 - 'name' => $columnKey,
89 - 'label' => $columnValue
90 - ];
91 - }
92 - }
119 + foreach ($columns as $columnKey => $columnValue) {
120 + $columnKey = trim(sanitize_text_field($columnKey));
121 + $table[$rowKey]['columns'][] = [
122 + 'name' => $columnKey,
123 + 'label' => $columnValue,
124 + ];
125 + }
126 + }
93 127
94 - return $table;
95 - }
128 + return $table;
129 + }
96 130
97 - protected function getElementHelpMessage($data, $form)
98 - {
99 - $elementHelpMessage = '';
100 - if ($form->settings['layout']['helpMessagePlacement'] == 'under_input') {
131 + protected function getElementHelpMessage($data, $form)
132 + {
133 + $elementHelpMessage = '';
134 + $helpMessagePlacement = ArrayHelper::get($form->settings, 'layout.helpMessagePlacement', 'with_label');
135 + if ('under_input' == $helpMessagePlacement) {
101 136 $elementHelpMessage = $this->getInputHelpMessage($data);
102 137 }
103 138
104 139 return $elementHelpMessage;
105 - }
140 + }
106 141
107 - protected function setClasses(&$data)
108 - {
109 - if (!isset($data['attributes']['class'])) {
110 - $data['attributes']['class'] = '';
111 - }
142 + protected function setClasses(&$data)
143 + {
144 + if (! isset($data['attributes']['class'])) {
145 + $data['attributes']['class'] = '';
146 + }
112 147
113 - $placement = $data['settings']['label_placement'];
114 - $placementClass = $placement ? 'ff-el-form-'.$placement : '';
115 - $hasConditions = $this->hasConditions($data) ? ' has-conditions' : '';
116 - $defaultContainerClass = $this->getDefaultContainerClass();
117 - $containerClass = $data['settings']['container_class'];
118 - $data['attributes']['class'] .= trim(implode(' ', array_map('trim', [
119 - $defaultContainerClass, $containerClass, $placementClass, $hasConditions
120 - ])));
121 -
122 - return $this;
123 - }
148 + $placement = $data['settings']['label_placement'];
149 + $placementClass = $placement ? 'ff-el-form-' . $placement : '';
150 + $hasConditions = $this->hasConditions($data) ? ' has-conditions' : '';
151 + $defaultContainerClass = $this->getDefaultContainerClass();
152 + $containerClass = $data['settings']['container_class'];
153 + $data['attributes']['class'] .= trim(implode(' ', array_map('trim', [
154 + $defaultContainerClass, $containerClass, $placementClass, $hasConditions,
155 + ])));
156 +
157 + return $this;
158 + }
124 159 }