Both the standard List Widget in The Events Calendar and the advanced version of it in Events Calendar Pro naturally list upcoming events in date order.

What if instead of using the start date of each event, though, we want to use the publication date. In other words, we want a way to show the world which events have been added most recently – regardless of when they are taking place?

It turns out we can add some code to change the way the List Widget works. The snippet is listed below. You can add this as a standalone plugin or even to your theme’s functions.php file. With this in place, list widgets will show the most recently published events first.

Of course, you may not wish to make all list widgets behave that way and for that reason, you can add some constraints to help target specific widgets and sidebars.

For instance, if you have a widget entitled “Newly Added” you can opt to modify the behavior of that widget only by changing the following line (found at the bottom of the snippet):

new EventsListWidget_NewlyAddedEvents();

…to this:

new EventsListWidget_NewlyAddedEvents( array(
  'widget_title' => 'Newly Added'
) );

Further detail on adding constraints is provided near the bottom of the snippet itself 🙂

class EventsListWidget_NewlyAddedEvents {
  protected $constraints = array(
    'sidebar_id'   => null,
    'widget_id'    => null,
    'widget_title' => null
  );

  public function __construct( array $constraints = array() ) {
    $this->constraints = array_merge( $this->constraints, $constraints );
    add_filter( 'widget_display_callback', array( $this, 'setup' ), 10, 3 );
  }

  public function setup( $instance, $widget, $args ) {
    // We're interested only in the (advanced or regular) events list widgets
    $targets = array( 'tribe-events-adv-list-widget', 'tribe-events-list-widget' );
    if ( ! in_array( $widget->id_base, $targets ) ) return $instance;

    // Check for constraints
    if ( ! $this->constraints_met( $instance, $args ) ) return $instance;

    // Modify behavior
    add_filter( 'tribe_events_list_widget_query_args', array( $this, 'order_by_latest' ) );
    return $instance;
  }

  protected function constraints_met( $instance, $args ) {
    $fail = false;

    // Should only run within a specific sidebar?
    if ( ! is_null( $this->constraints['sidebar_id'] ) && $this->constraints['sidebar_id'] !== $args['id'] )
    $fail = true;

    // Should only run in relation to a specific instance of the widget?
    if ( ! is_null( $this->constraints['widget_id'] ) && $this->constraints['widget_id'] !== $args['widget_id'] )
    $fail = true;

    // Should only run when the widget title is set to something specific?
    if ( ! is_null( $this->constraints['widget_title'] ) && $this->constraints['widget_title'] !== $instance['title'] )
    $fail = true;

    return ! $fail;
  }

  public function order_by_latest( $args ) {
    // Don't interfere in other queries
    remove_filter( 'tribe_events_list_widget_query_args', array( $this, 'order_by_latest' ) );

    // Tweak the actual orderby clause
    add_filter( 'posts_orderby', array( $this, 'override_orderby' ), 100 );
      return $args;
  }

  public function override_orderby( $orderby_sql ) {
    global $wpdb;

    // Don't interfere in other queries
    remove_filter( 'posts_orderby', array( $this, 'override_orderby' ), 100 );
    return "$wpdb->posts.post_date DESC, $orderby_sql";
  }
}

/**
 * By itself, the following line will impact *all* list widgets. However it may
 * be desirable to impact just one. To achieve this, it is possible to specify
 * one or more constraints.
 *
 * Valid constraints include:
 *
 *     sidebar_id (the ID of the sidebar - list widgets in other sidebars will not be affected)
 *     widget_id (the specific widget ID itself)
 *     widget_title (if you don't know how to determine the widget/sidebar ID, you can specify the title)
 *
 * Example:
 *
 *   new EventsListWidget_NewlyAddedEvents( array(
 *     'sidebar_id' => 'sidebar-1'
 *   ) );
 *
 * Or:
 *
 *   new EventsListWidget_NewlyAddedEvents( array(
 *     'widget_title' => 'Newly Added Events!'
 *   ) );
 */
new EventsListWidget_NewlyAddedEvents();