2

In continuation of this question: Custom metabox content displayed in single product additional tabs on Woocommerce

When I use the following code from this answer:

And by this method, when I want to not show empty tabs, I get an error. I use the following code:

// Add a custom metabox
add_action( 'add_meta_boxes', 'additional_product_tabs_metabox' );
function additional_product_tabs_metabox()
{
    add_meta_box(
        'add_product_metabox_additional_tabs',
        __( 'Additional product Tabs', 'woocommerce' ),
        'additional_product_tabs_metabox_content',
        'product',
        'normal',
        'high'
    );
}

//  Add custom metabox content
function additional_product_tabs_metabox_content( $post )
{
    // Key Features
    echo '<h4>' . __( 'Key Features', 'woocommerce' ) . '</h4>';
    $value = get_post_meta( $post->ID, '_key_features', true );
    wp_editor( $value, '_key_features', array( 'editor_height' => 100 ) );


    // What News?
    echo '<br><hr><h4>' . __( 'What News?', 'woocommerce' ) . '</h4>';
    $value = get_post_meta( $post->ID, '_what_news', true );
    wp_editor( $value, '_what_news', array( 'editor_height' => 100 ) );


    // FAQ
    echo '<br><hr><h4>' . __( 'FAQ', 'woocommerce' ) . '</h4>';
    $value = get_post_meta( $post->ID, '_faq', true );
    wp_editor( $value, '_faq', array( 'editor_height' => 100 ) );


    // Nonce field (for security)
    echo '<input type="hidden" name="additional_product_tabs_nonce" value="' . wp_create_nonce() . '">';
}


// Save product data
add_action( 'save_post_product', 'save_additional_product_tabs', 10, 1 );
function save_additional_product_tabs( $post_id ) {

    // Security check
    if ( ! isset( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
        return $post_id;
    }

    //Verify that the nonce is valid.
    if ( ! wp_verify_nonce( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
        return $post_id;
    }

    // If this is an autosave, our form has not been submitted, so we don't want to do anything.
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return $post_id;
    }

    if ( ! current_user_can( 'edit_product', $post_id ) ) {
        return $post_id;
    }

    // Sanitize user input and save the post meta fields values.

    if( isset($_POST[ '_key_features' ]) )
        update_post_meta( $post_id, '_key_features', wp_kses_post($_POST[ '_key_features' ]) );

    if( isset($_POST[ '_what_news' ]) )
        update_post_meta( $post_id, '_what_news', wp_kses_post($_POST[ '_what_news' ]) );
    
    if( isset($_POST[ '_faq' ]) )
        update_post_meta( $post_id, '_faq', wp_kses_post($_POST[ '_faq' ]) );

}

add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
    
    $values = get_field('key_features_tab');
    if ( ! empty($values) ) { 
        $tabs['key_features_tab'] = array(
            'title'     => __( 'Key Features', 'woocommerce' ),
            'priority'  => 10,
            'callback'  => 'woo_key_features_tab_content'
        );
    }
    
    $what_news_values = get_field('what_news_tab');
    if ( ! empty($what_news_values) ) {
        $tabs['what_news_tab'] = array(
            'title'     => __( 'What News?', 'woocommerce' ),
            'priority'  => 20,
            'callback'  => 'woo_what_news_tab_content'
        );
    }
    
    $faq_values = get_field('faq_tab');
    if ( ! empty($faq_values) ) {
        $tabs['faq_tab'] = array(
            'title'     => __( 'FAQ', 'woocommerce' ),
            'priority'  => 30,
            'callback'  => 'woo_faq_tab_content'
        );
    }
    
    $tabs['reviews']['priority'] = 40;

    return $tabs;
}


function woo_key_features_tab_content()  {
    global $product;

    echo'<div><p>'. $product->get_meta( '_key_features' ) . '</p></div>';
}

function woo_what_news_tab_content()  {
    global $product;

    echo'<div><p>'. $product->get_meta( '_what_news' ) . '</p></div>';
}

function woo_faq_tab_content()  {
    global $product;

    echo'<div><p>'. $product->get_meta( '_faq' ) . '</p></div>';
}

Where is the problem in this code?

Another question is that I know that additional info is displayed when the product has weight, height, etc. Is it possible to delete the additional info tab forever because my products are virtual and I don't have a physical product. Also, can I create a tab called additional info that has nothing to do with WooCommerce's additional info tab?

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Adam Luper
  • 230
  • 9

1 Answers1

3

The problem is that you are using ACF get_field() function instead of the WooCommerce method get_meta() inside woo_custom_product_tabs() hooked function. Also, you are using the wrong meta keys.

So change it for:

add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
    global $product;

    $key_features = $product->get_meta('_key_features');
    if ( ! empty($key_features) ) { 
        $tabs['key_features_tab'] = array(
            'title'     => __( 'Key Features', 'woocommerce' ),
            'priority'  => 10,
            'callback'  => 'woo_key_features_tab_content'
        );
    }
    
    $what_news = $product->get_meta('_what_news');;
    if ( ! empty($what_news) ) {
        $tabs['what_news_tab'] = array(
            'title'     => __( 'What News?', 'woocommerce' ),
            'priority'  => 20,
            'callback'  => 'woo_what_news_tab_content'
        );
    }
    
    $faq_values = $product->get_meta('_faq');
    if ( ! empty($faq_values) ) {
        $tabs['faq_tab'] = array(
            'title'     => __( 'FAQ', 'woocommerce' ),
            'priority'  => 30,
            'callback'  => 'woo_faq_tab_content'
        );
    }
    
    $tabs['reviews']['priority'] = 40;

    return $tabs;
}

Now it should work as expected.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • 1
    As there is some JavaScript that is enabled on those tabs, I am not sure that it's a good idea. You can try by [overriding the WooCommerce template via your theme.](https://woocommerce.com/document/template-structure/). The related template file is: [single-product / tabs / tabs.php](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/templates/single-product/tabs/tabs.php). – LoicTheAztec Jun 22 '23 at 14:29
  • 1. When I save the values of the fields of custom tabs, the formatting of the values is lost, for example, if the contents are moved to the next line by pressing Enter, or if some HTML commands are used, such as the **
    ** tag, etc., only in the form of a simple text and Is this because of Sanitize user input? Can this problem be solved without reducing security? 2. If I am the site administrator myself and enter safe values, do I still need Sanitize? 3. Can I use **WYSIWYG** in the same code above? _Sorry, I wanted to ask these questions in a new, but I have a limit on new questions!_
    – Adam Luper Jun 22 '23 at 19:59
  • 1
    There is not really security issues on product backend pages, as editing products is restricted to admins and shop manager user roles. You can define which html tags you want to keep when sanitizing, making a custom sanitizing function ([see this post](https://stackoverflow.com/a/21238226/3730754)). – LoicTheAztec Jun 22 '23 at 20:22
  • Thanks, If I want to define all tags and standard values at once, how should I do it? That is, I want it to be exactly like the default (classic) WordPress editor (Product description), which accepts all standard values. – Adam Luper Jun 27 '23 at 06:26
  • Another question is, to remove Sanitize values I only need to remove wp_kses_post? Is this principled and standard work? – Adam Luper Jun 27 '23 at 06:27
  • 1
    Replace `wp_kses_post()` with `esc_html()` instead, for sanitization, allowing html without restrictions. – LoicTheAztec Jun 27 '23 at 06:38
  • In the main and default editors of WordPress and WooCommerce, when I press the Enter button and write the text on the next line, the text is displayed on the next line on the output page, but in the custom editors made by myself, this is not possible unless from I use the br tag, is there a solution to fix this problem? To be exactly like the main editor of WordPress itself? – Adam Luper Jun 29 '23 at 14:50
  • When I use `esc_html()` the values are only printed in the output and not executed. Am I making a mistake in executing the commands? – Adam Luper Jun 29 '23 at 14:51
  • I created a new question to explain in more detail: https://stackoverflow.com/questions/76570579 – Adam Luper Jun 29 '23 at 14:53