feature: Allow sorting by event date via API

This commit is contained in:
Keith Solomon
2025-09-07 10:59:45 -05:00
parent 0ebbcc7574
commit 5f8d40b42d
+125 -2
View File
@@ -36,6 +36,7 @@ function events_register_post_type() {
'publicly_queryable' => true, 'publicly_queryable' => true,
'show_ui' => true, 'show_ui' => true,
'show_in_menu' => true, 'show_in_menu' => true,
'show_in_rest' => true,
'query_var' => true, 'query_var' => true,
'rewrite' => array( 'slug' => 'events' ), 'rewrite' => array( 'slug' => 'events' ),
'capability_type' => 'post', 'capability_type' => 'post',
@@ -124,12 +125,15 @@ add_action( 'init', 'events_register_event_tag_taxonomy' );
*/ */
function events_add_admin_columns( $columns ) { function events_add_admin_columns( $columns ) {
$new_columns = array(); $new_columns = array();
foreach ( $columns as $key => $value ) { foreach ( $columns as $key => $value ) {
$new_columns[ $key ] = $value; $new_columns[ $key ] = $value;
if ( 'title' === $key ) { if ( 'title' === $key ) {
$new_columns['event_datetime'] = __( 'Event Date & Time', 'aa-events' ); $new_columns['event_datetime'] = __( 'Event Date & Time', 'aa-events' );
} }
} }
return $new_columns; return $new_columns;
} }
add_filter( 'manage_edit-event_columns', 'events_add_admin_columns' ); add_filter( 'manage_edit-event_columns', 'events_add_admin_columns' );
@@ -143,6 +147,7 @@ add_filter( 'manage_edit-event_columns', 'events_add_admin_columns' );
function events_display_admin_column_content( $column, $post_id ) { function events_display_admin_column_content( $column, $post_id ) {
if ( 'event_datetime' === $column ) { if ( 'event_datetime' === $column ) {
$datetime = get_field( 'event_datetime', $post_id ); $datetime = get_field( 'event_datetime', $post_id );
if ( $datetime ) { if ( $datetime ) {
echo esc_html( gmdate( 'F j, Y g:i a', strtotime( $datetime ) ) ); echo esc_html( gmdate( 'F j, Y g:i a', strtotime( $datetime ) ) );
} }
@@ -162,6 +167,26 @@ function events_make_admin_column_sortable( $columns ) {
} }
add_filter( 'manage_edit-event_sortable_columns', 'events_make_admin_column_sortable' ); add_filter( 'manage_edit-event_sortable_columns', 'events_make_admin_column_sortable' );
/**
* Map of sortable meta keys and their types.
*
* Key is the meta_key; value is the meta type used for sorting.
* Supported types include 'NUMERIC', 'CHAR', 'DATE', 'DATETIME'.
* Extend this list to allow additional meta-key sorting.
*
* @return array<string,string>
*/
function events_get_sortable_meta_map() {
return array(
'event_datetime' => 'DATETIME',
// Alias often used externally; map to same type.
'event_start_date' => 'DATETIME',
// Add more allowed meta keys here as needed, for example:
// 'event_capacity' => 'NUMERIC',
// 'venue' => 'CHAR',
);
}
/** /**
* Handle sorting by the custom column. * Handle sorting by the custom column.
* *
@@ -172,13 +197,95 @@ function events_sort_by_custom_column( $query ) {
return; return;
} }
if ( 'event_datetime' === $query->get( 'orderby' ) ) { $orderby = $query->get( 'orderby' );
$query->set( 'meta_key', 'event_datetime' ); $map = events_get_sortable_meta_map();
if ( isset( $map[ $orderby ] ) ) {
$meta_type = strtoupper( $map[ $orderby ] );
$query->set( 'meta_key', $orderby );
if ( 'NUMERIC' === $meta_type ) {
$query->set( 'orderby', 'meta_value_num' );
} else {
$query->set( 'orderby', 'meta_value' ); $query->set( 'orderby', 'meta_value' );
$query->set( 'meta_type', $meta_type );
}
} }
} }
add_action( 'pre_get_posts', 'events_sort_by_custom_column' ); add_action( 'pre_get_posts', 'events_sort_by_custom_column' );
/**
* Extend REST API to allow ordering events by meta value.
* Adds support for `orderby=meta_value|meta_value_num` and `meta_key`.
*
* @param array $params The existing REST API collection parameters.
* @return array The modified REST API collection parameters.
*/
function events_rest_extend_collection_params( $params ) {
if ( isset( $params['orderby']['enum'] ) && is_array( $params['orderby']['enum'] ) ) {
$params['orderby']['enum'][] = 'meta_value';
$params['orderby']['enum'][] = 'meta_value_num';
}
$params['meta_key'] = array(
'description' => __( 'Meta key to order by.', 'aa-events' ),
'type' => 'string',
'sanitize_callback' => 'sanitize_key',
'validate_callback' => function ( $value ) {
return is_string( $value ) && '' !== $value;
},
);
// Optional: allow specifying meta_type when using orderby=meta_value.
$params['meta_type'] = array(
'description' => __( 'Meta type used for ordering.', 'aa-events' ),
'type' => 'string',
'enum' => array( 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ),
);
return $params;
}
add_filter( 'rest_event_collection_params', 'events_rest_extend_collection_params' );
/**
* Apply REST meta ordering to the WP_Query args for events.
*
* @param array $args The prepared query args.
* @param WP_REST_Request $request The REST request.
* @return array
*/
function events_rest_adjust_query_for_meta_ordering( $args, $request ) {
$orderby = $request->get_param( 'orderby' );
$meta_key = $request->get_param( 'meta_key' );
$meta_type = $request->get_param( 'meta_type' );
if ( in_array( $orderby, array( 'meta_value', 'meta_value_num' ), true ) && $meta_key ) {
// Allow simple aliasing of requested meta keys to real keys used in DB.
$aliases = array(
'event_start_date' => 'event_datetime',
);
if ( isset( $aliases[ $meta_key ] ) ) {
$meta_key = $aliases[ $meta_key ];
}
$args['meta_key'] = $meta_key;
$args['orderby'] = $orderby;
// If meta_type explicitly provided (and using meta_value), apply it.
if ( $meta_type && 'meta_value' === $orderby ) {
$args['meta_type'] = strtoupper( $meta_type );
} elseif ( function_exists( 'events_get_sortable_meta_map' ) ) {
// Otherwise, try to infer from our whitelist map for convenience.
$map = events_get_sortable_meta_map();
if ( isset( $map[ $meta_key ] ) && 'meta_value' === $orderby ) {
$args['meta_type'] = strtoupper( $map[ $meta_key ] );
}
}
}
return $args;
}
add_filter( 'rest_event_query', 'events_rest_adjust_query_for_meta_ordering', 10, 2 );
/** /**
* Set default sort order for event post type by event_datetime ascending. * Set default sort order for event post type by event_datetime ascending.
* Applies to both admin and frontend queries. * Applies to both admin and frontend queries.
@@ -202,6 +309,22 @@ function events_set_default_sort_order( $query ) {
// Frontend: event archives and taxonomies // Frontend: event archives and taxonomies
if ( ! is_admin() && $query->get( 'post_type' ) === 'event' ) { if ( ! is_admin() && $query->get( 'post_type' ) === 'event' ) {
$map = events_get_sortable_meta_map();
$orderby = $query->get( 'orderby' );
// If a known meta key is explicitly requested via orderby, honor it.
if ( isset( $map[ $orderby ] ) ) {
$meta_type = strtoupper( $map[ $orderby ] );
$query->set( 'meta_key', $orderby );
if ( 'NUMERIC' === $meta_type ) {
$query->set( 'orderby', 'meta_value_num' );
} else {
$query->set( 'orderby', 'meta_value' );
$query->set( 'meta_type', $meta_type );
}
return; // Do not apply defaults if explicit meta sort requested.
}
// Main event archive: newest first (descending by date/time) // Main event archive: newest first (descending by date/time)
if ( $query->is_post_type_archive( 'event' ) ) { if ( $query->is_post_type_archive( 'event' ) ) {
if ( ! $query->get( 'orderby' ) ) { if ( ! $query->get( 'orderby' ) ) {