index of
/
home
/
thefkyzp
/
public_html
/
wp-content
/
plugins
/
forminator
/
library
/
abstracts
/
File: /home/thefkyzp/public_html/wp-content/plugins/forminator/library/abstracts/abstract-class-field.php
<?php /** * The Forminator Field. * * @package Forminator */ if ( ! defined( 'ABSPATH' ) ) { die(); } /** * Class Forminator_Field * * @since 1.0 * Abstract class for fields * * @since 1.0.5 * @property array form_settings * @property array field * @property mixed|void autofill_settings * @property mixed|void advanced_settings * @property mixed|void markup */ abstract class Forminator_Field { /** * The field * * @var array */ public $field = array(); /** * The Form settings * * @var array */ public $form_settings = array(); /** * The name * * @var string */ public $name = ''; /** * The slug * * @var string */ public $slug = ''; /** * The category * * @var string */ public $category = ''; /** * Type * * @var string */ public $type = ''; /** * Options * * @var array */ public $options = array(); /** * The settings * * @var array */ public $settings = array(); /** * The autofill settings * * @var array */ public $autofill_settings = array(); /** * The defaults * * @var array */ public $defaults = array(); /** * The hide advanced * * @var bool */ public $hide_advanced = false; /** * The position * * @var int */ public $position = 99; /** * Is inout * * @var bool */ public $is_input = false; /** * Has counter * * @var bool */ public $has_counter = false; /** * Check if the input data for field is valid * * @var bool */ public $is_valid = true; /** * Validation message * * @var array */ public $validation_message = array(); /** * Activated Autofill Providers for this field based @see autofill_settings * * @since 1.0.5 * @var Forminator_Autofill_Provider_Abstract[] */ protected $activated_autofill_providers = array(); /** * Flag property value not exist * * Support backward compat, for non existent property from older forminator version * * @since 1.6 */ const FIELD_PROPERTY_VALUE_NOT_EXIST = 'FORMINATOR_PROPERTY_VALUE_NOT_EXIST'; /** * The icon * * @var string */ public $icon = 'sui-icon-element-radio'; /** * Is calculable * * @var bool */ public $is_calculable = false; const FIELD_NOT_CALCULABLE = 'FIELD_NOT_CALCULABLE'; /** * The Constructor */ public function __construct() { add_action( 'admin_init', array( &$this, 'admin_init_field' ) ); } /** * Admin init field * * @since 1.7 */ public function admin_init_field() { $this->settings = apply_filters( "forminator_field_{$this->slug}_general_settings", array() ); $this->autofill_settings = apply_filters( "forminator_field_{$this->slug}_autofill_settings", $this->autofill_settings() ); $this->defaults = apply_filters( "forminator_field_{$this->slug}_defaults", $this->defaults() ); $this->position = apply_filters( "forminator_field_{$this->slug}_position", $this->position ); $this->is_calculable = apply_filters( "forminator_field_{$this->slug}_is_calculable", $this->is_calculable ); } /** * Return field name * * @since 1.0 * @return string */ public function get_name() { return $this->name; } /** * Return field slug * * @since 1.0 * @return string */ public function get_slug() { return $this->slug; } /** * Get Category * * @return string */ public function get_category() { return $this->category; } /** * Return field settings * * @since 1.0 * @return array */ public function get_settings() { return $this->settings; } /** * Create decimals pattern from decimals number * * @since 1.7 * @param integer $decimals Decimals. * @return mixed */ protected static function create_step_string( $decimals = 2 ) { $step = 1; if ( ! empty( $decimals ) ) { for ( $i = 1; $i < $decimals; $i++ ) { $step = '0' . $step; } $step = '0.' . $step; } return $step; } /** * Return field property * * @since 1.0 * @since 1.6 add $data_type, to cast it * * @param string $property Property. * @param array $field Field. * @param string $fallback Fallback. * @param string $data_type data type to return. * * @return mixed */ public static function get_property( $property, $field, $fallback = '', $data_type = null ) { $property_value = $fallback; if ( isset( $field[ $property ] ) ) { $property_value = $field[ $property ]; } if ( ! empty( $data_type ) ) { $property_value = forminator_var_type_cast( $property_value, $data_type ); } if ( 'required_message' === $property ) { $property_value = wp_kses_post( $property_value ); } return $property_value; } /** * Get options for radio and selectbox fields * * @param array $field Field settings. * @return array */ public static function get_options( $field ) { $options = self::get_property( 'options', $field, array() ); if ( ! empty( $field['options_order'] ) && 'random' === $field['options_order'] ) { shuffle( $options ); } return $options; } /** * Markup * * @since 1.0 * * @param mixed $field Field. * @param Forminator_Render_Form $views_obj Forminator_Render_Form object. * * @return mixed */ public function markup( // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed // @noinspection PhpUnusedParameterInspection. $field, $views_obj ) { return ''; } /** * Defaults * * @since 1.0 * @return array */ public function defaults() { return array(); } /** * Return description * * @since 1.0 * * @param string $description Description. * @param string $get_id Id. * * @return string */ public static function get_description( $description, $get_id = '' ) { $html = ''; if ( ! empty( $description ) ) { $html .= sprintf( '<span id="%s" class="forminator-description">%s</span>', esc_attr( $get_id . '-description' ), self::esc_description( $description, $get_id ) ); } return apply_filters( 'forminator_field_description', $html, $description, $get_id ); } /** * Escape description * * @param string $description Description. * @param string $field_id Field ID. * * @return string */ public static function esc_description( $description, $field_id ) { $allowed_html = apply_filters( 'forminator_field_description_allowed_html', array( 'a' => array( 'href' => true, 'title' => true, 'target' => true, 'rel' => true, ), 'span' => array( 'class' => true, ), 'br' => array(), 'em' => array(), 'strong' => array(), ), $description, $field_id ); return wp_kses( $description, $allowed_html ); } /** * Return new input field * * @since 1.0 * * @param array $attr Attribute. * * @param string $label Label. * @param string $description Description. * @param bool $required Required. * @param string $design Design. * @param array $wrapper_input Wrapper Input. * * @return mixed */ public static function create_input( $attr = array(), $label = '', $description = '', $required = false, $design = '', $wrapper_input = array() ) { $html = ''; // Override value by the posted value. $value = isset( $attr['value'] ) ? $attr['value'] : false; if ( isset( $attr['name'] ) ) { $value = self::get_post_data( $attr['name'], $value ); } $attr['value'] = $value; if ( ! empty( $description ) ) { $attr['aria-describedby'] = $attr['id'] . '-description'; } $markup = self::implode_attr( $attr ); // Get field id. $get_id = $attr['id']; $html .= self::get_field_label( $label, $get_id, $required ); if ( isset( $wrapper_input[0] ) ) { $html .= $wrapper_input[0]; } if ( isset( $wrapper_input[2] ) && ! empty( $wrapper_input[2] ) ) { $html .= sprintf( '<label for="%s"><span class="forminator-icon-%s" aria-hidden="true"></span></label>', $get_id, $wrapper_input[2] ); } if ( isset( $wrapper_input[3] ) && ! empty( $wrapper_input[3] ) ) { $html .= sprintf( '<span class="forminator-prefix">%s</span>', $wrapper_input[3] ); } $html .= sprintf( '<input %s />', $markup ); if ( isset( $wrapper_input[1] ) ) { $html .= $wrapper_input[1]; } if ( ! empty( $description ) ) { $html .= self::get_description( $description, $get_id ); } return apply_filters( 'forminator_field_create_input', $html, $attr, $label, $description ); } /** * Return new textarea field * * @since 1.0 * * @param array $attr Field Attribute. * @param string $label Field Label. * @param string $description Field Description. * @param bool $required Required. * @param string $design Design. * * @return mixed */ public static function create_textarea( $attr = array(), $label = '', $description = '', $required = false, $design = '' ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed $html = ''; $content = isset( $attr['content'] ) ? $attr['content'] : ''; if ( isset( $attr['name'] ) ) { $content = self::get_post_data( $attr['name'], $content ); } unset( $attr['content'] ); if ( ! empty( $description ) ) { $attr['aria-describedby'] = $attr['id'] . '-description'; } $markup = self::implode_attr( $attr ); $html .= self::get_field_label( $label, $attr['id'], $required ); $html .= sprintf( '<textarea %s >%s</textarea>', $markup, wp_kses_post( $content ) ); if ( ! empty( $description ) ) { $html .= self::get_description( $description, $attr['id'] ); } return apply_filters( 'forminator_field_create_textarea', $html, $attr, $label, $description ); } /** * Return wp_editor_field * * @since 1.0.2 * * @param array $attr Field Attribute. * @param string $label Field Label. * @param string $description Field Description. * @param bool $required Required. * @param string $default_height Height. * @param integer $limit Limit. * * @return mixed */ public static function create_wp_editor( $attr = array(), $label = '', $description = '', $required = false, $default_height = '140', $limit = 0 ) { $html = ''; $content = isset( $attr['content'] ) ? $attr['content'] : ''; if ( isset( $attr['name'] ) ) { $content = self::get_post_data( $attr['name'], $content ); } unset( $attr['content'] ); $editor_id = 'forminator-wp-editor-' . ( isset( $attr['id'] ) ? $attr['id'] : '' ); if ( $label ) { $html .= '<div class="forminator-field--label">'; $html .= sprintf( '<label for="%s" id="forminator-label-%s" class="forminator-label">%s</label>', $editor_id, $attr['id'], esc_html( $label ) . ( $required ? ' ' . forminator_get_required_icon() : '' ) ); $html .= '</div>'; } $wp_editor_class = isset( $attr['class'] ) ? $attr['class'] : ''; if ( $required ) { apply_filters( 'the_editor', array( __CLASS__, 'add_required_wp_editor' ) ); $wp_editor_class .= ' do-validate forminator-wp-editor-required'; } elseif ( ! empty( $limit ) ) { $wp_editor_class .= ' do-validate'; } ob_start(); wp_editor( $content, $editor_id, array( 'textarea_name' => isset( $attr['name'] ) ? $attr['name'] : '', 'media_buttons' => false, 'editor_class' => $wp_editor_class, 'editor_height' => $default_height, ) ); $html .= ob_get_clean(); if ( ! empty( $description ) ) { $html .= self::get_description( $description ); } return apply_filters( 'forminator_field_create_wp_editor', $html, $attr, $label, $description ); } /** * Add Required attribute to wp_editor * * @since 1.0.2 * * @param string $editor_markup Editor markup. * * @return mixed */ public static function add_required_wp_editor( $editor_markup ) { if ( stripos( $editor_markup, 'forminator-wp-editor-required' ) !== false ) { // mark required. $editor_markup = str_replace( '<textarea', '<textarea required="true"', $editor_markup ); } return $editor_markup; } /** * Maybe add label if it's not empty * * @param string $label Field label. * @param string $id Field id. * @param bool $required Is field required or not. * @return string */ protected static function get_field_label( $label, $id, $required ) { $html = ''; if ( $label ) { $html .= sprintf( '<label for="%s" id="%s" class="forminator-label">%s</label>', esc_attr( $id ), esc_attr( $id . '-label' ), esc_html( $label ) . ( $required ? ' ' . forminator_get_required_icon() : '' ) ); } return $html; } /** * Get full field id * * @param string $element_id Field slug. * @return string */ protected static function get_field_id( $element_id ) { return 'forminator-field-' . $element_id . '_' . Forminator_CForm_Front::$uid; } /** * Return new select field * * @since 1.0 * * @param array $attr Field attribute. * @param string $label Field label. * @param array $options Field option. * @param string $value Field value. * @param string $description Field description. * @param bool $required Required. * * @return mixed */ public static function create_select( $attr = array(), $label = '', $options = array(), $value = '', $description = '', $required = false ) { $html = ''; if ( ! empty( $description ) ) { $attr['aria-describedby'] = $attr['id'] . '-description'; } if ( isset( $attr['id'] ) ) { $get_id = $attr['id']; } else { $get_id = uniqid( 'forminator-select-' ); } ! empty( $label ) ? $attr['aria-labelledby'] = $get_id . '-label' : ''; ! empty( $description ) ? $attr['aria-describedby'] = $get_id . '-description' : ''; $markup = self::implode_attr( $attr ); if ( self::get_post_data( $attr['name'], false ) ) { $value = self::get_post_data( $attr['name'] ); } $html .= self::get_field_label( $label, $get_id, $required ); $markup .= ' data-default-value="' . esc_attr( $value ) . '"'; $html .= sprintf( '<select %s>', $markup ); $html .= self::populate_options_for_select( $options, $value ); $html .= '</select>'; if ( ! empty( $description ) ) { $html .= self::get_description( $description, $get_id ); } return apply_filters( 'forminator_field_create_select', $html, $attr, $label, $options, $value, $description ); } /** * Return new simple select field * * @since 1.0 * * @param array $attr Field Attribute. * @param array $options Field Options. * @param string $value Field Value. * @param string $description Field Description. * * @return mixed */ public static function create_simple_select( $attr = array(), $options = array(), $value = '', $description = '' ) { _deprecated_function( 'create_simple_select', '1.6.1', 'create_select' ); $html = ''; $get_id = uniqid( 'forminator-select-' ); ! empty( $description ) ? $attr['aria-describedby'] = $get_id . '-description' : ''; $markup = self::implode_attr( $attr ); if ( self::get_post_data( $attr['name'], false ) ) { $value = self::get_post_data( $attr['name'] ); } $html .= sprintf( '<select %s>', $markup ); $html .= self::populate_options_for_select( $options, $value ); $html .= '</select>'; if ( ! empty( $description ) ) { $html .= self::get_description( $description, $get_id ); } return apply_filters( 'forminator_field_create_simple_select', $html, $attr, $options, $value, $description ); } /** * Populate <options>s for <select> * * @since 1.5.2 * * @param array $options Options. * @param string $selected_value Selected value. * * @return string */ public static function populate_options_for_select( $options, $selected_value = '' ) { $html = ''; foreach ( $options as $option ) { $selected = ''; $disabled = isset( $option['disabled'] ) && $option['disabled'] ? ' disabled' : ''; if ( isset( $option['value'] ) && is_array( $option['value'] ) ) { $populated_optgroup_options = self::populate_options_for_select( $option['value'], $selected_value ); $html .= sprintf( '<optgroup label="%s">%s</optgroup>', esc_attr( $option['label'] ), $populated_optgroup_options ); } else { if ( ( '' === $selected_value && '' === $option['value'] ) || ( '' !== $selected_value && $option['value'] == $selected_value ) // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- loose comparison ok : possible compare '01' and '1'. || ! empty( $option['selected'] ) ) { $selected = 'selected="selected"'; } $html .= sprintf( '<option value="%s" %s%s>%s</option>', esc_html( $option['value'] ), $selected, $disabled, esc_html( $option['label'] ) ); } } return $html; } /** * Create file upload * * @since 1.0 * * @param string $id Field Id. * @param string $name Field name. * @param string $description Field description. * @param bool $required Field required. * @param string $design Design. * @param string $file_type File type. * @param integer $form_id Form Id. * @param array $upload_attr Upload attributes. * * @return string $html */ public static function create_file_upload( $id, $name, $description, $required, $design, $file_type = 'single', $form_id = 0, $upload_attr = array() ) { $html = ''; $style = ''; $field_id = $id; $id = 'forminator-field-' . $field_id; $button_id = 'forminator-field-' . $field_id . '_button'; $mainclass = 'forminator-file-upload'; $class = 'forminator-input-file'; $aria_describedby = ( ! empty( $description ) ? ' aria-describedby="' . esc_attr( $id . '-description' ) . '"' : '' ); if ( $required ) { $class .= '-required do-validate'; } if ( 'multiple' === $file_type ) { $mainclass = 'forminator-multi-upload'; $class .= ' ' . $id . '-' . $form_id; } $upload_data = self::implode_attr( $upload_attr ); $html .= sprintf( '<div class="%s %s" data-element="%s"%s>', $mainclass, $style, $field_id, $aria_describedby ); $html .= sprintf( '<input type="file" name="%s" id="%s" class="%s" %s>', $name, $id, $class, $upload_data ); if ( 'none' === $design ) { $html .= sprintf( '<button class="forminator-upload--remove" style="display: none;">%s</button>', esc_html__( 'Remove', 'forminator' ) ); } elseif ( 'multiple' === $file_type ) { $html .= '<div class="forminator-multi-upload-message" aria-hidden="true">'; $html .= '<span class="forminator-icon-upload" aria-hidden="true"></span>'; $html .= '<p>'; // translators: %1$s - Opening anchor tag, %2$s - Closing anchor tag. $html .= sprintf( esc_html__( 'Drag and Drop (or) %1$sChoose Files%2$s', 'forminator' ), '<a class="forminator-upload-file--' . $id . '" href="#" onclick="return false;">', '</a>' ); $html .= '</p>'; $html .= '</div>'; } else { $html .= sprintf( '<button id="%s" class="forminator-button forminator-button-upload" data-id="%s">', $button_id, $id ); if ( 'material' === $design ) { $html .= sprintf( '<span>%s</span>', esc_html__( 'Choose File', 'forminator' ) ); $html .= '<span aria-hidden="true"></span>'; } else { $html .= esc_html__( 'Choose File', 'forminator' ); } $html .= '</button>'; $html .= sprintf( '<span data-empty-text="%s">%s</span>', esc_html__( 'No file chosen', 'forminator' ), esc_html__( 'No file chosen', 'forminator' ) ); $html .= '<button class="forminator-button-delete" style="display: none;">'; $html .= '<i class="forminator-icon-close" aria-hidden="true"></i>'; $html .= sprintf( '<span class="forminator-screen-reader-only">%s</span>', esc_html__( 'Delete uploaded file', 'forminator' ) ); $html .= '</button>'; } $html .= '</div>'; // Check if description is not empty and append it. if ( ! empty( $description ) ) { $html .= self::get_description( $description, $id ); } return apply_filters( 'forminator_field_create_file_upload', $html, $id, $name, $required ); } /** * Return string from array * * @since 1.0 * * @param array $args Attributes. * * @return string */ public static function implode_attr( $args ) { $data = array(); foreach ( $args as $key => $value ) { $data[] = $key . '="' . esc_attr( $value ) . '"'; } return implode( ' ', $data ); } /** * Validate data * * @since 1.0 * * @param array $field Field. * @param array|string $data - the data to be validated. */ public function validate( $field, $data ) { } /** * Validate field data * * @param array $field_array Field settings. * @param array|string $field_data - the data to be validated. * @return array validated field data. */ public function validate_entry( $field_array, $field_data ) { // Validate data when its available. if ( $this->is_available( $field_array ) ) { /** * Mayble re autofill, when autofill not editable, it should return autofill value * * @since 1.0.5 */ $field_data = $this->maybe_autofill( $field_array, $field_data, Forminator_CForm_Front_Action::$module_settings ); $this->validate( $field_array, $field_data ); } return $field_data; } /** * Check if entry is valid for the field * * @since 1.0 * @return bool|array true on valid, or array validation messages on invalid */ public function is_valid_entry() { $this->is_valid = empty( $this->validation_message ); if ( ! $this->is_valid ) { foreach ( $this->validation_message as $field_name => $error ) { Forminator_CForm_Front_Action::$submit_errors[][ $field_name ] = $error; } return $this->validation_message; } return $this->is_valid; } /** * Check if field has input limit * * @since 1.0 * * @param array $field Field. * * @return bool */ public function has_limit( $field ) { if ( isset( $field['limit'] ) && intval( $field['limit'] ) > 0 ) { return true; } return false; } /** * Check if field is required * * @since 1.0 * * @param array $field Field. * * @return bool */ public function is_required( $field ) { $required = self::get_property( 'required', $field, false ); $required = filter_var( $required, FILTER_VALIDATE_BOOLEAN ); return $required; } /** * Check if Field is hidden based on conditions property and POST-ed data * * @param array $field_settings Field settings. * @param array $extra_conditions payment plan conditions. * @param string $group_suffix Group suffix. * * @return bool */ public static function is_hidden( $field_settings, $extra_conditions = array(), $group_suffix = '' ) { $conditions = isset( $extra_conditions['conditions'] ) ? $extra_conditions['conditions'] : self::get_field_conditions( $field_settings, $group_suffix ); $condition_rule = isset( $extra_conditions['condition_rule'] ) ? $extra_conditions['condition_rule'] : self::get_property( 'condition_rule', $field_settings, 'all' ); $condition_action = isset( $extra_conditions['condition_action'] ) ? $extra_conditions['condition_action'] : self::get_property( 'condition_action', $field_settings, 'show' ); // empty conditions. if ( empty( $conditions ) ) { return false; } $condition_fulfilled = 0; $conditions_count = 0; foreach ( $conditions as $condition ) { $element_id = $condition['element_id']; // Increase conditions count. ++$conditions_count; if ( in_array( $element_id, Forminator_CForm_Front_Action::$hidden_fields, true ) ) { $current_is_hidden = true; $is_condition_fulfilled = isset( $condition['rule'] ) && 'is_not' === $condition['rule'] && isset( $condition['value'] ) && ! is_null( $condition['value'] ) && '' !== $condition['value']; } else { $current_is_hidden = false; $is_condition_fulfilled = self::is_condition_matched( $condition ); } if ( $is_condition_fulfilled ) { ++$condition_fulfilled; } elseif ( 'all' === $condition_rule ) { // if condition rule is ALL and at least one condition isn't matched - we don't need to check others. break; } // Check parent conditions only if the current condition is matched. if ( $is_condition_fulfilled && ! $current_is_hidden && Forminator_Front_Action::$module_object ) { $parent_field = Forminator_Front_Action::$module_object->get_field( $element_id ); $parent_hidden = self::is_hidden( $parent_field, array(), $group_suffix ); if ( $parent_hidden ) { --$condition_fulfilled; if ( 'all' === $condition_rule ) { break; } } } // There is no sense to continue checking if at least 1 condition is matched for ANY condition rule. if ( 'any' === $condition_rule && $condition_fulfilled ) { break; } } $all_matched = ( $condition_fulfilled > 0 && 'any' === $condition_rule ) || ( $conditions_count === $condition_fulfilled && 'all' === $condition_rule ); // initialized as hidden. if ( 'show' === $condition_action ) { return ! $all_matched; } else { // initialized as shown. return $all_matched; } } /** * Get field conditions * * @param array $field_settings Field settings. * @param string $group_suffix Group suffix. * @return array */ public static function get_field_conditions( $field_settings, $group_suffix ) { $conditions = self::get_property( 'conditions', $field_settings, array() ); foreach ( $conditions as $key => $condition ) { if ( forminator_old_field( $condition['element_id'], Forminator_Front_Action::$module_object->get_fields(), Forminator_Front_Action::$module_id ) ) { unset( $conditions[ $key ] ); } } if ( ! $group_suffix || empty( $conditions ) ) { return $conditions; } $parent_group = $field_settings['parent_group'] ?? ''; $grouped_fields = Forminator_Front_Action::$module_object->get_grouped_fields_slugs( $parent_group ); if ( empty( $grouped_fields ) ) { return $conditions; } foreach ( $conditions as $key => $condition ) { foreach ( $grouped_fields as $g_field ) { if ( $condition['element_id'] === $g_field || 0 === strpos( $condition['element_id'], $g_field . '-' ) ) { $conditions[ $key ]['element_id'] .= $group_suffix; } } } return $conditions; } /** * Check if passed condition is matched * * @param array $condition Current condition. * @return bool */ public static function is_condition_matched( $condition ) { $form_data = Forminator_CForm_Front_Action::$prepared_data; $form_id = $form_data['form_id']; // empty conditions. if ( empty( $condition ) ) { return false; } $element_id = $condition['element_id']; $field_value = isset( $form_data[ $element_id ] ) ? $form_data[ $element_id ] : ''; if ( stripos( $element_id, 'upload-' ) !== false && ! isset( $form_data[ $element_id ] ) && isset( $form_data['forminator-multifile-hidden'] ) ) { $form_upload_data = $form_data['forminator-multifile-hidden']; if ( $form_upload_data && isset( $form_upload_data[ $element_id ] ) ) { $field_value = $form_upload_data[ $element_id ]; } } // If date field is dropdown type. if ( stripos( $element_id, 'date-' ) !== false && isset( $form_data[ $element_id . '-month' ] ) && isset( $form_data[ $element_id . '-day' ] ) && isset( $form_data[ $element_id . '-year' ] ) ) { $field_value = $form_data[ $element_id . '-year' ] . '-' . $form_data[ $element_id . '-month' ] . '-' . $form_data[ $element_id . '-day' ]; $date_format = Forminator_API::get_form_field( $form_id, $element_id, false )->date_format; $normalized_format = new Forminator_Date(); $normalized_format = $normalized_format->normalize_date_format( $date_format ); $date = date_create_from_format( 'Y-m-d', $field_value ); $field_value = false !== $date ? date_format( $date, $normalized_format ) : ''; } if ( stripos( $element_id, 'signature-' ) !== false ) { // We have signature field. $is_condition_fulfilled = false; $signature_id = 'field-' . $element_id; if ( isset( $form_data[ $signature_id ] ) ) { $signature_data = 'ctlSignature' . $form_data[ $signature_id ] . '_data'; if ( isset( $form_data[ $signature_data ] ) ) { $is_condition_fulfilled = self::is_condition_fulfilled( $form_data[ $signature_data ], $condition ); } } } elseif ( stripos( $element_id, 'calculation-' ) !== false || stripos( $element_id, 'stripe-' ) !== false ) { $is_condition_fulfilled = false; if ( isset( Forminator_CForm_Front_Action::$prepared_data[ $element_id ] ) ) { // Condition's value is saved as a string value. $is_condition_fulfilled = self::is_condition_fulfilled( (string) Forminator_CForm_Front_Action::$prepared_data[ $element_id ], $condition ); } } elseif ( stripos( $element_id, 'checkbox-' ) !== false || stripos( $element_id, 'radio-' ) !== false ) { $is_condition_fulfilled = self::is_condition_fulfilled( $field_value, $condition ); } elseif ( stripos( $element_id, 'rating-' ) !== false ) { $rating_value = explode( '/', $field_value )[0] ?? 0; $is_condition_fulfilled = self::is_condition_fulfilled( $rating_value, $condition ); } else { $is_condition_fulfilled = self::is_condition_fulfilled( $field_value, $condition, $form_id ); } return $is_condition_fulfilled; } /** * Check if Form Field value fullfilled the condition * * @since 1.0 * * @param mixed $form_field_value Form field. * @param array $condition Condition. * @param null|integer $form_id Form ID. * * @return bool */ public static function is_condition_fulfilled( $form_field_value, $condition, $form_id = null ) { if ( is_array( $form_field_value ) ) { $form_field_value = forminator_trim_array( $form_field_value ); } else { $form_field_value = strtolower( trim( $form_field_value ) ); } $form_field_value = wp_unslash( $form_field_value ); $condition_value = trim( $condition['value'] ); // Remove lines below coz strtolower is already applied using forminator_trim_array. // if ( is_array( $form_field_value ) ) { // $form_field_value = array_map( 'strtolower', $form_field_value ); // } else if ( is_string( $form_field_value ) ) { // $form_field_value = strtolower( $form_field_value ); // }. if ( is_string( $condition_value ) ) { $condition_value = strtolower( $condition_value ); } switch ( $condition['rule'] ) { case 'is': if ( is_array( $form_field_value ) ) { // possible input is "1" to be compared with 1. return in_array( $condition_value, $form_field_value ); //phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict } if ( is_numeric( $condition_value ) ) { return ( (int) $form_field_value === (int) $condition_value ); } return ( $form_field_value === $condition_value ); case 'is_not': if ( is_array( $form_field_value ) ) { // possible input is "1" to be compared with 1. return ! in_array( $condition_value, $form_field_value ); //phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict } return ( $form_field_value !== $condition_value ); case 'is_great': if ( ! is_numeric( $condition_value ) ) { return false; } if ( ! is_numeric( $form_field_value ) ) { return false; } return $form_field_value > $condition_value; case 'is_less': if ( ! is_numeric( $condition_value ) ) { return false; } if ( ! is_numeric( $form_field_value ) ) { return false; } return $form_field_value < $condition_value; case 'contains': return ( stripos( $form_field_value, $condition_value ) === false ? false : true ); case 'does_not_contain': return ! ( stripos( $form_field_value, $condition_value ) !== false ); case 'starts': return ( stripos( $form_field_value, $condition_value ) === 0 ? true : false ); case 'ends': return ( substr( $form_field_value, - strlen( $condition_value ) ) === $condition_value ); case 'day_is': if ( null !== $form_id && ! empty( $form_field_value ) ) { $day = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'D' ); return strtolower( $day ) === $condition_value; } return false; case 'day_is_not': if ( null !== $form_id && ! empty( $form_field_value ) ) { $day = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'D' ); return strtolower( $day ) !== $condition_value; } return false; case 'month_is': if ( null !== $form_id && ! empty( $form_field_value ) ) { $month = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'M' ); return strtolower( $month ) === $condition_value; } return false; case 'month_is_not': if ( null !== $form_id && ! empty( $form_field_value ) ) { $month = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'M' ); return strtolower( $month ) !== $condition_value; } return false; case 'is_before': if ( null !== $form_id && ! empty( $form_field_value ) ) { $date = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'j F Y' ); return strtotime( $date ) < Forminator_Date::prepare_condition_date( $condition_value ); } return false; case 'is_after': if ( null !== $form_id && ! empty( $form_field_value ) ) { $date = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'j F Y' ); return strtotime( $date ) > Forminator_Date::prepare_condition_date( $condition_value ); } return false; case 'is_before_n_or_more_days': if ( null !== $form_id && ! empty( $form_field_value ) ) { $date = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'Y-m-d' ); return strtotime( $date ) <= strtotime( '-' . $condition_value . ' days' ); } return false; // date_is_less_than_n_days_before_current_date. case 'is_before_less_than_n_days': if ( null !== $form_id && ! empty( $form_field_value ) ) { $date = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'Y-m-d' ); $rule_date = strtotime( '-' . $condition_value . ' days' ); $current_date = strtotime( 'today' ); return $rule_date < strtotime( $date ) && strtotime( $date ) <= $current_date; } return false; case 'is_after_n_or_more_days': if ( null !== $form_id && ! empty( $form_field_value ) ) { $date = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'Y-m-d' ); return strtotime( $date ) >= strtotime( '+' . $condition_value . ' days' ); } return false; // date_is_less_than_n_days_after_current_date. case 'is_after_less_than_n_days': if ( null !== $form_id && ! empty( $form_field_value ) ) { $date = self::get_day_or_month( $form_field_value, $condition['element_id'], $form_id, 'Y-m-d' ); $rule_date = strtotime( '+' . $condition_value . ' days' ); $current_date = strtotime( 'today' ); return $rule_date > strtotime( $date ) && strtotime( $date ) >= $current_date; } return false; case 'is_correct': return $form_field_value ? true : false; case 'is_incorrect': return ! $form_field_value ? true : false; case 'is_final_result': return $form_field_value === $condition['element_id']; case 'is_not_final_result': return $form_field_value !== $condition['element_id']; default: return false; } } /** * Get the day or month from given date * * @since 1.14 * * @param mixed $form_field_value Form field value. * @param string $element_id Element Id. * @param integer $form_id Form ID. * @param string $format Format. * * @return string|bool */ public static function get_day_or_month( $form_field_value, $element_id, $form_id, $format ) { if ( empty( $form_field_value ) ) { return false; } $date_format = Forminator_API::get_form_field( $form_id, $element_id, false )->date_format; $normalized_format = new Forminator_Date(); $normalized_format = $normalized_format->normalize_date_format( $date_format ); $date = date_create_from_format( $normalized_format, $form_field_value ); if ( false === $date ) { $date = date_create_from_format( 'Y/m/d', $form_field_value ); } if ( 'D' === $format ) { // Day format is based on fields' visibility day format. return substr( date_format( $date, $format ), 0, -1 ); } else { return date_format( $date, $format ); } } /** * Get subfield id. * * @param string $id Field ID. * @param string $prefix Field prefix. * @return string */ protected static function get_subfield_id( $id, $prefix ) { $parts = explode( '-', $id ); $real_id = implode( '-', array_slice( $parts, 0, 2 ) ); $group_id = implode( '-', array_slice( $parts, 2 ) ); $subfield_id = $real_id . $prefix; if ( $group_id ) { $subfield_id .= '-' . $group_id; } return $subfield_id; } /** * Return field ID * * @since 1.0 * * @param array $field Field. * * @return string */ public function get_id( $field ) { return self::get_property( 'element_id', $field ); } /** * Field validation rules * * @since 1.0 * @return string */ public function get_validation_rules() { return ''; } /** * Field validation messages * * @since 1.0 * @return string */ public function get_validation_messages() { return ''; } /** * Sanitize data * * @since 1.0.2 * * @param array $field Field. * @param array|string $data - the data to be sanitized. * * @return array|string $data - the data after sanitization */ public function sanitize( // @noinspection PhpUnusedParameterInspection. $field, $data ) { return $data; } /** * Sanitize value * * @param mixed $value Value. * @return string */ public function sanitize_value( $value ) { return htmlspecialchars( $value, ENT_COMPAT ); } /** * Check if field is available * Override it for field that needs dependencies * Example : `captcha` that needs `captcha_key` to be displayed properly * * @see Forminator_Captcha::is_available() * * @since 1.0.3 * * @param array $field Field. * * @return bool */ public function is_available( // @noinspection PhpUnusedParameterInspection. $field ) { return true; } /** * Return form style * * @since 1.0.3 * * @param array $settings Settings. * * @return string|bool */ public function get_form_style( $settings ) { if ( isset( $settings['form-style'] ) ) { return $settings['form-style']; } return false; } /** * Return value stored in $_POST, or the fallback value * * @since 1.1 * * @param string $id Field Id. * @param mixed $fallback Fallback. * * @return mixed value of $_POST[$id] or $fallback when unavailable */ public static function get_post_data( $id, $fallback = '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- The nonce is verified before the method call. if ( isset( $_POST[ $id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput -- The nonce is verified before the method call and sanitized in Forminator_Core::sanitize_array. $post_data = Forminator_Core::sanitize_array( $_POST[ $id ], $id ); } if ( ! empty( $post_data ) ) { return self::get_post_data_sanitize( $post_data, $fallback ); } return $fallback; } /** * Return sanitized $_POST value, or the fallback value * * @since 1.6.3 * * @param string $data Post data. * @param mixed $fallback Fallback. * * @return mixed value of $_POST[$id] or $fallback when unavailable */ public static function get_post_data_sanitize( $data, $fallback ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed if ( is_array( $data ) ) { $escaped = array(); foreach ( $data as $key => $value ) { $escaped[ $key ] = self::get_post_data_sanitize( $value, '' ); } return $escaped; } return esc_html( $data ); } /** * Abstraction of autofill settings * * @since 1.0.5 * * @param array $settings Settings. * * @return array */ public function autofill_settings( $settings = array() ) { return $settings; } /** * Get Autofill setting as paired ['element_id' => $setting] * * @since 1.0.5 * * @param array $settings Settings. * * @return array */ public static function get_autofill_setting( $settings ) { // Autofill not enabled. if ( ! self::is_autofill_enabled( $settings ) ) { return array(); } if ( ! empty( $settings['fields-autofill'] ) ) { // build to array key. $fields_autofill = $settings['fields-autofill']; $fields_autofill_pair = array(); if ( ! is_array( $fields_autofill ) ) { return array(); } foreach ( $fields_autofill as $field_autofill ) { if ( empty( $field_autofill['element_id'] ) ) { continue; } $fields_autofill_pair[ $field_autofill['element_id'] ] = $field_autofill; } return $fields_autofill_pair; } return array(); } /** * Check if autofill enabled on this form * * @since 1.0.5 * * @param array $settings Settings. * * @return bool */ public static function is_autofill_enabled( $settings ) { return isset( $settings['use-autofill'] ) ? forminator_var_type_cast( $settings['use-autofill'], 'bool' ) : false; } /** * Restore value of the POST fields if its not editable, so we ensure its not modified by anykind * Happens before this POST fields getting validated, so autofill-ed value will be getting validated too * * @since 1.0.5 * * @param array $field_array Field array. * @param mixed $field_data Field data. * @param array $settings Settings. * * @return array|mixed|string */ public function maybe_autofill( $field_array, $field_data, $settings ) { if ( ( isset( $settings['form-type'] ) && in_array( $settings['form-type'], array( 'registration', 'login' ), true ) ) || ! is_user_logged_in() ) { return $field_data; } $autofill_settings = self::get_autofill_setting( $settings ); if ( empty( $autofill_settings ) ) { return $field_data; } $element_id = self::get_property( 'element_id', $field_array ); if ( is_array( $field_data ) ) { foreach ( $field_data as $element_id_suffix => $field_datum ) { $element_id = $element_id . '-' . $element_id_suffix; $element_autofill_settings = self::get_element_autofill_settings( $element_id, $autofill_settings ); if ( ! self::element_autofill_is_editable( $element_autofill_settings ) ) { // refill with autofill provider. $field_data[ $element_id_suffix ] = $this->maybe_replace_to_autofill_value( $field_datum, $element_autofill_settings ); } } } else { $element_autofill_settings = self::get_element_autofill_settings( $element_id, $autofill_settings ); if ( ! self::element_autofill_is_editable( $element_autofill_settings ) ) { $current_data = $field_data; // refill with autofill provider. $field_data = $this->maybe_replace_to_autofill_value( $field_data, $element_autofill_settings ); if ( ! strlen( $field_data ) ) { $field_data = $current_data; } } } return $field_data; } /** * Get autofill as markup attributes to used later * * @since 1.0.5 * * @example { * 'value' => [] // VALUE. * 'readonly' => 'readonly' * } * * @param string $element_id Element Id. * * @return array */ public function get_element_autofill_markup_attr( $element_id ) { $settings = $this->form_settings; if ( ! self::is_autofill_enabled( $settings ) ) { return array(); } $autofill_settings = self::get_autofill_setting( $settings ); if ( empty( $autofill_settings ) ) { return array(); } $element_autofill_settings = self::get_element_autofill_settings( $element_id, $autofill_settings ); $value = $this->maybe_replace_to_autofill_value( '', $element_autofill_settings ); // only return value when its autofilled. if ( ! empty( $value ) ) { $markup_attr = array( 'value' => $value, ); // only disable if value is not empty. if ( ! self::element_autofill_is_editable( $element_autofill_settings ) ) { $markup_attr['readonly'] = 'readonly'; } return $markup_attr; } return array(); } /** * Get element autofill value if all requirement(s) fulfilled * - Autofill Provider activated * * @param mixed $element_value Element value. * @param array $element_autofill_settings Element settings. * * @return mixed|string */ public function maybe_replace_to_autofill_value( $element_value, $element_autofill_settings ) { if ( ! empty( $element_autofill_settings['provider'] ) ) { $attribute_provider = $element_autofill_settings['provider']; $provider_parts = explode( '.', $attribute_provider ); if ( ! empty( $provider_parts[1] ) ) { $provider_slug = $provider_parts[0]; $provider_instance = forminator_autofill_init_provider( $provider_slug ); if ( $provider_instance ) { $element_value = $provider_instance->fill( $provider_parts[1] ); } } } return $element_value; } /** * Get individial element autofill setting * * @since 1.0.5 * * @param string $element_id Element id. * @param array $autofill_settings Settings. * * @return array */ public static function get_element_autofill_settings( $element_id, $autofill_settings ) { $autofill_element_settings = array(); if ( isset( $autofill_settings[ $element_id ] ) && is_array( $autofill_settings[ $element_id ] ) ) { $autofill_element_settings = $autofill_settings[ $element_id ]; } return $autofill_element_settings; } /** * Check if an element is editable when autofill enabled * * @param array $element_autofill_settings Settings. * * @return bool */ public static function element_autofill_is_editable( $element_autofill_settings ) { if ( isset( $element_autofill_settings['is_editable'] ) && 'yes' === $element_autofill_settings['is_editable'] ) { return true; } return false; } /** * Get required message for multiple name field * * @param string $id Field Id. * @param array $field Field. * @param string $property Property. * @param string $slug Slug. * @param mixed $fallback Fallback. * * @return string */ protected function get_field_multiple_required_message( $id, $field, $property, $slug, $fallback ) { // backward compat *_required_message. $required_message = self::get_property( $property, $field, self::FIELD_PROPERTY_VALUE_NOT_EXIST, 'string' ); if ( self::FIELD_PROPERTY_VALUE_NOT_EXIST === $required_message || empty( $required_message ) ) { $required_message = $fallback; } $required_message = wp_kses_post( $required_message ); $required_message = apply_filters( "forminator_{$this->slug}_field_{$slug}_required_validation_message", $required_message, $id, $field ); return $required_message; } /** * Get calculable value * * @since 1.7 * * @param array|mixed $submitted_field_data Field data. * @param array $field_settings Settings. * * @return float|string */ public static function get_calculable_value( $submitted_field_data, $field_settings ) { $field_slug = $field_settings['type']; $calculable_value = self::FIELD_NOT_CALCULABLE; /** * Filter formula being used on calculable value on abstract level * this hook can be used on un-implemented calculation field * * @since 1.7 * * @param float $calculable_value * @param array $submitted_field_data * @param array $field_settings * * @return string|int|float formula, or hardcoded value */ $calculable_value = apply_filters( "forminator_field_{$field_slug}_calculable_value", $calculable_value, $submitted_field_data, $field_settings ); return $calculable_value; } /** * * Get calculable precision * * @since 1.7 * * @param array $field_settings Settings. * * @return int */ public static function get_calculable_precision( $field_settings ) { $fallback = ! empty( $field_settings['type'] ) && 'number' === $field_settings['type'] ? 0 : 2; $precision = self::get_property( 'precision', $field_settings, $fallback, 'num' ); /** * Filter formula being used on calculable value on abstract level * this hook can be used on un-implemented calculation field * * @param int $precision * @param array $submitted_data * @param array $field_settings * * @return string|int|float formula, or hardcoded value */ $precision = apply_filters( 'forminator_field_calculable_precision', $precision, Forminator_CForm_Front_Action::$prepared_data, $field_settings ); return $precision; } /** * Return if field has pre-fill value filled * * @since 1.10 * * @param array $field Field. * @param boolean|string $prefix Prefix. * @return bool */ public function has_prefill( $field, $prefix = false ) { if ( $prefix ) { $prefix = $prefix . '_'; } $prefill = self::get_property( $prefix . 'prefill', $field, false ); if ( $prefill ) { return true; } return false; } /** * Get pre-fill value if set, else return $default * * @since 1.10 * * @param array $field Field. * @param mixed $default_value Default value. * @param bool|string $prefix Prefix. * @return mixed */ public function get_prefill( $field, $default_value, $prefix = false ) { if ( $prefix ) { $prefix = $prefix . '_'; } $prefill = self::get_property( $prefix . 'prefill', $field, false ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- The nonce is verified before the method call. if ( isset( $_REQUEST[ $prefill ] ) ) { if ( 'textarea' === $field['type'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- The nonce is verified before the method call. $return = rawurldecode( wp_kses_post( wp_unslash( $_REQUEST[ $prefill ] ) ) ); } else { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- The nonce is verified before the method call. $return = rawurldecode( esc_html( wp_unslash( $_REQUEST[ $prefill ] ) ) ); } if ( $return ) { return $return; } } return $default_value; } /** * Replace object value from prefill * * @since 1.10 * * @param array $field Field. * @param array $attributes Attributes. * @param string $prefix Prefix. * @param bool $default_value Default value. * @return mixed */ public function replace_from_prefill( $field, $attributes, $prefix, $default_value = false ) { if ( $this->has_prefill( $field, $prefix ) ) { // We have pre-fill parameter, use its value or $value. $value = $this->get_prefill( $field, $default_value, $prefix ); $attributes['value'] = esc_html( $value ); } return $attributes; } /** * Get TinyMCE arguments for js on front-end * * @param string $id Editor ID. * @return string */ public static function get_tinymce_args( $id ) { $args = "{ tinymce: { wpautop : true, theme : 'modern', skin : 'lightgray', language : 'en', formats : { alignleft : [ { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: { textAlign: 'left' } }, { selector: 'img,table,dl.wp-caption', classes: 'alignleft' } ], aligncenter: [ { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: { textAlign: 'center' } }, { selector: 'img,table,dl.wp-caption', classes: 'aligncenter' } ], alignright : [ { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: { textAlign: 'right' } }, { selector: 'img,table,dl.wp-caption', classes: 'alignright' } ], strikethrough: { inline: 'del' } }, relative_urls : false, remove_script_host : false, convert_urls : false, browser_spellcheck : true, fix_list_elements : true, entities : '38,amp,60,lt,62,gt', entity_encoding : 'raw', keep_styles : false, paste_webkit_styles : 'font-weight font-style color', preview_styles : 'font-family font-size font-weight font-style text-decoration text-transform', tabfocus_elements : ':prev,:next', plugins : 'charmap,hr,media,paste,tabfocus,textcolor,fullscreen,wptextpattern,lists,wordpress,wpeditimage,wpgallery,link,wplink,wpdialogs,wpview'," // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText -- false positive. . " resize : 'vertical', menubar : false, indent : false, toolbar1 : 'formatselect,bold,italic,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,wp_more,fullscreen,wp_adv', toolbar2 : 'strikethrough,underline,hr,forecolor,pastetext,alignjustify,removeformat,charmap,outdent,indent,undo,redo,wp_help', toolbar3 : '', toolbar4 : '', body_class : 'id post-type-post post-status-publish post-format-standard', wpeditimage_disable_captions: false, wpeditimage_html5_captions : true }, quicktags: true, }"; /** * Filter TinyMCE arguments for js on front-end. * * @since 1.1 * * @param string $args TinyMCE arguments. * @param string $id Editor ID. */ $args = apply_filters( 'forminator_tinymce_args', $args, $id ); return $args; } /** * Number separators * * @param string $separator Separator. * @param string $field Field. * * @return array */ public static function forminator_separators( $separator, $field ) { $separators = array( 'blank' => array( 'point' => '.', 'separator' => '', ), 'comma_dot' => array( 'point' => '.', 'separator' => ',', ), 'dot_comma' => array( 'point' => ',', 'separator' => '.', ), 'space_comma' => array( 'point' => ',', 'separator' => ' ', ), ); if ( 'custom' === $separator ) { $data_point = self::get_property( 'decimal-separators', $field, '.' ); $data_separator = self::get_property( 'thousand-separators', $field, ',' ); } else { $data_point = $separators[ $separator ]['point']; $data_separator = $separators[ $separator ]['separator']; } return array( 'separator' => $data_separator, 'point' => $data_point, ); } /** * Number formatting * * @param string $field Field. * @param string $number Number. * * @return string */ public static function forminator_number_formatting( $field, $number ) { $precision = self::get_calculable_precision( $field ); $separator = self::get_property( 'separators', $field, 'blank' ); $separators = self::forminator_separators( $separator, $field ); $data_value = (float) str_replace( $separators['point'], '.', $number ); $formatted = number_format( $data_value, $precision, $separators['point'], $separators['separator'] ); if ( ! empty( $field['prefix'] ) || ! empty( $field['suffix'] ) ) { // Prefix. $formatted = ( ! empty( $field['prefix'] ) ? $field['prefix'] . ' ' : '' ) . $formatted; // Suffix. $formatted = $formatted . ( ! empty( $field['suffix'] ) ? ' ' . $field['suffix'] : '' ); } elseif ( ! empty( $field['currency'] ) ) { $formatted .= ' ' . $field['currency']; } return $formatted; } /** * Replace number formatting * * @param array $field Field. * @param string $number Number. * * @return string */ public static function forminator_replace_number( $field, $number ) { $separator = self::get_property( 'separators', $field, 'blank' ); $separators = self::forminator_separators( $separator, $field ); // Replace decimal with # temporarily to prevent being replaced with a separator. $number = str_replace( $separators['point'], '#', $number ); $number = str_replace( $separators['separator'], '', $number ); $number = str_replace( '#', '.', $number ); return $number; } /** * Check index and htaccess files inside root directory. And create them if need it. */ public static function check_upload_root_index_file() { $upload_root = forminator_upload_root(); // Make sure it was not called before WP init. if ( ! file_exists( $upload_root . 'index.php' ) && function_exists( 'insert_with_markers' ) ) { self::add_index_file( $upload_root ); self::add_htaccess_file(); } } /** * Create index file * * @param string $dir Directory. * * @return void */ public static function add_index_file( $dir ) { $dir = untrailingslashit( $dir ); if ( ! is_dir( $dir ) || ! wp_is_writable( $dir ) || is_link( $dir ) ) { return; } $dp = opendir( $dir ); if ( ! $dp ) { return; } if ( ! function_exists( 'wp_filesystem' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } global $wp_filesystem; if ( WP_Filesystem() ) { $index_file_path = $dir . '/index.php'; // creates an empty index.php file. $wp_filesystem->put_contents( $index_file_path, '', FS_CHMOD_FILE ); } // restores error handler. restore_error_handler(); while ( ( false !== $file = readdir( $dp ) ) ) { // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition -- false positive if ( is_dir( "$dir/$file" ) && '.' !== $file && '..' !== $file ) { self::add_index_file( "$dir/$file" ); } } closedir( $dp ); } /** * Add index file * * @param string|integer $form_id Form Id. * @param string $path Path. * * @return void */ public static function forminator_upload_index_file( $form_id, $path = '' ) { $form_id = absint( $form_id ); $upload_root = forminator_upload_root(); if ( ! is_dir( $upload_root ) ) { return; } self::check_upload_root_index_file(); if ( ! file_exists( forminator_get_upload_path( $form_id ) . 'index.php' ) ) { self::add_index_file( forminator_get_upload_path( $form_id ) ); } if ( ! file_exists( $path . 'index.php' ) ) { self::add_index_file( $path ); } } /** * Add htaccess file */ public static function add_htaccess_file() { global $wp_locale_switcher; // Return if $wp_locale_switcher is not ready. if ( ! $wp_locale_switcher ) { return false; } $upload_root = forminator_upload_root(); if ( ! is_dir( $upload_root ) ) { return; } if ( ! wp_is_writable( $upload_root ) ) { return; } $htaccess_file = $upload_root . '.htaccess'; if ( file_exists( $htaccess_file ) ) { wp_delete_file( $htaccess_file ); } $rules = '# Disable parsing of PHP for some server configurations. <Files *> SetHandler none SetHandler default-handler Options -ExecCGI Options -Indexes RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo </Files> <IfModule mod_php5.c> php_flag engine off </IfModule> <IfModule headers_module> Header set X-Robots-Tag "noindex" </IfModule>'; /** * A filter to allow the modification/disabling of parsing certain PHP * * @since 1.23.1 * * @param mixed $rules The Rules of what to parse or not to parse */ $rules = apply_filters( 'forminator_upload_root_htaccess_rules', $rules ); if ( ! empty( $rules ) ) { insert_with_markers( $htaccess_file, 'Forminator', $rules ); } } /** * Update metadata for uploaded file. * * @param int $attachment_id Attachment Id. * @param string $file File. * * @return void */ public static function generate_upload_metadata( $attachment_id, $file ) { require_once ABSPATH . 'wp-admin/includes/media.php'; require_once ABSPATH . 'wp-admin/includes/image.php'; // Generate and save the attachment metas into the database. wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) ); } }