Search code examples
wordpresswoocommerceproducthook-woocommerce

Print styled HTML as custom field output from admin meta box fields in WooCommerce


I have this code, based on Display custom field values of product variations to custom product tab in WooCommerce to display 3 custom field on WooCommerce variations.

In that fields I want to insert text with HTML tags and show it in shortcode with all HTML styling (tables etc...) but current code doesn't output styled text but raw text with printed HTML tags:

<div>some text etc...</div><a>some link</a>

Any suggestions what I did wrong here?

/* Add custom field input @ Product Data > Variations > Single Variation */
add_action( 'woocommerce_variation_options', 'add_custom_field_cage_code_to_variations', 10, 3 );
function add_custom_field_cage_code_to_variations( $loop, $variation_data, $variation ) {
    echo '<div class="cage_code_options_group options_group">';
        woocommerce_wp_text_input( array(
            'id' => 'cage_code[' . $loop . ']',
            'label' => __( 'One-line description', 'woocommerce' ),
            'value' => get_post_meta( $variation->ID, 'cage_code', true )
        ));

        woocommerce_wp_textarea_input( array(
            'id' => 'cage_code_part_number[' . $loop . ']',
            'label' => __( 'Short Description', 'woocommerce' ),
            'value' => get_post_meta( $variation->ID, 'cage_code_part_number', true )
        ));

        woocommerce_wp_textarea_input( array(
            'id' => 'cage_code_niin_nsn_number[' . $loop . ']',
            'label' => __( 'Long description', 'woocommerce' ),
            'value' => get_post_meta( $variation->ID, 'cage_code_niin_nsn_number', true )
        ));
    echo '</div>';
}

/* Save custom field on product variation save */
add_action( 'woocommerce_save_product_variation', 'magazine_save_custom_field_variations', 10, 2 );
function magazine_save_custom_field_variations( $variation_id, $i ) {
    $cage_code = $_POST['cage_code'][$i];
    if ( isset( $cage_code ) ) update_post_meta( $variation_id, 'cage_code', esc_attr( 
    $cage_code ) );

    $cage_code_part_number = $_POST['cage_code_part_number'][$i];
    if ( isset( $cage_code ) ) update_post_meta( $variation_id, 'cage_code_part_number', 
    esc_attr( $cage_code_part_number ) );

    $cage_code_niin_nsn_number = $_POST['cage_code_niin_nsn_number'][$i];
    if ( isset( $cage_code_niin_nsn_number ) ) update_post_meta( $variation_id, 
    'cage_code_niin_nsn_number', esc_attr( $cage_code_niin_nsn_number ) );
}

function woo_cage_code_info_tab_content() {
     global $product;
    
    if ( $product->is_type( 'variable' ) ) {
        
        // Loop through the variation IDs
        foreach( $product->get_children() as $key => $variation_id ) {
            // Get an instance of the WC_Product_Variation Object
            $variation = wc_get_product( $variation_id );
            
            // Get meta
            $cage_code = $variation->get_meta( 'cage_code' );
            $cage_code_part_number = $variation->get_meta( 'cage_code_part_number' );
            $cage_code_niin_nsn_number = $variation->get_meta( 
     'cage_code_niin_nsn_number' );
            
            // Output
            echo '<div class="woo_cage_code_info_tab_content 
     woo_cage_code_info_tab_content-' . $variation_id .'">';
            
            if ( $cage_code ) {
                echo '<p>' . $cage_code . '</p>';
            }
            
            echo '</div>';
        }
        ?>
        <script>
        jQuery(document).ready(function($) {
            // Hide all
            $( '.woo_cage_code_info_tab_content' ).css( 'display', 'none' );

            // Change
            $( 'input.variation_id' ).change( function() {
                // Hide all
                $( '.woo_cage_code_info_tab_content' ).css( 'display', 'none' );

                if( $( 'input.variation_id' ).val() != '' ) {
                    var var_id = $( 'input.variation_id' ).val();

                    // Display current
                    $( '.woo_cage_code_info_tab_content-' + var_id ).css( 'display', 'block' );
                }
            });    
        });
        </script>
        <?php
    }
}
add_shortcode('woo_cage_code_info_tab_content', 'woo_cage_code_info_tab_content');

Solution

  • Your code contains some minor mistakes. You can use woocommerce_wp_text_input() or woocommerce_wp_textarea_input() without issues.

    However, do not use esc_attr() when saving because it's for escaping HTML attributes (I assume that you as admin only have access to the backend fields) OR if you do use it, convert HTML entities back to characters at the output. In this answer I have used wp_kses_post() and wp_unslash()

    The woocommerce_admin_process_variation_object replaces the outdated woocommerce_save_product_variation hook

    So you get:

    // Add field(s)
    function action_woocommerce_variation_options( $loop, $variation_data, $variation ) {
        echo '<div class="cage_code_options_group options_group">';
    
            woocommerce_wp_text_input(
                array(
                    'id'    => 'cage_code[' . $loop . ']',
                    'label' => __( 'One-line description', 'woocommerce' ),
                    'value' => get_post_meta( $variation->ID, 'cage_code', true )
                )
            );
    
            woocommerce_wp_textarea_input(
                array(
                    'id'    => 'cage_code_part_number[' . $loop . ']',
                    'label' => __( 'Short Description', 'woocommerce' ),
                    'value' => get_post_meta( $variation->ID, 'cage_code_part_number', true )
                )
            );
    
            woocommerce_wp_textarea_input(
                array(
                    'id'    => 'cage_code_niin_nsn_number[' . $loop . ']',
                    'label' => __( 'Long description', 'woocommerce' ),
                    'value' => get_post_meta( $variation->ID, 'cage_code_niin_nsn_number', true )
                )
            );
    
        echo '</div>';
    }
    add_action( 'woocommerce_variation_options', 'action_woocommerce_variation_options', 10, 3 );
    
    // Save
    function action_woocommerce_admin_process_variation_object( $variation, $i ) {
        // Isset
        if ( isset( $_POST['cage_code'][$i] ) ) {
            // Store
            $cage_code = wp_kses_post( wp_unslash( $_POST['cage_code'][$i] ) );
    
            // Update
            $variation->update_meta_data( 'cage_code', $cage_code );
        }
    
        // Isset
        if ( isset( $_POST['cage_code_part_number'][$i] ) ) {
            // Store
            $cage_code_part_number = wp_kses_post( wp_unslash( $_POST['cage_code_part_number'][$i] ) );
    
            // Update
            $variation->update_meta_data( 'cage_code_part_number', $cage_code_part_number );
        }
    
        // Isset
        if ( isset( $_POST['cage_code_niin_nsn_number'][$i] ) ) {
            // Store
            $cage_code_niin_nsn_number = wp_kses_post( wp_unslash( $_POST['cage_code_niin_nsn_number'][$i] ) );
    
            // Update
            $variation->update_meta_data( 'cage_code_niin_nsn_number', $cage_code_niin_nsn_number );
        }
    }
    add_action( 'woocommerce_admin_process_variation_object', 'action_woocommerce_admin_process_variation_object', 10, 2 );
    

    Then I have no idea why you would use a shortcode versus a hook to render, like I did this in my answer. This can be any hook as long as it applies to the single product page:

    // Display
    function filter_woocommerce_product_tabs( $tabs ) {
        // Adds the new tab 
        $tabs['cage_code_information_tab'] = array(
            'title'     => __( 'Cage Code Information', 'woocommerce' ),
            'priority'  => 50,
            'callback'  => 'woo_cage_code_info_tab_content'
        );
    
        return $tabs;
    }
    add_filter( 'woocommerce_product_tabs', 'filter_woocommerce_product_tabs', 100, 1 );
    
    function woo_cage_code_info_tab_content() {
        global $product;
        
        if ( $product->is_type( 'variable' ) ) {
            
            // Loop through the variation IDs
            foreach( $product->get_children() as $key => $variation_id ) {
                // Get an instance of the WC_Product_Variation Object
                $variation = wc_get_product( $variation_id );
                
                // Get meta
                $cage_code = $variation->get_meta( 'cage_code' );
                $cage_code_part_number = $variation->get_meta( 'cage_code_part_number' );
                $cage_code_niin_nsn_number = $variation->get_meta( 'cage_code_niin_nsn_number' );
                
                // Output
                echo '<div class="woo_cage_code_info_tab_content woo_cage_code_info_tab_content-' . $variation_id .'">';
                
                if ( $cage_code ) {
                    echo '<p>Cage code: ' . $cage_code . '</p>';
                }
    
                if ( $cage_code_part_number ) {
                    echo '<p>Cage code part number: ' . $cage_code_part_number . '</p>';
                }
                
                if ( $cage_code_niin_nsn_number ) {
                    echo '<p>Cage code niin nsn_number: ' . $cage_code_niin_nsn_number . '</p>';
                }
                
                echo '</div>';
            }
            ?>
            <script>
            jQuery(document).ready(function($) {
                // Hide all
                $( '.woo_cage_code_info_tab_content' ).css( 'display', 'none' );
    
                // Change
                $( 'input.variation_id' ).change( function() {
                    // Hide all
                    $( '.woo_cage_code_info_tab_content' ).css( 'display', 'none' );
    
                    if( $( 'input.variation_id' ).val() != '' ) {
                        var var_id = $( 'input.variation_id' ).val();
    
                        // Display current
                        $( '.woo_cage_code_info_tab_content-' + var_id ).css( 'display', 'block' );
                    }
                });    
            });
            </script>
            <?php
        }
    }