', array_values($columnLabels)); $elementHelpMessage = $this->getElementHelpMessage($data, $form); $elementLabel = $this->setClasses($data)->buildElementLabel($data, $form); $elMarkup = "'; $tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex(); foreach ($this->makeTabularData($data) as $index => $row) { $elMarkup .= ''; $elMarkup .= "'; $isRowChecked = in_array($row['name'], $checked) ? 'checked' : ''; foreach ($row['columns'] as $column) { $name = $data['attributes']['name'] . '[' . $row['name'] . ']'; $name = 'checkbox' == $fieldType ? ($name . '[]') : $name; $isColChecked = in_array($column['name'], $checked) ? 'checked' : ''; $isChecked = $isRowChecked ? $isRowChecked : $isColChecked; $atts = [ 'name' => $name, 'type' => $fieldType, 'value' => $column['name'], ]; if ($tabIndex) { $atts['tabindex'] = $tabIndex; } $attributes = $this->buildAttributes($atts, $form); $ariaRequired = 'false'; if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) { $ariaRequired = 'true'; } // SECURITY (FINDING-12): esc_attr the row/column labels before interpolating them // into the double-quoted aria-label; save-time sanitizers do not encode quotes. $input = '"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $attributes is escaped before being passed in. $elMarkup .= ""; } $elMarkup .= ''; } $elMarkup .= '
" . fluentform_sanitize_html($columnHeaders) . '
" . fluentform_sanitize_html($row['label']) . '{$input}
'; $elMarkup = "
{$elMarkup}" . fluentform_sanitize_html($elementHelpMessage) . '
'; // SECURITY (FINDING-12): esc_attr the attribute values interpolated into the single-quoted // data-type / data-name / class attributes; sanitize_text_field at save does not encode quotes. $html = sprintf( "
%s", esc_attr($data['attributes']['data-type']), esc_attr($data['attributes']['name']), esc_attr($data['attributes']['class']), $elementLabel ) . $elMarkup . '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $elementLabel is escaped before being passed in. $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); $this->printContent('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } public function makeTabularData($data) { $table = []; $rows = $data['settings']['grid_rows']; $columns = $data['settings']['grid_columns']; foreach ($rows as $rowKey => $rowValue) { $rowKey = trim(sanitize_text_field($rowKey)); $table[$rowKey] = [ 'name' => $rowKey, 'label' => $rowValue, 'columns' => [], ]; foreach ($columns as $columnKey => $columnValue) { $columnKey = trim(sanitize_text_field($columnKey)); $table[$rowKey]['columns'][] = [ 'name' => $columnKey, 'label' => $columnValue, ]; } } return $table; } protected function getElementHelpMessage($data, $form) { $elementHelpMessage = ''; $helpMessagePlacement = ArrayHelper::get($form->settings, 'layout.helpMessagePlacement', 'with_label'); if ('under_input' == $helpMessagePlacement) { $elementHelpMessage = $this->getInputHelpMessage($data); } return $elementHelpMessage; } protected function setClasses(&$data) { if (! isset($data['attributes']['class'])) { $data['attributes']['class'] = ''; } $placement = $data['settings']['label_placement']; $placementClass = $placement ? 'ff-el-form-' . $placement : ''; $hasConditions = $this->hasConditions($data) ? ' has-conditions' : ''; $defaultContainerClass = $this->getDefaultContainerClass(); $containerClass = $data['settings']['container_class']; $data['attributes']['class'] .= trim(implode(' ', array_map('trim', [ $defaultContainerClass, $containerClass, $placementClass, $hasConditions, ]))); return $this; } }