phpwordpresswoocommercecustom-fieldswebinar

Replace WooCommerce add to cart button depending on purchased product custom field


In WooCommerce, I have added a custom product type to sale Google meet webinars.

I have been really working hard on it, but I didn’t get it fixed!

I still have the following problems:

  1. The “Thank You” page is actually crashing.
  2. After purchasing the product, the add to cart button is not replaced by "join the webinar" text.

Any help is appreciated.

My code so far:

// Add Google Meet link field
function custom_add_google_meet_link_field() {
    echo '<div class="options_group">';
    woocommerce_wp_text_input(
        array(
            'id' => 'google_meet_link',
            'label' => __('Google Meet Link', 'text-domain'),
            'placeholder' => 'Enter Google Meet Link',
            'desc_tip' => 'true',
            'description' => __('Add your Google Meet link.', 'text-domain')
        )
    );
    echo '</div>';
}
add_action('woocommerce_product_options_general_product_data', 'custom_add_google_meet_link_field');

// Save Google Meet link field data
function custom_save_google_meet_link_field_data($product_id) {
    $google_meet_link = isset($_POST['google_meet_link']) ? sanitize_text_field($_POST['google_meet_link']) : '';
    update_post_meta($product_id, 'google_meet_link', $google_meet_link);
}
add_action('woocommerce_process_product_meta', 'custom_save_google_meet_link_field_data');

// Display Google Meet link on order details and thank you page (clickable)
function custom_display_google_meet_link($order) {
    $order_id = method_exists($order, 'get_id') ? $order->get_id() : $order->id;
    $items = $order->get_items();

    foreach ($items as $item) {
        $product_id = $item['product_id'];
        $google_meet_link = get_post_meta($product_id, 'google_meet_link', true);

        if (!empty($google_meet_link)) {
            echo '<h3>' . __('Google Meet Link:', 'text-domain') . '</h3>';
            echo '<p><a href="' . esc_url($google_meet_link) . '">' . esc_html($google_meet_link) . '</a></p>';
        }
    }
}
add_action('woocommerce_order_details_after_order_table', 'custom_display_google_meet_link', 10, 1);
add_action('woocommerce_thankyou', 'custom_display_google_meet_link', 10, 1);

// Change "Add to Cart" button to "Join Webinar"
function custom_change_add_to_cart_button($button_text, $product) {
    if ($product->get_type() === 'google_meet_webinar' && $product->is_purchasable()) {
        $button_text = __('Join Webinar', 'text-domain');
    }
    return $button_text;
}
add_filter('woocommerce_product_single_add_to_cart_text', 'custom_change_add_to_cart_button', 10, 2);
add_filter('woocommerce_product_add_to_cart_text', 'custom_change_add_to_cart_button', 10, 2);

Solution

  • I have revisited your code nearly completely and managed to fix your issues.

    For the add to cart button of the purchased product by the user, it's now replaced by a similar custom button "join the webinar" linked to the Google webinar.

    The revisited code (updated):

    // Admin Product - Add Google Meet link field
    add_action('woocommerce_product_options_general_product_data', 'add_google_meet_link_custom_field');
    function add_google_meet_link_custom_field() {
        echo '<div class="options_group">';
    
        woocommerce_wp_text_input( array(
            'id'            => 'google_meet_link',
            'label'         => __('Google Meet Link', 'text-domain'),
            'placeholder'   => 'Enter Google Meet Link',
            'desc_tip'      => 'true',
            'description'   => __('Add your Google Meet link.', 'text-domain')
        ) );
    
        echo '</div>';
    }
    
    // Admin Product - Save Google Meet link field data
    add_action('woocommerce_admin_process_product_object', 'save_google_meet_link_custom_field');
    function save_google_meet_link_custom_field( $product ) {
        if ( isset($_POST['google_meet_link']) ) {
            $product->update_meta_data( 'google_meet_link', sanitize_url($_POST['google_meet_link']) );
        } 
    }
    
    // Display Google Meet link on order details and thank you page (clickable)
    add_action('woocommerce_order_details_after_order_table', 'display_google_meet_link_custom_field_value', 10, 1);
    function display_google_meet_link_custom_field_value( $order ) {
        $has_link = false;
        $html     = '';
    
        foreach ( $order->get_items() as $item ) {
            $product = $item->get_product();
            $google_meet_link = $product->get_meta('google_meet_link');
    
            if ( $google_meet_link ) {
                $html .= '<p><a href="' . esc_url($google_meet_link) . '">' . esc_html($google_meet_link) . '</a></p>';
                $has_link = true;
            }
        }
        
        if ( $has_link ) {
            echo '<h3>' . __('Google Meet Link:', 'text-domain') . '</h3>';
            echo $html;
        }
    }
    
    // Function that check if the webinar link exist or return webinar link
    function get_webinar_link( $product, $conditional = false ) {
        $link = $product->get_meta('google_meet_link');
    
        if ( $conditional ) {
            return ! $link ? false : true;
        } else {
            return $link;
        }
    }
    
    // The custom replacement button function
    function join_webinar_button( $product = null ){
        if ( ! $product ) global $product;
    
        // HERE your custom button text and link
        $button_text = __('Join Webinar', 'woocommerce');
        $button_link = get_webinar_link( $product );
        
        // Display button
        echo '<a class="button webinar-on" href="'.$button_link.'">' . $button_text . '</a>';
    }
    
    
    // Function that check if the current product has been purchased by the customer
    function has_purchased_product( $product_id = null, $user_id = null ) {
        global $wpdb;
    
        $product_id = ! $product_id ? get_the_ID() : $product_id;
        $user_id = ! $user_id ? get_current_user_id() : $user_id;
    
        // Returns an array of product Ids reviewed by the customer
        return $wpdb->get_var( "
            SELECT  COUNT( opl.order_item_id )
            FROM {$wpdb->prefix}wc_order_product_lookup as opl
            INNER JOIN {$wpdb->prefix}postmeta as pm ON pm.post_id = opl.order_id 
            WHERE pm.meta_key = '_customer_user' AND pm.meta_value = '{$user_id}' 
                AND opl.product_id = '{$product_id}'
        " );
    }
    
    // Replacing single product button add to cart by a custom button
    add_action( 'woocommerce_single_product_summary', 'replace_single_add_to_cart_button', 1 );
    function replace_single_add_to_cart_button() {
        global $product;
    
        // Targeting our product type and checking that the product is purchased by user
        if ( $product->is_type( 'simple' ) && get_webinar_link( $product, true ) && // 'google_meet_webinar'
            has_purchased_product( $product->get_id() ) ) 
        {
            remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
             add_action( 'woocommerce_single_product_summary', 'join_webinar_button', 30 );
        }
    }
    
    // Shop and archives pages: Replacing add to cart button by a link to the product
    add_filter( 'woocommerce_loop_add_to_cart_link', 'replace_loop_add_to_cart_button', 10, 2 );
    function replace_loop_add_to_cart_button( $button, $product  ) {
        // Targeting our product type and checking that the product is purchased by user
        if ( $product->is_type( 'simple' ) && get_webinar_link( $product, true ) && // 'google_meet_webinar'
            has_purchased_product( $product->get_id() ) ) 
        {
            $button = join_webinar_button( $product );
        }
        return $button;
    }
    

    Code goes in functions.php file of your active child theme (or active theme). Tested and works.