• Resolved LasseMT

    (@lassemt)


    Hi!
    I’m creating a custom field so I can specify allergies in a dish. What I want to create is something like this:

    Allergy 1 (e.g. Gluten)
    — Checkbox (on/off) — Text input (Specify type of gluten e.g. kind of flour ect.) —

    Allergy 2 (e.g. Nuts)
    — Checkbox (on/off) — Text input (Type of nuts) —

    — And so on.. —

    Currently my code looks like this:

    function cmb2_render_dish_allergies( $field, $value, $object_id, $object_type, $field_type ) {
    
        // make sure we specify each part of the value we need.
        $value = wp_parse_args( $value, array(
            'gluten' => '',
            'nuts' => '',
        ) );
    
        ?>
        <ul>
    	    <li>
    	    	<label for="<?php echo $field_type->_id( '_gluten_bool' ); ?>"><?php _e('Gluten', 'textdomain'); ?></label>
    	        <?php echo $field_type->checkbox( array(
    	            'name'  => $field_type->_name( '[gluten][bool]' ),
    	            'id'    => $field_type->_id( '_gluten_bool' ),
    	            'value' => 'on',
    	            'desc'  => '',
    	        ) ); ?>	    
    
    	        <?php echo $field_type->input( array(
    	        	'name'  => $field_type->_name( '[gluten][type]' ),
    				'id'    => $field_type->_id( '_gluten_type' ),
    				'value' => $value['gluten']['type'],
    				'desc'  => '',
    			) ); ?>
    	    </li>
    
    	    <li>
    	    	<label for="<?php echo $field_type->_id( '_nuts_bool' ); ?>"><?php _e('nuts', 'textdomain'); ?></label>
    	        <?php echo $field_type->checkbox( array(
    	            'name'  => $field_type->_name( '[nuts][bool]' ),
    	            'id'    => $field_type->_id( '_nuts_bool' ),
    	            'value' => 'on',
    	            'desc'  => '',
    	        ) ); ?>	    
    
    	        <?php echo $field_type->input( array(
    	        	'name'  => $field_type->_name( '[nuts][type]' ),
    				'id'    => $field_type->_id( '_nuts_type' ),
    				'value' => $value['nuts']['type'],
    				'desc'  => '',
    			) ); ?>
    	    </li>
        </ul>
    
        <br class="clear">
        <?php
        echo $field_type->_desc( true );
    
    }
    add_filter( 'cmb2_render_dish_allergies', 'cmb2_render_dish_allergies', 10, 5 );

    When saving I get the error message: “Notice: Array to string conversion in /www.example.dev/wordpress/wp-includes/formatting.php on line 1025”. I think this might be a problem because the array I’m trying to save is not sanitized?

    I’m quite new to using custom fields in CMB2 and sanitising/escaping ect. and was hoping some of you guys could explain me how to solve this?

    https://wordpress.org/plugins/cmb2/

Viewing 10 replies - 1 through 10 (of 10 total)
  • Plugin Author Justin Sternberg

    (@jtsternberg)

    Not sure using a custom field is necessary if Allergy 1, 2, etc are just repeated fields. For that I would use a repeatable field group: https://github.com/WebDevStudios/CMB2/blob/master/example-functions.php#L388-L452

    If you’re looking to do a custom field w/ multiple inputs, you should follow this documentation: https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-field-types#example-4-multiple-inputs-one-field-lets-create-an-address-field

    Thread Starter LasseMT

    (@lassemt)

    Thank you for you reply Justin 🙂

    I don’t want to use repeatable fields, because I want the field to be static (not repeatable and the repeatable fields does not support checkbox. I used the custom field w/ multiple inputs to create my my custom field, but I need a way to sanitise my custom field.

    I basically want to create something like this:

    <ul>
    	    <li>
    	    	<input type="checkbox" name="[gluten][bool]" id="gluten_bool" value="on" />
    	    	<input type="text" name="[gluten][type]" id="gluten_type" value="e.g. Wheat gluten" />
    	    </li>
    
    	    <li>
    	    	<input type="checkbox" name="[nuts][bool]" id="nuts_bool" value="on" />
    	    	<input type="text" name="[nuts][type]" id="nuts_type" value="e.g. Walnuts" />
    	    </li>	  
    
    	    <li>
    			And so on..
    	    </li>
        </ul>

    Where checkbox determine if the allergy should be outputted on front-page and the text input is the “NEW Value” that specifies the allergy more. So if the checkbox is checked and the text input has no value, it will output a standard value set for the allergy.

    Here is an var_dump of an example $meta_value that is being sent to my custom cmb2_sanitize function:

    array(2) {
    	["gluten"]=> array(2) {
    		["bool"]=> string(2) "on"
    		["type"]=> string(12) "Wheat gluten"
    	}
    	["nuts"]=> array(2) {
    		["bool"]=> string(2) "on"
    		["type"]=> string(0) ""
    	}
    }

    How should I sanitise this information, so it can be saved with CMB2?

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    LasseMT I’m a little confused when you say “sanitize” here. It sounds like you’re wanting to conditionally check the saved value and use the state of the meta data to determine what to output on the frontend. Or is this something you’re needing to do at that time of saving to the database?

    Thread Starter LasseMT

    (@lassemt)

    Michael Beckwith Thank you for taking your time to help me, and I’m sorry I confused you with my bad explanation 🙂

    It is something I need to do at that time of saving to the database. I might be of the chart by calling it “sanitization” (not sure if I have used the right word), but I want to make the array “clean” so it can be stored to the database.

    The text inputs (not the checkbox) are saved when escape_cb and sanitization_cb is set to false. When I set escape_cb and sanitization_cb to true, I get the error message “Array to string conversion in http://www.example.dev/wordpress/wp-includes/formatting.php on line 1025”. Thats why I thought I needed to bypass the CMB sanitization methods with my own callback.

    So I’m asking if someone could explain me how to handle an array like this:

    array(2) {
    	["gluten"]=> array(2) {
    		["bool"]=> string(2) "on"
    		["type"]=> string(12) "Wheat gluten"
    	}
    	["nuts"]=> array(2) {
    		["bool"]=> string(2) "on"
    		["type"]=> string(0) ""
    	}
    }

    in a custom sanitization callback. I will probably need to create a custom escaping callback as well.

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    In this case, you are right. If it was something being done on the frontend and output to the screen that wouldn’t be the right word. You’re needing to handle things before saving to the database, so it is accurate.

    I’ll chime in a bit later when I have time to sit down and think it through some more, and try to provide a more complete answer.

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Can you pastebin the complete block you’re using for this? I want to tinker around and see what’s going on here.

    From the looks of the error you pasted above, it’s a case of passing in an array to the wp_check_invalid_utf8() function, whether directly or through a chain of function calls.

    Thread Starter LasseMT

    (@lassemt)

    Michael Beckwith Here is what I got for now in a pastebin: http://pastebin.com/bKE1jZv3. Currently my sanitize functions is empty because there have been no results in my different tries.

    Btw, thank you again for taking a look on this! Do you have a donation link, where I can buy you a beer or two? 🙂

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    Can you also pastebin the metabox setup? This looks like half of what would be needed to recreate.

    Not sure about any donation links for CMB2, and I won’t take direct donations. Especially since it’s not me doing most of the work on CMB2

    Thread Starter LasseMT

    (@lassemt)

    Here is an updated pastebin. The metabox setup is in the bottom of the pastebin.

    http://pastebin.com/BgEu8P8U

    Plugin Contributor Michael Beckwith

    (@tw2113)

    The BenchPresser

    After about an hour of tinkering, I think this will get you back on a good foot forward, and you can work on your render callback more with preserved values.

    I found that I was able to get the preserved values into the render callback by setting the escape_cb to false if you want to bypass completely, though you probably should escape as attributes, using esc_attr(). The other part is the sanitization_cb parameter. If none are provided for either one, then my digging through the CMB2 source code showed that it always fell back to sanitize_text_field() for the security, and that caused the arrays to be cast as string and just stored “Array” as the value.

    I’d personally recommend using both ‘escape_cb’ and ‘sanitization_cb’ and just provide a function name for the callbacks. In the callbacks, loop over passed in values and sanitize each index, before reconstructing the same array structure and returning.

    Examples:

    $test_metabox->add_field( array(
    	'name' => __( 'Allergier', 'textdomain' ),
    	'desc' => __( '', 'textdomain' ),
    	'id'   => $prefix . 'allergies_test',
    	'type' => 'dish_allergies',
    	'escape_cb' => 'barfoo',
    	'sanitization_cb' => 'foobar',
    ) );
    function foobar( $a, $b, $c ) {
    	// Sanitize here.
    	return $a;
    }
    function barfoo( $a, $b, $c, ) {
    	// Escape here.
    	return $a;
    }

    The first parameter in both are going to be the values submitted. In your example, an array of arrays, the first being ‘gluten’ storing it’s own array of the bool checkbox and the type, and repeated for the ‘nuts’ index.

    The second parameter looks like an object holding the field type info, the third parameter would be the CMB2_Field instance with a bit more info available to you. Likely only really need the first parameter unless you need to conditionally apply things. You would also be able to get rid of the cmb2_sanitize_dish_allergies add_filter line, as all my testing never ended up reaching that once I provided the sanitization_cb parameter. Just provide the same callback function name in that spot in the add_field().

Viewing 10 replies - 1 through 10 (of 10 total)

The topic ‘Sanitising multiple inputs in one field. (multidimensional array)’ is closed to new replies.