settings = $settings; // Loop through properties, save to instance. foreach ( $props as $prop => $value ) { // Handle default value. if ( $prop === 'value' ) { $this->default_value = $value; continue; } $this->{ $prop } = $value; } } /** * Register scripts to enqueue when displaying field. * * @since 2.5 * * @return array */ public function scripts() { return array(); } /** * Register styles to enqueue when displaying field. * * @since 2.5 * * @return array */ public function styles() { return array(); } // # RENDER METHODS ------------------------------------------------------------------------------------------------ /** * Render field. * * @since 2.5 * * @return string */ public function prepare_markup() { if ( isset( $this->callback ) && is_callable( $this->callback ) && self::$current_render_callback !== $this->callback ) { self::$current_render_callback = $this->callback; $html = call_user_func( $this->callback, $this, false ); self::$current_render_callback = false; } else { $html = $this->markup(); } // If field has nested fields, display. if ( ! empty( $this->fields ) ) { $html .= '
'; } return $html; } /** * Prepare field markup. * * @since 2.5 * * @return string */ public function markup() { return ''; } /** * Returns a set of HTML attributes to be added to the HTML element. * * @since 2.5 * * @param array $default Default set of attributes. * * @return array */ public function get_attributes( $default = array() ) { // Define default attributes. $default_atts = array( 'class' => '', 'default_value' => '', // Default value that should be selected or entered for the field. ); // Add additional default attributes. switch ( $this->type ) { case 'select': $default_atts['choices'] = array(); break; case 'checkbox': $default_atts['checked'] = false; $default_atts['checkbox_label'] = ''; $default_atts['choices'] = array(); break; default: break; } /** * Each nonstandard property will be extracted from the $props array so it is not auto-output in the field HTML * * @param array $field The current field meta to be parsed. */ $excluded_atts = apply_filters( 'gaddon_no_output_field_properties', array( 'default_value', 'label', 'toggle_label', 'choices', 'feedback_callback', 'checked', 'checkbox_label', 'value', 'type', 'validation_callback', 'hidden', 'tooltip', 'dependency', 'messages', 'name', 'args', 'exclude_field_types', 'field_type', 'after_input', 'input_type', 'icon', 'save_callback', 'enable_custom_value', 'enable_custom_key', 'merge_tags', 'key_field', 'value_field', 'callback', 'labels', 'input_types', 'settings', 'inputs', 'fields', 'no_choices', 'enhanced_ui', 'description' ), $this ); // Merge field properties with default attributes. $atts = wp_parse_args( $this, $default_atts ); $atts['id'] = rgempty( 'id', $atts ) ? rgar( $atts, 'name' ) : rgar( $atts, 'id' ); $atts['id'] = str_replace( '[]', null, $atts['id'] ); $atts['required'] = ( $atts['required'] === true ) ? 'required' : null; // Remove disabled property. if ( isset( $atts['disabled'] ) && $atts['disabled'] === false ) { unset( $atts['disabled'] ); } // Remove excluded attributes. foreach ( $atts as $key => $value ) { if ( in_array( $key, $excluded_atts ) ) { unset( $atts[ $key ] ); } } // Add default attributes. foreach ( $default as $key => $value ) { if ( isset( $atts[ $key ] ) ) { $atts[ $key ] = $value . $atts[ $key ]; } else { $atts[ $key ] = $value; } } // Prepare attributes as strings. $return = array(); foreach ( $atts as $att => $value ) { if ( ! in_array( $value, array( 'disabled', 'readonly' ) ) && ( is_callable( $value ) || empty( $value ) ) ) { continue; } $return[ $att ] = "{$att}='" . esc_attr( $value ) . "'"; } return $return; } /** * Parses the properties of a field choice and returns a set of HTML attributes to be added to the HTML element. * * @since 2.5 * * @param array $choice Field choice meta. * @param array $field_attributes Field attributes. * @param array $default_attributes Default attributes for choice. * * @return array */ public static function get_choice_attributes( $choice, $field_attributes = array(), $default_attributes = array() ) { // Use field attributes as a base for the choice attributes. $atts = $field_attributes; // Loop through each choice property, add to the attributes. foreach ( $choice as $prop => $value ) { // Choice properties to remove. $excluded_atts = array( 'default_value', 'label', 'checked', 'value', 'type', 'validation_callback', 'required', 'tooltip', 'icon' ); if ( $prop === 'disabled' && $value === false ) { unset( $atts[ $prop ] ); } elseif ( in_array( $prop, $excluded_atts ) || is_array( $value ) ) { unset( $atts[ $prop ] ); } else { $atts[ $prop ] = "{$prop}='" . esc_attr( $value ) . "'"; } } // Adding default attributes: create new attribute or prepend to existing. foreach ( $default_attributes as $attr_name => $attr_value ) { if ( isset( $atts[ $attr_name ] ) ) { $atts[ $attr_name ] = str_replace( "{$attr_name}='", "{$attr_name}='{$attr_value}", $atts[ $attr_name ] ); } else { $atts[ $attr_name ] = "{$attr_name}='" . esc_attr( $attr_value ) . "'"; } } return $atts; } /** * Get describer element(s) for field. * * @since 2.5 * * @return string */ public function get_describer() { // Prepare error and description IDs. $error_id = sprintf( 'error-%s', esc_attr( $this->name ) ); $description_id = $this->get_description() ? sprintf( 'description-%s', esc_attr( $this->name ) ) : ''; return $this->get_error() ? implode( ', ', array( $error_id, $description_id ) ) : $description_id; } /** * Renders the description text for a field. * * @since 2.5 * * @return string */ public function get_description() { return isset( $this->description ) ? sprintf( '%s', $this->name, $this->description ) : ''; } /** * Gets the classes to apply to the field container. * * @since 2.5 * * @return string */ public function get_container_classes() { // Prepare feedback. $error = $this->get_error(); $is_invalid = ! empty( $error ); $value = $this->get_value(); $is_feedback_valid = null; // Prepare container classes. $feedback_callback = ( $this->type == 'text' ) ? rgar( $this, 'feedback_callback' ) : null; if ( is_callable( $feedback_callback ) ) { $is_feedback_valid = call_user_func_array( $feedback_callback, array( $value, $this ) ); } $container_classes = array( 'gform-settings-input__container' ); if ( is_bool( $is_feedback_valid ) ) { $container_classes[] = $is_feedback_valid ? 'gform-settings-input__container--feedback-success' : 'gform-settings-input__container--feedback-error'; } if ( is_string( $is_feedback_valid ) ) { $container_classes[] = sprintf( 'gform-settings-input__container--feedback-%s', $is_feedback_valid ); } if ( $is_invalid ) { $container_classes[] = 'gform-settings-input__container--invalid'; } if ( isset( $this->append ) ) { $container_classes[] = 'gform-settings-input__container--with-append'; } if ( strpos( $this->class, 'merge-tag-support' ) !== false ) { $container_classes[] = 'gform-settings-input__container--with-merge-tag'; } return implode( ' ', $container_classes ); } /** * Determines if any of the available field choices have an icon. * * @since 2.5 * * @param array $choices * * @return bool */ public static function has_icons( $choices = array() ) { foreach ( $choices as $choice ) { if ( rgar( $choice, 'icon' ) ) { return true; } } return false; } /** * Determines if any of the available field choices have a tag. * * @since 2.5.6.4 * * @param array $choices * * @return bool */ public static function has_tag( $choices = array() ) { foreach ( $choices as $choice ) { if ( rgar( $choice, 'tag' ) ) { return true; } } return false; } // # VALIDATION METHODS -------------------------------------------------------------------------------------------- /** * Validate posted field value. * Run defined callback. * * @since 2.5 * * @deprecated Deprecated since 2.5-beta-3. Use handle_validation() instead. * * @param array|bool|string $value Posted field value. */ public function validate( $value ) { _deprecated_function( __METHOD__, '2.5-beta-3', '\Gravity_Forms\Gravity_Forms\Settings\Fields\Base::handle_validation()' ); $this->handle_validation( $value ); } /** * Validate posted field value. * Run defined callback. * * @since 2.5-beta-3 * * @param array|bool|string $value Posted field value. */ public function handle_validation( $value ) { // If field has a custom validation callback, call it. if ( is_callable( $this->validation_callback ) ) { call_user_func( $this->validation_callback, $this, $value ); return; } if ( is_callable( $this->legacy_validation_callback ) ) { call_user_func( $this->legacy_validation_callback, $this, $this->settings->get_posted_values() ); return; } // Validate field. $this->do_validation( $value ); } /** * Validate posted field value. * * @since 2.5 * * @deprecated Deprecated since 2.5-beta-3 - use do_validation() instead. * * @param array|bool|string $value Posted field value. */ public function is_valid( $value ) { _deprecated_function( __METHOD__, '2.5-beta-3', '\Gravity_Forms\Gravity_Forms\Settings\Fields\Base::do_validation()' ); $this->do_validation( $value ); } /** * Validate posted field value. * * @since 2.5-beta-3 * * @param array|bool|string $value Posted field value. */ public function do_validation( $value ) { // If field is required and value is empty, set error. if ( $this->required && rgblank( $value ) ) { $this->set_error( rgobj( $this, 'error_message' ) ); } } /** * Determine if the current choice is a match for the submitted field value. * * @since 2.5 * * @param array $choice The choice properties. * @param string|array $value The submitted field value. * * @return bool */ public static function is_choice_valid( $choice, $value ) { $choice_value = isset( $choice['value'] ) ? $choice['value'] : $choice['label']; return is_array( $value ) ? in_array( $choice_value, $value ) : $choice_value == $value; } /** * Get error message for field. * * @since 2.5 * * @return string */ public function get_error() { return $this->error; } /** * Gets the validation error icon. * * @since 2.5 * * @return string */ public function get_error_icon() { // Get field error. $error = $this->get_error(); return $error ? sprintf( '