app = wpFluentForm(); } /** * Build unique ID concatenating form id and name attribute * * @param array $data $form * * @return string for id value */ protected function makeElementId($data, $form) { if (isset($data['attributes']['name'])) { $formInstance = \FluentForm\App\Helpers\Helper::$formInstance; if (!empty($data['attributes']['id'])) { return $data['attributes']['id']; } $elementName = $data['attributes']['name']; $elementName = str_replace(['[', ']', ' '], '_', $elementName); $suffix = esc_attr($form->id); if ($formInstance > 1) { $suffix = $suffix . '_' . $formInstance; } $suffix .= '_' . $elementName; return 'ff_' . esc_attr($suffix); } } /** * Build attributes for any html element * * @param array $attributes * * @return string [Compiled key='value' attributes] */ protected function buildAttributes($attributes, $form = null) { $atts = ''; foreach ($attributes as $key => $value) { if ($value || 0 === $value || '0' === $value) { $value = htmlspecialchars($value); $atts .= esc_attr($key) . '="' . $value . '" '; } } return $atts; } /** * Extract value attribute from attribute list * * @param array &$element * * @return string */ protected function extractValueFromAttributes(&$element) { $value = ''; if (isset($element['attributes']['value'])) { $value = $element['attributes']['value']; unset($element['attributes']['value']); } return $value; } protected function extractDynamicValues($data, $form) { $defaultValues = []; if ($dynamicDefaultValue = ArrayHelper::get($data, 'settings.dynamic_default_value')) { $parseValue = $this->parseEditorSmartCode($dynamicDefaultValue, $form); if (is_array($parseValue)) { $defaultValues = $parseValue; } elseif (!empty($parseValue) && is_string($parseValue)) { $defaultValues = explode(',', $parseValue); $defaultValues = array_map('trim', $defaultValues); } } return $defaultValues; } /** * Determine if the given element has conditions bound * * @param array $element [Html element being compiled] * * @return bool */ protected function hasConditions($element) { $conditionals = ArrayHelper::get($element, 'settings.conditional_logics'); if (isset($conditionals['status']) && $conditionals['status']) { if (isset($conditionals['type']) && $conditionals['type'] === 'group') { $groups = ArrayHelper::get($conditionals, 'condition_groups'); if (!is_array($groups)) { return false; } $groups = array_filter($groups, function ($group) { $rules = ArrayHelper::get($group, 'rules', []); return !empty(array_filter($rules, fn($rule) => !empty($rule['field']) && !empty($rule['operator']))); }); return !!$groups; } return !!array_filter($conditionals['conditions'], function ($item) { return $item['field'] && $item['operator']; }); } return false; } /** * Generate a unique id for an element * * @param string $str [preix] * * @return string [Unique id] */ protected function getUniqueId($str) { return $str . '_' . md5(uniqid(wp_rand(), true)); } /** * Get a default class for each form element wrapper * @return string */ protected function getDefaultContainerClass() { return 'ff-el-group '; } /** * Get required class for form element wrapper * * @param array $rules [Validation rules] * * @return mixed */ protected function getRequiredClass($rules) { if (isset($rules['required'])) { return $rules['required']['value'] ? 'ff-el-is-required ' : ''; } } /** * Get asterisk placement for the required form elements * @return string */ protected function getAsteriskPlacement($form) { // for older version compatibility $asteriskPlacement = 'asterisk-right'; if (isset($form->settings['layout']['asteriskPlacement'])) { $asteriskPlacement = $form->settings['layout']['asteriskPlacement']; } return $asteriskPlacement . ' '; } /** * Generate a label for any element * * @param array $data * * @return string [label Html element] */ protected function buildElementLabel($data, $form) { $helpMessage = ''; $helpMessagePlacement = ArrayHelper::get($form->settings, 'layout.helpMessagePlacement', 'with_label'); if ('with_label' == $helpMessagePlacement) { $helpMessage = $this->getLabelHelpMessage($data); } $id = isset($data['attributes']['id']) ? $data['attributes']['id'] : ''; $label = isset($data['settings']['label']) ? $data['settings']['label'] : ''; $requiredClass = $this->getRequiredClass(ArrayHelper::get($data, 'settings.validation_rules', [])); $classes = trim('ff-el-input--label ' . $requiredClass . $this->getAsteriskPlacement($form)); return "
' . $helpMessage . '
'; } /** * Generate html/markup for any element * * @param string $elMarkup [Predifined partial markup] * @param array $data * @param stdClass $form [Form object] * * @return string [Compiled markup] */ protected function buildElementMarkup($elMarkup, $data, $form) { $hasConditions = $this->hasConditions($data) ? 'has-conditions ' : ''; $labelPlacement = ArrayHelper::get($data, 'settings.label_placement'); $labelPlacementClass = $labelPlacement ? 'ff-el-form-' . $labelPlacement . ' ' : ''; $validationRules = ArrayHelper::get($data, 'settings.validation_rules'); $requiredClass = $this->getRequiredClass($validationRules); $labelClass = trim( 'ff-el-input--label ' . $requiredClass . $this->getAsteriskPlacement($form) ); $formGroupClass = trim( $this->getDefaultContainerClass() . $labelPlacementClass . $hasConditions . ArrayHelper::get($data, 'settings.container_class') ); $labelHelpText = $inputHelpText = ''; $labelPlacement = ArrayHelper::get($form->settings, 'layout.helpMessagePlacement', 'with_label'); if ('with_label' == $labelPlacement) { $labelHelpText = $this->getLabelHelpMessage($data); } elseif ('on_focus' == $labelPlacement) { $inputHelpText = $this->getInputHelpMessage($data, 'ff-hidden'); } elseif ('after_label' == $labelPlacement) { $inputHelpText = $this->getInputHelpMessage($data, 'ff_ahm'); } else { $inputHelpText = $this->getInputHelpMessage($data); } $forStr = ''; $LabelId = ''; if (isset($data['attributes']['id'])) { $forStr = "for='" . esc_attr($data['attributes']['id']) . "'"; $LabelId = "id='" . esc_attr('label_' . $data['attributes']['id']) . "'"; } $labelMarkup = ''; if (!empty($data['settings']['label'])) { $label = ArrayHelper::get($data, 'settings.label'); $ariaLabel = $label; $hasShortCodeIndex = strpos($label, '{dynamic.'); //Handle name field duplicate label accessibility $isNameField = strpos(ArrayHelper::get($data, 'attributes.name', ''), 'name') !== false; if ($isNameField) { $ariaLabel = ''; } elseif ($hasShortCodeIndex !== false) { $ariaLabel = trim(substr($label, 0, $hasShortCodeIndex)); } else { $ariaLabel = $label; } $labelMarkup = sprintf( '
%6$s
', esc_attr($labelClass), $forStr, $LabelId, $ariaLabel != '' ? 'aria-label="' . esc_attr($this->removeShortcode($label)) . '"' : '', fluentform_sanitize_html($label), fluentform_sanitize_html($labelHelpText) ); } $inputHelpText = fluentform_sanitize_html($inputHelpText); if ('after_label' == $labelPlacement) { $elMarkup = $inputHelpText . $elMarkup; $inputHelpText = ''; } return sprintf( "
%s
%s%s
", esc_attr($formGroupClass), $labelMarkup, $elMarkup, $inputHelpText ); } /** * Generate a help message for any element beside label * * @param array $data * * @return string [Html] */ protected function getLabelHelpMessage($data) { if (isset($data['settings']['help_message']) && '' != $data['settings']['help_message']) { $text = htmlspecialchars($data['settings']['help_message']); $icon = ''; return sprintf('
%s
', $text, $icon); } } /** * Generate a help message for any element beside form element * * @param array $data * * @return string [Html] */ protected function getInputHelpMessage($data, $hideClass = '') { $class = trim('ff-el-help-message ' . $hideClass); if (isset($data['settings']['help_message']) && !empty($data['settings']['help_message'])) { return "
" . fluentform_sanitize_html($data['settings']['help_message']) . '
'; } return false; } protected function parseEditorSmartCode($text, $form) { return (new Component($this->app))->replaceEditorSmartCodes($text, $form); } protected function printContent($hook, $html, $data, $form) { echo apply_filters($hook, $html, $data, $form); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound,WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic hook name for component content filter. $html is escaped before being passed in. } /** * A helper method for remove shortcode from aria label * * @param string $label * * @return string $label */ protected function removeShortcode($label) { // Find all occurrences of text enclosed in curly braces. preg_match_all('/{(.*?)}/', $label, $matches); // If there are matches, remove them from the label. if ($matches[0]) { $label = trim(str_replace($matches[0], '', $label)); } return wp_strip_all_tags($label); } }