I looked around for quite a while for a plugin that added the ability to sort products in Easy Digital Downloads but I couldn’t find anything. Maybe I’ve missed something but I expected this feature to be either part of the core plugin or commonly available.

I wanted to do something like the image below – namely, give the user a dropdown box they could use to sort products in different ways, the kind of thing you see on most online stores.

Not being able to find anything, I put together a short plugin that adds a select box to download pages that will modify the query and allow the user to sort products by different parameters. You can download the plugin here or follow the instructions below to build your own.

All the code does is filter the EDD [downloads] shortcode in a couple of places, firstly to modify the query parameters and secondly to add a dropdown box to the list of products. The user can select an option from the dropdown, e.g. ‘Newness’, and the products will now be sorted according to date published. Change the selection to ‘Price (lowest to highest)’ and the products will be listed with the cheapest first.

The code is as follows. You can add it to your functions.php file or other suitable location:

/**
 * Get the parameters for ordering that we'll include in our select field
 * 
 * @since 1.0.0
 * @return Array
 */
function sp_edd_orderby_params() {
  $params = array( 
    'newness_asc' => array( 
      'id' => 'newness_asc', // Unique ID 
      'title' => __( 'Newest first', 'sp-for-edd' ), // Text to display in select option 
      'orderby' => 'post_date', // Orderby parameter, must be legit WP_Query orderby param 
      'order' => 'DESC' // Either ASC or DESC
    ),
    'newness_desc' => array(
      'id' => 'newness_desc',
      'title' => __( 'Oldest first', 'sp-for-edd' ),
      'orderby' => 'post_date',
      'order' => 'ASC'
    ),
    'price_asc' => array(
      'id' => 'price_asc',
      'title' => __( 'Price (Lowest to Highest)', 'sp-for-edd' ),
      'orderby' => 'meta_value_num',
      'order' => 'ASC'
    ),
    'price_desc' => array(
      'id' => 'price_desc',
      'title' => __( 'Price (Highest to Lowest)', 'sp-for-edd' ),
      'orderby' => 'meta_value_num',
      'order' => 'DESC'
    ),
    'title_asc' => array(
      'id' => 'title_asc',
      'title' => __( 'Title (A - Z)', 'sp-for-edd' ),
      'orderby' => 'title',
      'order' => 'ASC'
    ),
    'title_desc' => array(
      'id' => 'title_desc',
      'title' => __( 'Title (Z - A)', 'sp-for-edd' ),
      'orderby' => 'title',
      'order' => 'DESC'
    )
  );
  $params = apply_filters( 'sp_edd_filter_orderby_params', $params );
  return $params;
}

The block of code above just creates an array of parameters that we’ll use for the dropdown box and for modifying the query.

/**
 * Filter the [downloads] query
 * @since 1.0.0
 * @param $query The query to filter
 * @param $atts The shortcode atts
*/
function sp_edd_filter_query( $query, $atts ) { 
  // We're going to modify the order and orderby parameters depending on variables contained in the URL
  if( isset( $_GET['sp_orderby'] ) ) {
    // If a orderby option has been set, get the array of parameters
    $params = sp_edd_orderby_params();
    $orderby = $_GET['sp_orderby'];
    // Check the parameter that we've chosen exists
    if( isset( $params[$orderby] ) ) {
      $param = $params[$orderby];
      // Set the query parameters according to our selection
      $query['orderby'] = esc_attr( $param['orderby'] );
      $query['order'] = esc_attr( $param['order'] );
      if( strpos( $param['id'], 'price' ) !== false ) {
        // Specify meta key if we're querying by price
        $query['meta_key'] = 'edd_price';
      }
    }
  }
// Return the query, with thanks
return $query;
}
add_filter( 'edd_downloads_query', 'sp_edd_filter_query', 10, 2 );

This is our function to filter the original downloads query from the shortcode. We check if an sp_orderby parameter has been set and, if so, we use it to update some of the query arguments, notably orderby and order. If the parameter is price-based, we also set a meta_key parameter.

/**
 * Filter the [downloads] shortcode to add dropdown field 
 * @since 1.0.0
 * @param $display The markup to print
*/
function sp_edd_add_dropdown( $display ) {
  $orderby = '';
  // Get the current parameter
  if( isset( $_GET['sp_orderby'] ) ) {
    $orderby = $_GET['sp_orderby'];
  }
  // Get the array of parameters
  $params = sp_edd_orderby_params();
  $select = '';
  if( ! empty( $params ) ) {
    // Build the select field
    $select = '<form class="sp-edd-sorting">';
    $select .= '<select class="sp-orderby" name="sp_orderby">';
    // Iterate through each parameter to add options to the select field
    foreach( $params as $param ) {
      $select .= '<option value="' . $param['id'] . '" ' . selected( $param['id'], $orderby, false ) . '>' . $param['title'] . '</option>';
    }
    $select .= '</select>';
    $select .= '</form>';
    // Add a script to submit the form when a new selection is made
    $select .= '<script>
      jQuery(document).ready(function($) {
        $(".sp-orderby").change( function(){
          $(this).closest("form").submit();
        });
      });
    </script>';
    // Add the select field to the top of the downloads grid
    $display = $select . $display;
  }
  return $display; 
}
add_filter( 'downloads_shortcode', 'sp_edd_add_dropdown', 10, 1 );

This function filters the downloads shortcode markup and adds a select field above the product listing. We use the sp_edd_orderby_params function to get our list of parameters then add them one by one to the select. The select is wrapped in a form so we use a small bit of jQuery to submit the form whenever the user selects a new value.

Remember: this will only work with the [downloads] shortcode, not on archive or taxonomy pages.


Do you develop plugins?

You should try Wisdom, a plugin designed specifically for plugin developers that allows you to track your plugin's usage and provides invaluable data on how your plugin is being used. Find out more.

Leave a Reply

Your email address will not be published. Required fields are marked *