4

Code:

<?php

// --- Product Type: re_subscription -- Custom Fields: type (mls / nomls), duration in days ---

// --- Actions & Filters ---

add_filter('product_type_selector', 're_add_subscription_product_type');
add_filter('woocommerce_product_data_tabs', 're_remove_shipping_menu', 10, 1);
add_filter('woocommerce_product_class', 're_subscription_product_class', 10, 2);

add_action('plugins_loaded', 're_create_subscription_product_type');
add_action('admin_footer', 're_subscription_admin_custom_js');
add_action('woocommerce_product_options_general_product_data', 're_add_custom_settings');
add_action('woocommerce_process_product_meta', 're_save_custom_settings');


// --- Create Product Type ---

function re_add_subscription_product_type($types){
    $types['re_subscription'] = __('RealEstate Subscription');
    return $types;
}

function re_create_subscription_product_type(){
     // declare the product class
     class WC_Product_Re_Subscription extends WC_Product{
        public function __construct($product) {
           $this->product_type = 're_subscription';
           parent::__construct($product);
           // add additional functions here
        }

        /**
         * Get internal type.
         * Needed for WooCommerce 3.0 Compatibility
         * @return string
         */

        public function get_type() {
            return 're_subscription';
        }
    }
}

function re_subscription_product_class($classname, $product_type) {
    if ($product_type == 're_subscription')
        $classname = 'WC_Product_Re_Subscription';

    return $classname;
}


// --- Remove Shipping Menu ---

function re_remove_shipping_menu($tabs){
    /*
        The available tab array keys are:
        general, inventory, shipping, linked_product, attribute, variations, advanced
     */
    unset($tabs['shipping']);
    return $tabs;
}

// --- Show General Tab ---

function re_subscription_admin_custom_js() {
    if ('product' != get_post_type()) :
        return;
    endif;

    ?>
    <script type='text/javascript'>
        jQuery(document).ready(function () {
            // For Price tab
            jQuery('.product_data_tabs .general_tab').show();
            jQuery('#general_product_data .pricing').addClass('show_if_re_subscription').show();

           });
    </script>
    <?php
}

// --- Add Fields ---

function re_add_custom_settings() {
    global $woocommerce, $post;
    $post_id = $post->ID;
    $re_is_mls = get_post_meta($post_id, 're_is_mls', true);
    if($re_is_mls == '')
        $re_is_mls = 'no';

    echo '<div class="options_group show_if_re_subscription">';
    // Duration
    woocommerce_wp_text_input(
      array(
       'id'                => 're_duration_field',
       'label'             => __('Duration in days', 'woocommerce' ),
       'placeholder'       => '30',
       'desc_tip'    => 'true',
       'description'       => __('Duration of the subscription in days', 'woocommerce'),
       'type'              => 'number',
       ));

    // Type
    woocommerce_wp_checkbox(
       array(
       'id'            => 're_is_mls',
       'label'         => __('Is this MLS?', 'woocommerce'),
       'value' => $re_is_mls,
    ));

    echo '</div>';
}

function re_save_custom_settings($post_id){
    // Save Duration field
    $re_duration_fielld = $_POST['re_duration_field'];
    if(!empty($re_duration_fielld))
        update_post_meta($post_id, 're_duration_field', esc_attr($re_duration_fielld));

    // Save MLS option
    $re_is_mls = isset($_POST['re_is_mls']) ? 'yes' : 'no';
    update_post_meta($post_id, 're_is_mls', $re_is_mls);
}

Screenshot: http://prntscr.com/hq4zzo

On simple products the add to cart product button shows and works with no problems, but on my custom products the Add to Cart button is missing. Price still shows just fine.

I've posted to /r/woocommerce and got no answers :/ hoping for something here :3

Does anyone know where to look? Thanks :)

Admir Zatega
  • 43
  • 1
  • 8

4 Answers4

10

Similar to the Howdy_McGee's answer, but calling do_action instead of wc_get_template:

add_action( "woocommerce_{$my_product_type}_add_to_cart", function() {
    do_action( 'woocommerce_simple_add_to_cart' );
});
tivnet
  • 1,898
  • 17
  • 19
  • 1
    this works great on the product page but doesn't work on the loop page. Any ideas how to enable "add to cart" on the loop page for a custom product type? – Bruno Crosier Apr 20 '20 at 01:37
7

WooCommerce gets their Add to Cart template by product type. In the WooCommerce plugin templates folder we see:

plugins\woocommerce\templates\single-product\add-to-cart

In here we have a template containing HTML based on the product type. You could just create a function, call and action with your type which returns the simple product template.

/**
 * Gives custom product type a template
 *
 * @return void
 */
function se47910821_answer() {
    wc_get_template( 'single-product/add-to-cart/simple.php' );
}
add_action( 'woocommerce_re_subscription_add_to_cart', 'se47910821_answer' );

The hook being:

add_action( "woocommerce_{$product_type}_add_to_cart", 'callback_function' );
Howdy_McGee
  • 10,422
  • 29
  • 111
  • 186
2

I struggled with this for a while and what finally fixed it was adding an "add_to_cart_url()" method in my "WC_Product_Custom" class, like this:

public function add_to_cart_url() {
    $url = $this->is_purchasable() && $this->is_in_stock() ? remove_query_arg( 'added-to-cart', add_query_arg( 'add-to-cart', $this->id ) ) : get_permalink( $this->id );

    return apply_filters( 'woocommerce_product_add_to_cart_url', $url, $this );
}

and then manually adding a link with $product->add_to_cart_url() as the href in the "woocommerce_single_product_summary" action, like this:

add_action( 'woocommerce_single_product_summary', 'custom_product_add_to_cart', 60 );
function custom_product_add_to_cart () {
    global $product;

    // Make sure it's our custom product type
    if ( 'my_custom_product' == $product->get_type() ) {
        do_action( 'woocommerce_before_add_to_cart_button' ); ?>

        <p class="cart">
            <a href="<?php echo esc_url( $product->add_to_cart_url() ); ?>" rel="nofollow" class="single_add_to_cart_button button alt">
                <?php echo "Add to cart"; ?>
            </a>
        </p>

        <?php do_action( 'woocommerce_after_add_to_cart_button' );
    }
}
Emilio Venegas
  • 546
  • 5
  • 22
2

A complement, because previous answers won't work in the loop (e.g shop and archive product pages), as pointed by Bruno Crosier. And also I've added the support of ajax to cart button. You will have to add in your custom product class those functions, copied from class-wc-product-simple.php (and of course yon can customize it):

public function __construct($product) {
    $this->product_type = your_product_name;
    $this->supports[]   = 'ajax_add_to_cart';
    parent::__construct( $product );
}
public function add_to_cart_url() {
            $url = $this->is_purchasable() && $this->is_in_stock() ? remove_query_arg(
                'added-to-cart',
                add_query_arg(
                    array(
                        'add-to-cart' => $this->get_id(),
                    ),
                    ( function_exists( 'is_feed' ) && is_feed() ) || ( function_exists( 'is_404' ) && is_404() ) ? $this->get_permalink() : ''
                )
            ) : $this->get_permalink();
            return apply_filters( 'woocommerce_product_add_to_cart_url', $url, $this );
        }

        /**
         * Get the add to cart button text.
         *
         * @return string
         */
        public function add_to_cart_text() {
            $text = $this->is_purchasable() && $this->is_in_stock() ? __( 'Add to cart', 'woocommerce' ) : __( 'Read more', 'woocommerce' );

            return apply_filters( 'woocommerce_product_add_to_cart_text', $text, $this );
        }

        public function add_to_cart_description() {
        /* translators: %s: Product title */
        $text = $this->is_purchasable() && $this->is_in_stock() ? __( 'Add &ldquo;%s&rdquo; to your cart', 'woocommerce' ) : __( 'Read more about &ldquo;%s&rdquo;', 'woocommerce' );

        return apply_filters( 'woocommerce_product_add_to_cart_description', sprintf( $text, $this->get_name() ), $this );
        }
CRavon
  • 91
  • 1
  • 4