Kolawole Emmanuel Izzy
Kolawole Emmanuel Izzy

Reputation: 1052

How to display WooCommerce downloads table using PHP code or Shotcode

I'm trying to display woocommerce download table on the dashboard endpoint. After studying the woocommerce download endpoint file i notice woocommerce uses the below code to display the download table;

$downloads     = WC()->customer->get_downloadable_products();
$has_downloads = (bool) $downloads;

do_action( 'woocommerce_before_account_downloads', $has_downloads ); ?>

<?php if ( $has_downloads ) : ?>

    <?php do_action( 'woocommerce_before_available_downloads' ); ?>

    <?php do_action( 'woocommerce_available_downloads', $downloads ); ?>

    <?php do_action( 'woocommerce_after_available_downloads' ); ?>

<?php else : ?>
    <div class="woocommerce-Message woocommerce-Message--info woocommerce-info">
        <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
            <?php esc_html_e( 'Go shop', 'woocommerce' ); ?>
        </a>
        <?php esc_html_e( 'No downloads available yet.', 'woocommerce' ); ?>
    </div>
<?php endif; ?>

<?php do_action( 'woocommerce_after_account_downloads', $has_downloads ); ?>

what I want to achieve is to display the 5 latest downloads in table format. will like to know how to limit this action <?php do_action( 'woocommerce_available_downloads', $downloads ); ?> to only display the latest 5 downloads.

UPDATE

This is the download table in the Woocommerce Download Endpoint Page enter image description here

in which I want to display the same exact table structure on the dashboard endpoint page

enter image description here

Upvotes: 3

Views: 3532

Answers (3)

Kolawole Emmanuel Izzy
Kolawole Emmanuel Izzy

Reputation: 1052

Following the code by @LoicTheAztec Second option (Option 2), I then added the WooCommerce Download Template into a shortcode while adding the function in @LoicTheAztec Option 2 to filter the output. Code Below;

function make_customer_download_output_five_products() {
    $downloads     = WC()->customer->get_downloadable_products();
    $downloads  = get_customer_latest_downloads($downloads); //Here is the function from Option 2
    $has_downloads = (bool) $downloads;
    ob_start();

    if ( $has_downloads ) {
        do_action( 'woocommerce_available_downloads', $downloads );
    } else {
        ?>
        <div class="woocommerce-Message woocommerce-Message--info woocommerce-info">
            <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
                <?php esc_html_e( 'Go shop', 'woocommerce' ); ?>
            </a>
            <?php esc_html_e( 'No downloads available yet.', 'woocommerce' ); ?>
        </div>
        <?php
     }
    return ob_get_clean();
}
add_shortcode('your_downloads', 'make_customer_download_output_five_products');

You can then add the shortcode to any page of choice using do_shortcode(['your_downloads']).

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

Upvotes: 1

LoicTheAztec
LoicTheAztec

Reputation: 253784

You can use 2 ways:

Option 1 - Using a filter hook (filtering on a specific endpoint):

The filter woocommerce_customer_get_downloadable_products is located inside the code from WC_CUstomer get_downloadable_products() method.

The following will give you the 5 latest downloads in a specific endpoint (Here on My Account > downloads endpoint):

add_filter( 'woocommerce_customer_get_downloadable_products', 'filter_customer_downloadable_products', 10, 1 );
function filter_customer_downloadable_products( $downloads ) {
    $limit = 5; // Number of downloads to keep

    // Only on My account Downloads section for more than 5 downloads
    if( is_wc_endpoint_url( 'downloads' ) && sizeof($downloads) > $limit ) {
        $keys_by_order_id = $sorted_downloads = array();
        $count = 0;

        // Loop through the downloads array
        foreach( $downloads as $key => $download ) {
            // Store the array key with the order ID
            $keys_by_order_id[$key] = $download['order_id']; 
        }

        // Sorting the array by Order Ids in DESC order
        arsort($keys_by_order_id); 

        // Loop through the sorted array
        foreach( $keys_by_order_id as $key => $order_id ) {
            // Set the corresponding  download in a new array (sorted)
            $sorted_downloads[] = $downloads[$key];
            $count++; // Increase the count
            // When the count reaches the limit
            if( $count === $limit ) {
                break; // We stop the loop
            }
        }
        return $sorted_downloads;
    }
    return $downloads;
}

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


Option 2 - Using a custom function that filters:

Just use this function, to get from customer $downloads variable the latest 5 downloads.

It can be used anywhere.

function get_customer_latest_downloads( $downloads, $limit = 5 ) {
    // Only on my account pages for more than 5 downloads
    if( sizeof($downloads) > $limit ) {
        $keys_by_order_id = $sorted_downloads = array();
        $count = 0;

        // Loop through the downloads array
        foreach( $downloads as $key => $download ) {
            // Store the array key with the order ID
            $keys_by_order_id[$key] = $download['order_id']; 
        }

        // Sorting the array by Order Ids in DESC order
        arsort($keys_by_order_id); 

        // Loop through the sorted array
        foreach( $keys_by_order_id as $key => $order_id ) {
            // Set the corresponding  download in a new array (sorted)
            $sorted_downloads[] = $downloads[$key];
            $count++; // Increase the count
            // When the count reaches the limit
            if( $count === $limit ) {
                break; // We stop the loop
            }
        }
        return $sorted_downloads;
    }
    return $downloads;
}

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

USAGE Example (in a template or a shortcode):

$downloads     = WC()->customer->get_downloadable_products();

$downloads     = get_customer_latest_downloads( $downloads ); // The 5 latest downloads

// Testing the array raw output
echo '<pre>'; print_r($downloads); echo '</pre>';

Note: Action hooks doesn't filter data.

Upvotes: 2

Derek Gutierrez
Derek Gutierrez

Reputation: 638

Here is a simple example to illustrate how you would manipulate the downloads list before it is displayed by WooCommerce.

The most effective way would be using a filter. This function simply returns the first five downloads in the array. To ensure that the five downloads it returns are the most recent you will need to do a bit more work.

// Define the callback
function filter_woocommerce_customer_available_downloads($downloads, $customer_id) { 

    // Manipulate download data here, this example we'll get the first 5 downloads in the array
    $downloads = array_slice($downloads, 0, 5);

    // Return first five downloads
    return $downloads;

}; 
// Add the filter, this tells wordpress to apply this filter every time available downloads is called
add_filter( 'woocommerce_customer_available_downloads', 'filter_woocommerce_customer_available_downloads', 10, 2 );

Place this at the bottom of your "functions.php" file in your theme. Please keep in mind that this is a quick and dirty example and is untested.

Upvotes: 1

Related Questions