renderField($field); } if ($print) { echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } return $html; } public function renderField($field) { $type = Arr::get($field, 'type'); if ($type == 'container') { return $this->renderContainer($field); } if ($type == 'raw_html') { return (string) Arr::get($field, 'html'); } if ($type == 'hidden') { $atts = $this->buildAttributes($field['atts']); return ''; } $inputHtml = ''; if ($type == 'input') { $inputHtml = $this->renderInput($field); } else if ($type == 'select') { $inputHtml = $this->renderSelect($field); } else if ($type == 'select-multi') { $inputHtml = $this->renderMultiSelect($field); } else if ($type == 'radio') { $inputHtml = $this->renderRadio($field); } else if ($type == 'checkboxes') { $inputHtml = $this->renderCheckboxes($field); } else if ($type == 'date') { $inputHtml = $this->renderDate($field); } else if ($type == 'textarea') { $inputHtml = $this->renderTextarea($field); } else if ($type == 'number') { $inputHtml = $this->renderInput($field); } else if ($type == 'custom_date') { $inputHtml = $this->renderDatePicker($field); } else if ($type == 'custom_date_time') { $inputHtml = $this->renderDateTimePicker($field); } else if ($type == 'date_dropdowns') { $inputHtml = $this->renderDateDropdowns($field); } return $this->renderLabel($field, $inputHtml); } public function renderSelect($field) { $atts = $this->buildAttributes([ 'id' => Arr::get($field, 'id'), 'name' => Arr::get($field, 'name'), ]); $html = ''; return $html; } public function renderRadio($field) { $name = $field['name']; $html = '
'; foreach ($field['options'] as $key => $label) { $attributes = [ 'type' => 'radio', 'name' => $name, 'value' => $key ]; if ($key == $field['value']) { $attributes['checked'] = true; } $html .= ''; } $html .= '
'; return $html; } public function renderCheckboxes($field) { $name = $field['name']; $options = $field['options']; $selectedValues = (array) $field['value']; $html = '
'; $isAssoc = array_keys($options) !== range(0, count($options) - 1); foreach ($options as $optionKey => $list_option) { $optionValue = $isAssoc ? $optionKey : $list_option; $attrbutes = [ 'type' => 'checkbox', 'name' => esc_attr($name) . '[]', 'value' => esc_attr($optionValue) ]; if (in_array($optionValue, $selectedValues)) { $attrbutes['checked'] = true; } $html .= ''; } $html .= '
'; return $html; } public function renderContainer($field) { $innerFields = Arr::get($field, 'fields', []); if (!$innerFields) { return ''; } $html = '
'; $html .= $this->renderFields($innerFields); $html .= '
'; return $html; } public function renderLabel($field, $innerHtml = '') { $containerClass = 'fc_field fc_field_' . $field['name'] . ' fc_field_' . $field['type']; if ($givenClass = Arr::get($field, 'container_class')) { $containerClass .= ' ' . $givenClass; } $html = '
'; if ($label = Arr::get($field, 'label')) { if ($id = Arr::get($field, 'id')) { // date_dropdowns: label must target first visible select, not the hidden input $forId = (Arr::get($field, 'type') === 'date_dropdowns') ? $id . '_day' : $id; $labelAtts = $this->buildAttributes([ 'for' => $forId ]); } else { $labelAtts = ''; } $required = ''; if (Arr::get($field, 'required')) { $required = ' *'; } $html .= ''; } return $html . $innerHtml . '
'; } public function renderInput($field) { $atts = Arr::get($field, 'atts', []); $atts['name'] = $field['name']; if (!empty($field['required'])) { $atts['required'] = true; } if (!empty($field['id'])) { $atts['id'] = $field['id']; } if (empty($atts['class'])) { $atts['class'] = 'fc_input_control'; } else { $atts['class'] .= ' fc_input_control'; } $atts['value'] = $field['value']; return 'buildAttributes($atts) . '/>'; } public function renderDate($field) { // Legacy combodate field. combodate requires moment.js (not bundled on // public pages), so custom_date (flatpickr) is preferred for new fields. // Kept for backward compatibility. wp_enqueue_script('combodate', FLUENTCRM_PLUGIN_URL . 'assets/libs/combodate/combodate.js', ['jquery'], '1.0.7', true); $this->ensureFieldInitializer(); // Tag the input so the externalized initializer (form-fields.js) can find // it, instead of emitting an inline