Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
forbidals
/
wp-content
/
plugins
/
formidable
/
classes
/
models
:
FrmFieldFormHtml.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } /** * @since 3.0 */ class FrmFieldFormHtml { /** * @var string */ private $html; /** * @var string */ private $html_id; /** * @var FrmFieldType */ private $field_obj; /** * @var int|string */ private $field_id; /** * @var array|object */ private $form = array(); /** * @var array */ private $pass_args = array(); /** * @since 3.0 * * @param array $atts */ public function __construct( $atts ) { $this->_set( 'field_obj', $atts ); $this->set_field_id( $atts ); $this->_set( 'form', $atts ); $this->_set( 'html_id', $atts ); $this->set_html( $atts ); $this->set_pass_args( $atts ); } /** * @since 3.0 * * @param string $param * @param array $atts * * @return void */ private function _set( $param, $atts ) { if ( isset( $atts[ $param ] ) ) { $this->{$param} = $atts[ $param ]; } } /** * @since 3.0 * * @param array $atts * * @return void */ private function set_html( $atts ) { $this->set_from_field( $atts, array( 'param' => 'html', 'default' => 'custom_html', ) ); } /** * @since 3.0 * * @param array $atts * * @return void */ private function set_field_id( $atts ) { $this->set_from_field( $atts, array( 'param' => 'field_id', 'default' => 'id', ) ); } /** * @since 3.0 * * @param array $atts * * @return void */ private function set_pass_args( $atts ) { $this->pass_args = $atts; $exclude = array( 'field_obj', 'html' ); foreach ( $exclude as $ex ) { if ( isset( $atts[ $ex ] ) ) { unset( $this->pass_args[ $ex ] ); } } } /** * @since 3.0 * * @param array $atts * @param array $set * * @return void */ private function set_from_field( $atts, $set ) { if ( isset( $atts[ $set['param'] ] ) ) { $this->{$set['param']} = $atts[ $set['param'] ]; } else { $this->{$set['param']} = $this->field_obj->get_field_column( $set['default'] ); } } /** * @return string */ public function get_html() { $this->replace_shortcodes_before_input(); $this->replace_shortcodes_with_atts(); $this->replace_shortcodes_after_input(); return $this->html; } /** * @since 3.0 * * @return void */ private function replace_shortcodes_before_input() { $this->html = apply_filters( 'frm_before_replace_shortcodes', $this->html, $this->field_obj->get_field(), $this->pass_args['errors'], $this->form ); $this->replace_field_values(); $this->replace_required_label_shortcode(); $this->replace_required_class(); $this->maybe_replace_description_shortcode( false ); $this->replace_error_shortcode(); $this->add_class_to_label(); $this->add_field_div_classes(); $this->replace_entry_key(); $this->replace_form_shortcodes(); $this->process_wp_shortcodes(); $this->maybe_replace_description_shortcode( true ); $this->add_multiple_input_attributes(); } /** * @since 3.0 * * @return void */ private function replace_field_values() { // Replace [id]. $this->html = str_replace( '[id]', $this->field_id, $this->html ); // set the label for $this->html = str_replace( 'field_[key]', $this->html_id, $this->html ); // Replace [key]. $this->html = str_replace( '[key]', $this->field_obj->get_field_column( 'field_key' ), $this->html ); // Replace [field_name]. $this->html = str_replace( '[field_name]', FrmAppHelper::maybe_kses( $this->field_obj->get_field_column( 'name' ) ), $this->html ); } /** * @since 3.0 * * @return void */ private function replace_required_label_shortcode() { $required = FrmField::is_required( $this->field_obj->get_field() ) ? $this->field_obj->get_field_column( 'required_indicator' ) : ''; FrmShortcodeHelper::remove_inline_conditions( ! empty( $required ), 'required_label', $required, $this->html ); } /** * If this is an HTML field, the values are included in the description. * In this case, we don't want to run the wp shortcodes with the description included. * * @since 3.0 * * @param bool $wp_processed * * @return void */ private function maybe_replace_description_shortcode( $wp_processed = false ) { $is_html = 'html' === $this->field_obj->get_field_column( 'type' ); $should_replace = ( $is_html && $wp_processed ) || ( ! $is_html && ! $wp_processed ); if ( $should_replace ) { $this->replace_description_shortcode(); } } /** * @since 3.0 * * @return void */ private function replace_description_shortcode() { $this->maybe_add_description_id(); $description = FrmAppHelper::maybe_kses( $this->field_obj->get_field_column( 'description' ) ); // phpcs:ignore Universal.Operators.StrictComparisons FrmShortcodeHelper::remove_inline_conditions( ( $description && $description != '' ), 'description', $description, $this->html ); } /** * Add an ID to the description for aria-describedby. * This ID was added to the HTML in v3.0. * * @since 3.0 * * @return void */ private function maybe_add_description_id() { $description = $this->field_obj->get_field_column( 'description' ); // phpcs:ignore Universal.Operators.StrictComparisons if ( $description != '' ) { $this->add_element_id( 'description', 'desc' ); } } /** * Insert an ID if it doesn't exist. * * @since 3.06.02 * * @param string $param * @param string $id * * @return void */ private function add_element_id( $param, $id ) { preg_match_all( '/(\[if\s+' . $param . '\])(.*?)(\[\/if\s+' . $param . '\])/mis', $this->html, $inner_html ); if ( ! isset( $inner_html[2] ) ) { return; } if ( ! is_string( $inner_html[2] ) && count( $inner_html[2] ) === 1 ) { $inner_html[2] = $inner_html[2][0]; } if ( is_string( $inner_html[2] ) ) { $has_id = str_contains( $inner_html[2], ' id=' ); if ( ! $has_id ) { $id = 'frm_' . $id . '_' . $this->html_id; $this->html = str_replace( 'class="frm_' . $param, 'id="' . esc_attr( $id ) . '" class="frm_' . esc_attr( $param ), $this->html ); } } } /** * @since 3.0 * * @return void */ private function replace_error_shortcode() { $this->maybe_add_error_id(); $error = $this->pass_args['errors'][ 'field' . $this->field_id ] ?? false; if ( $error && ! str_contains( $this->html, 'role="alert"' ) && FrmAppHelper::should_include_alert_role_on_field_errors() ) { $error_body = self::get_error_body( $this->html ); if ( is_string( $error_body ) && ! str_contains( $error_body, 'role=' ) ) { $new_error_body = preg_replace( '/class="frm_error/', 'role="alert" class="frm_error', $error_body, 1 ); $this->html = str_replace( '[if error]' . $error_body . '[/if error]', '[if error]' . $new_error_body . '[/if error]', $this->html ); } } FrmShortcodeHelper::remove_inline_conditions( ! empty( $error ), 'error', $error, $this->html ); } /** * Pull the HTML between [if error] and [/if error] shortcodes. * * @param string $html * * @return false|string */ private static function get_error_body( $html ) { $start = strpos( $html, '[if error]' ); if ( false === $start ) { return false; } $end = strpos( $html, '[/if error]', $start ); if ( false === $end ) { return false; } return substr( $html, $start + 10, $end - $start - 10 ); } /** * Add an ID to the error message for aria-describedby. * This ID was added to the HTML in v3.06.02. * * @since 3.06.02 * * @return void */ private function maybe_add_error_id() { if ( ! isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ) { return; } $this->add_element_id( 'error', 'error' ); } /** * Replace [required_class] * * @since 3.0 * * @return void */ private function replace_required_class() { $required_class = FrmField::is_required( $this->field_obj->get_field() ) ? ' frm_required_field' : ''; $this->html = str_replace( '[required_class]', $required_class, $this->html ); } /** * @since 3.0 * * @return void */ private function replace_form_shortcodes() { if ( ! empty( $this->form ) ) { $form = (array) $this->form; // Replace [form_key]. $this->html = str_replace( '[form_key]', $form['form_key'], $this->html ); // Replace [form_name]. $this->html = str_replace( '[form_name]', $form['name'], $this->html ); } } /** * @since 3.0 * * @return void */ public function replace_shortcodes_after_input() { $this->html .= "\n"; // Stop html filtering on confirmation field to prevent loop if ( $this->field_obj->get_field_column( 'conf_field' ) !== 'stop' ) { $this->filter_for_more_shortcodes(); } } /** * @since 3.0 * * @return void */ private function filter_for_more_shortcodes() { $atts = $this->pass_args; // If field is not in repeating section. if ( empty( $atts['section_id'] ) ) { $atts = array( 'errors' => $this->pass_args['errors'], 'form' => $this->form, ); } $this->html = apply_filters( 'frm_replace_shortcodes', $this->html, $this->field_obj->get_field(), $atts ); } /** * Remove [collapse_this] if it's still included after all processing * * @since 3.0 * * @param string $html * * @return void */ public function remove_collapse_shortcode( &$html ) { if ( str_contains( $html, '[collapse_this]' ) ) { $html = str_replace( '[collapse_this]', '', $html ); } } /** * @since 3.0 * * @return void */ private function replace_shortcodes_with_atts() { preg_match_all( "/\[(input|deletelink)\b(.*?)(?:(\/))?\]/s", $this->html, $shortcodes, PREG_PATTERN_ORDER ); foreach ( $shortcodes[0] as $short_key => $tag ) { $shortcode_atts = FrmShortcodeHelper::get_shortcode_attribute_array( $shortcodes[2][ $short_key ] ); $tag = FrmShortcodeHelper::get_shortcode_tag( $shortcodes, $short_key ); $replace_with = ''; if ( $tag === 'deletelink' && FrmAppHelper::pro_is_installed() ) { $replace_with = FrmProEntriesController::entry_delete_link( $shortcode_atts ); } elseif ( $tag === 'input' ) { $replace_with = $this->replace_input_shortcode( $shortcode_atts ); } $this->html = str_replace( $shortcodes[0][ $short_key ], $replace_with, $this->html ); } } /** * @param array $shortcode_atts * * @return string */ private function replace_input_shortcode( $shortcode_atts ) { $shortcode_atts = $this->prepare_input_shortcode_atts( $shortcode_atts ); return $this->field_obj->include_front_field_input( $this->pass_args, $shortcode_atts ); } /** * @param array $shortcode_atts * * @return array */ private function prepare_input_shortcode_atts( $shortcode_atts ) { if ( isset( $shortcode_atts['opt'] ) ) { --$shortcode_atts['opt']; } $field_class = $shortcode_atts['class'] ?? ''; $this->field_obj->set_field_column( 'input_class', $field_class ); if ( isset( $shortcode_atts['class'] ) ) { unset( $shortcode_atts['class'] ); } $this->field_obj->set_aria_invalid_error( $shortcode_atts, $this->pass_args ); $this->field_obj->set_field_column( 'shortcodes', $shortcode_atts ); return $shortcode_atts; } /** * Add the label position class into the HTML * If the label position is inside, add a class to show the label if the field has a value. * * @since 3.0 * * @return void */ private function add_class_to_label() { $label_class = $this->field_obj->get_label_class(); $this->html = str_replace( '[label_position]', $label_class, $this->html ); } /** * Replace [entry_key] * * @since 3.0 * * @return void */ private function replace_entry_key() { $entry_key = FrmAppHelper::simple_get( 'entry', 'sanitize_title' ); $this->html = str_replace( '[entry_key]', $entry_key, $this->html ); } /** * Add classes to a field div * * @since 3.0 * * @return void */ private function add_field_div_classes() { $classes = $this->get_field_div_classes(); if ( in_array( $this->field_obj->get_field_column( 'type' ), array( 'html', 'summary' ), true ) && ! str_contains( $this->html, '[error_class]' ) ) { // there is no error_class shortcode for HTML fields $this->html = str_replace( 'class="frm_form_field', 'class="frm_form_field ' . esc_attr( $classes ), $this->html ); return; } $this->html = str_replace( '[error_class]', esc_attr( $classes ), $this->html ); } /** * Get the classes for a field div * * @since 3.0 * * @return string $classes */ private function get_field_div_classes() { // Add error class $classes = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? ' frm_blank_field' : ''; // Add label position class $settings = $this->field_obj->display_field_settings(); if ( ! empty( $settings['label_position'] ) ) { $label_position = $this->field_obj->get_field_column( 'label' ); $classes .= ' frm_' . $label_position . '_container'; // Add class if field has value, to be used for floating label styling. if ( 'inside' === $label_position && $this->field_obj->get_field_column( 'value' ) ) { $classes .= ' frm_label_float_top'; } } // Add CSS layout classes $extra_classes = $this->field_obj->get_field_column( 'classes' ); if ( $extra_classes ) { if ( ! str_contains( $this->html, 'frm_form_field ' ) ) { $classes .= ' frm_form_field'; } $classes .= ' ' . $extra_classes; } $classes .= $this->field_obj->get_container_class(); // Get additional classes $classes = apply_filters( 'frm_field_div_classes', $classes, $this->field_obj->get_field(), array( 'field_id' => $this->field_id ) ); // Remove unexpected characters from class. return implode( ' ', array_map( 'FrmFormsHelper::sanitize_layout_class', explode( ' ', $classes ) ) ); } /** * This filters shortcodes in the field HTML * * @since 3.0 * * @return void */ private function process_wp_shortcodes() { if ( apply_filters( 'frm_do_html_shortcodes', true ) ) { $this->html = do_shortcode( $this->html ); } } /** * Adds multiple input attributes. * * @since 6.4.1 * * @return void */ private function add_multiple_input_attributes() { $field_type = $this->field_obj->get_field_column( 'type' ); // Check if the field type is one of the following. if ( ! in_array( $field_type, array( 'radio', 'checkbox', 'data', 'product', 'scale' ), true ) ) { return; } $field = (array) $this->field_obj->get_field(); $attributes = array(); // Check if the field type is 'data' or 'product'. if ( in_array( $field_type, array( 'data', 'product' ), true ) ) { $data_type = FrmField::get_option( $field, 'data_type' ); $is_radio = 'radio' === $data_type; } else { $is_radio = 'radio' === $field_type || 'scale' === $field_type; } // Add 'role' attribute to the field. $attributes['role'] = $is_radio ? 'radiogroup' : 'group'; // Add 'aria-required' attribute to the field if required. if ( $is_radio && '1' === $field['required'] ) { $attributes['aria-required'] = 'true'; } // Add 'aria-invalid' attribute to the group if there are errors. if ( isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ) { $attributes['aria-invalid'] = 'true'; } // Concatenate attributes into a string, and replace the role="group" in the HTML with the attributes string. $html_attributes = FrmAppHelper::array_to_html_params( $attributes ); $this->html = str_replace( ' role="group"', $html_attributes, $this->html ); } }