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

291 views Asked by At

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

  • First, I have added a field to admin product pages to put the Google meet link (works).
  • Then, when the user purchase the product, the webinar link will be displayed on WooCommerce order details page and thank you page (works partially).
  • To finish, Once the user has purchased the product, I replace the add to cart button with a custom button to "join the webinar" linked to the webinar (doesn't work).

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);
1

There are 1 answers

6
LoicTheAztec On BEST ANSWER

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.