1

I have managed to add a custom text area to the woocommerce product data where my client can add in a kit list that is output to the packing list for the shop floor but the line breaks don't save and the output is a flow of text making it less easy on the eye for the guys picking This is what I have but where and how do I make it preserve the line breaks added in the admin suite to output on the packing slip:

//General Fields
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields',10,3 
);
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save',10,2 );
//variable data
add_action('woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3);
add_action('woocommerce_save_product_variation','save_variation_settings_fields',10, 2);

//data tab

add_action( 'woocommerce_product_data_panels', 'add_my_custom_product_data_fields',10,3 );
add_action( 'woocommerce_process_product_meta','woocommerce_process_product_meta_fields_save',10,2 );
function woo_add_custom_general_fields() {

global $woocommerce, $post;

// Textarea
woocommerce_wp_textarea_input(
  array(
    'id'          => '_textarea[' . $post->ID . ']',
    'label'       => __( 'Kit List', 'woocommerce' ),
    'placeholder' => '',
    'description' => __( 'Enter the kit list here.', 'woocommerce' ),
    'value'       => get_post_meta( $post->ID, '_textarea', true ),
  )
);
 }

function woo_add_custom_general_fields_save( $post_id ){


// Textarea
$textarea = $_POST['_textarea'][ $post_id ];
if( ! empty( $textarea ) ) {
update_post_meta( $post_id, '_textarea', esc_attr( $textarea ) );
}

}



function variation_settings_fields($loop, $variation_data, $variation){

// Textarea
woocommerce_wp_textarea_input(
  array(
    'id'          => '_textarea[' . $variation->ID . ']',
    'label'       => __( 'Kit List', 'woocommerce' ),
    'placeholder' => '',
    'description' => __( 'Enter the kit list here.', 'woocommerce' ),
    'value'       => get_post_meta( $variation->ID, '_textarea', true ),
  )
);
}
function save_variation_settings_fields($post_id){

// Textarea
 $textarea = $_POST['_textarea'][ $post_id ];
if( ! empty( $textarea ) ) {
update_post_meta( $post_id, '_textarea', esc_attr( $textarea ) );
}


}
add_action( 'wpo_wcpdf_after_item_meta', 'wpo_wcpdf_product_custom_field', 10, 3 );
function wpo_wcpdf_product_custom_field ( $template_type, $item, $order ) {
if ( $template_type == 'packing-slip' ) {
   // check if product exists first
    if (empty($item['product'])) return;

    // replace 'Location' with your custom field name!
    $field_name = '_textarea';
    $textarea = method_exists($item['product'], 'get_meta') ? $item['product']
    ->get_meta($field_name,true,'edit') : get_post_meta( $item['product']->id, $field_name, true );
    if (!empty($textarea)) {
        echo nl2br('Kit List: '.$textarea.'');  
    }
     }
    }
  • Hello Lisa Lawton, welcome to SO! Your question is in general quite detailed, the embedded code snippet is a nice touch - however, for me, it is not clear what your desired result looks like. Could you please elaborate more on that? – Andrew Adam Jan 16 '20 at 15:47
  • Hi I want the output of the textarea field to preserve the line breaks added - the text area is to output only on the packing slip. Basically the client adds a list using carriage breaks to the custom text area in woocommerce product data and it outputs into list format - however at the moment it is only outputting as one long line of text - hope this makes sense – Lisa Lawton Jan 20 '20 at 11:09
  • Hello Lisa, does any of these help?: https://stackoverflow.com/questions/30593103/preserve-line-breaks-in-textarea https://stackoverflow.com/questions/40417527/how-do-i-preserve-line-breaks-when-getting-text-from-a-textarea/40426477 https://stackoverflow.com/questions/498461/how-to-save-user-entered-line-breaks-from-a-textarea-to-a-database/48680684 – Andrew Adam Jan 20 '20 at 11:31
  • 1
    Thanks, I've read all of these a million times and cannot fathom where to wrap the output in
     as I am rubbish at code, I basically cobble together from snippets I find until something works.
    – Lisa Lawton Jan 20 '20 at 15:21
  • 1
    finally sussed it and replaced echo '
    Kit List: '.$_textarea.'
    '; with echo nl2br('Kit List: '.$textarea.''); I have edited my above code just in case this helps anyone else
    – Lisa Lawton Jan 20 '20 at 15:27
  • I am glad you could resolve the issue. If you want to help others then it is absolutely okay to answer your own question with a solution. I'd suggest you write an answer here with details on how you resolved it, why you chose nl2br, etc. And again: welcome to the community! – Andrew Adam Jan 20 '20 at 15:31

1 Answers1

0

That trouble in function wc_clean - it used to get value and always use _sanitize_text_fields( $str, false ), so regardless of field type, woo removes trailing characters :( See trace below:

In may situation (Need additional field in address), I found it in form edit address.

#/wp-content/plugins/woocommerce/templates/myaccount/form-edit-address.php:38

woocommerce_form_field( $key, $field, wc_get_post_data_by_key( $key, $field['value'] ) );

where wc_get_post_data_by_key function return cleaned data by wc_clean

#/wp-content/plugins/woocommerce/includes/wc-core-functions.php:2005

return wc_clean( wp_unslash( wc_get_var( $_POST[ $key ], $default ) ) ); // @codingStandardsIgnoreLine

that use satinize text

#/wp-content/plugins/woocommerce/includes/wc-formatting-functions.php:392

return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;

where not keep_newlines set (by default it is false):

#WordPress/wp-includes/formatting.php:5244

$filtered = _sanitize_text_fields( $str, false );

Thus, there are no line breaks in all data of any type received by the function wc_get_post_data_by_key()

#WordPress/wp-includes/formatting.php:5317

if ( ! $keep_newlines ) {
    $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
}

Solution (?)

the solution is cardinal - leave line breaks for all text fields similar to sanitize_textarea_field ():


add_filter( 'sanitize_text_field',  function ( $filtered, $str ) {
        return _sanitize_text_fields( $str, true );
    }
, 10, 2 );


MrSwed
  • 559
  • 8
  • 15