Support

Account

Home Forums ACF PRO Escaping & in text fields

Solving

Escaping & in text fields

  • I have an issue with character limits on text fields.
    My character limits are set by using John Huebner’s plugin ACF Input Counter (the plugin has nothing to do with the error).

    An & (ampersand) gets ‘changed’ (by ACF) to & when it’s saved, which is of course understandable, because it’s an unsafe character.

    BUT the problem is, when you use a & character and reach the character limit, you can’t save it, because on save 4 characters are added and thus the length of the string is too long.

    I tried to ‘not escape’ an & with kses but this didn’t work. Does anyone know a way how to do this ?

  • I think the validate value function in the text and textarea field classes need to be modified to add html_entity_decode() to the value before checking the length.

  • This is my function now.

    function pg_check_html_tags_text( $value, $post_id, $field ) {
        
        if ( $value != strip_tags( $value ) ) {
            $allowed_tags = array();
            $value        = wp_kses( $value, $allowed_tags );
        }
        
        return $value;
        
    }
    add_filter( 'acf/update_value/type=text', 'pg_check_html_tags_text', 10, 3 );

    Could it be ‘fixed’ by adding $value = html_entity_decode( $value ); before if ( $value != strip_tags( $value ) ) { ?

  • I think you need to let Elliot know about this https://www.advancedcustomfields.com/contact/

    This is the function in both the text and textarea fields that I thing is causing the issue, although I could be wrong

    
    
    	
    	/**
    	 * validate_value
    	 *
    	 * Validates a field's value.
    	 *
    	 * @date	29/1/19
    	 * @since	5.7.11
    	 *
    	 * @param	(bool|string) Whether the value is vaid or not.
    	 * @param	mixed $value The field value.
    	 * @param	array $field The field array.
    	 * @param	string $input The HTML input name.
    	 * @return	(bool|string)
    	 */
    	function validate_value( $valid, $value, $field, $input ){
    		
    		// Check maxlength
    		if( $field['maxlength'] && mb_strlen(wp_unslash($value)) > $field['maxlength'] ) {
    			return sprintf( __('Value must not exceed %d characters', 'acf'), $field['maxlength'] );
    		}
    		
    		// Return.
    		return $valid;
    	}
    
  • Ok.. gotcha… will shoot him an email…

  • I ran into this issue today. I sent a support ticket in with some more details. Just wanted to add on here.

    If you have a standard text input with a maxlength, it appears to be validating the string length after encoding HTML entities. That means an & character counts as 5 characters (& a m p ;).

    Unfortunately I couldn’t think of a “clean” solution that doesn’t override all other types of validations. The best I came up with is based on checking if the validation error contains the text “Value must not exceed” – which won’t work if the message changes or if your site is in another language.

    Below is my solution with those limitations in mind. It “fixes” regular text fields and also multi-line textareas. You can just remove the last line if you want to validate textareas normally.

    /**
     * Correct max length validation failures caused by html entities like & and < for text inputs.
     * 
     * @param string|true $valid
     * @param string $value
     * @param array $field
     * @param string $input_name
     *
     * @return string|true
     */
    function rs_fix_acf_length_validation( $valid, $value, $field, $input_name ) {
    	if ( is_string($valid) && strpos($valid, 'Value must not exceed') === 0 ) {
    		if ( !isset($field['maxlength']) ) return $valid; // maxlength should  be present here
    		
    		// decode html entities (& -> &). particularly: &, <, >, ", '
    		$decoded_value = wp_specialchars_decode( $value );
    		
    		// get new string length
    		$decoded_length = mb_strlen(wp_unslash( $decoded_value ));
    		
    		// if the decoded string length fits within the max length, override the validtion.
    		if ( $decoded_length <= $field['maxlength'] ) $valid = true;
    	}
    	return $valid;
    }
    add_filter( 'acf/validate_value/type=text', 'rs_fix_acf_length_validation', 20, 4 ); // Text and Textarea both support maxlength, as of ACF 5.8.11
    add_filter( 'acf/validate_value/type=textarea', 'rs_fix_acf_length_validation', 20, 4 );
  • I ran into this issue today. I sent a support ticket in with some more details. Just wanted to add on here.

    If you have a standard text input with a maxlength, it appears to be validating the string length after encoding HTML entities. That means an & character counts as 5 characters (& a m p ;).

    Unfortunately I couldn’t think of a “clean” solution that doesn’t override all other types of validations. The best I came up with is based on checking if the validation error contains the text “Value must not exceed” – which won’t work if the message changes or if your site is in another language.

    Below is my solution with those limitations in mind. It “fixes” regular text fields and also multi-line textareas. You can just remove the last line if you want to validate textareas normally.

    /**
     * Correct max length validation failures caused by html entities like & and < for text inputs.
     * 
     * @param string|true $valid
     * @param string $value
     * @param array $field
     * @param string $input_name
     *
     * @return string|true
     */
    function rs_fix_acf_length_validation( $valid, $value, $field, $input_name ) {
    	if ( is_string($valid) && strpos($valid, 'Value must not exceed') === 0 ) {
    		if ( !isset($field['maxlength']) ) return $valid; // maxlength should  be present here
    		
    		// decode html entities (& -> &). particularly: &, <, >, ", '
    		$decoded_value = wp_specialchars_decode( $value );
    		
    		// get new string length
    		$decoded_length = mb_strlen(wp_unslash( $decoded_value ));
    		
    		// if the decoded string length fits within the max length, override the validtion.
    		if ( $decoded_length <= $field['maxlength'] ) $valid = true;
    	}
    	return $valid;
    }
    add_filter( 'acf/validate_value/type=text', 'rs_fix_acf_length_validation', 20, 4 ); // Text and Textarea both support maxlength, as of ACF 5.8.11
    add_filter( 'acf/validate_value/type=textarea', 'rs_fix_acf_length_validation', 20, 4 );

    (Sorry if this is a repost, my other comment seems to have disappeared?)

  • Hi @radgh your message seemed gone for me too.
    I clicked the link in the notification email shortly and it was nowhere to be found.

    I won’t be able to test your solution for at least a week due to a full (client) schedule but I’ll be sure to come back to it, if Eliot hasn’t piled on in the meanwhile 🙂

Viewing 8 posts - 1 through 8 (of 8 total)

The topic ‘Escaping & in text fields’ is closed to new replies.