Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 0 additions & 166 deletions inc/Blocks/Calendar/Pagination/PageBoundary.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

namespace DataMachineEvents\Blocks\Calendar\Pagination;

use DataMachineEvents\Blocks\Calendar\Cache\CalendarCache;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
Expand All @@ -23,170 +21,6 @@ class PageBoundary {
const DAYS_PER_PAGE = 5;
const MIN_EVENTS_FOR_PAGINATION = 20;

/**
* Get unique event dates for pagination calculations (cached).
*
* Multi-day events are expanded to count on each spanned date.
*
* @deprecated Use CalendarAbilities::get_unique_event_dates() instead. Moved in 0.16.0.
*
* @param array $params Query parameters.
* @return array {
* @type array $dates Ordered array of unique date strings (Y-m-d).
* @type int $total_events Total number of matching events.
* @type array $events_per_date Event counts keyed by date.
* }
*/
public static function get_unique_event_dates( array $params ): array {
$cache_key = CalendarCache::generate_key( $params, 'dates' );
$cached = CalendarCache::get( $cache_key );

if ( false !== $cached ) {
return $cached;
}

$result = self::compute_unique_event_dates( $params );

CalendarCache::set( $cache_key, $result, CalendarCache::TTL_DATES );

return $result;
}

/**
* Compute unique event dates (uncached).
*
* Fetches start/end dates (without post IDs) and uses DATE() in SQL
* to minimize data transfer. Multi-day events are properly expanded
* to count on each spanned date. This reduces cold query time from
* ~960ms to ~500ms at 25,000 events by eliminating the ID column
* and gmdate() parsing in PHP.
*
* @deprecated Use CalendarAbilities::compute_unique_event_dates() instead. Moved in 0.16.0.
*
* @param array $params Query parameters.
* @return array Event dates data.
*/
private static function compute_unique_event_dates( array $params ): array {
global $wpdb;

$show_past_param = $params['show_past'] ?? false;
$current_date = current_time( 'Y-m-d' );
$ed_table = \DataMachineEvents\Core\EventDatesTable::table_name();

// Build WHERE clauses from params for taxonomy/location filtering.
$where_clauses = array(
"p.post_type = 'data_machine_events'",
"p.post_status = 'publish'",
);
$join_clauses = array();
$query_values = array();

if ( ! $show_past_param ) {
$where_clauses[] = 'ed.start_datetime >= %s';
$query_values[] = $current_date . ' 00:00:00';
}

// Handle taxonomy archive filter (any taxonomy: artist, venue, location, etc.).
$archive_taxonomy = $params['archive_taxonomy'] ?? '';
$archive_term_id = $params['archive_term_id'] ?? 0;

if ( $archive_taxonomy && $archive_term_id ) {
$join_clauses[] = "INNER JOIN {$wpdb->term_relationships} tr_archive ON p.ID = tr_archive.object_id";
$join_clauses[] = "INNER JOIN {$wpdb->term_taxonomy} tt_archive ON tr_archive.term_taxonomy_id = tt_archive.term_taxonomy_id";
$where_clauses[] = 'tt_archive.taxonomy = %s';
$query_values[] = $archive_taxonomy;
$where_clauses[] = 'tt_archive.term_id = %d';
$query_values[] = (int) $archive_term_id;
}

// Handle additional taxonomy filters from the filter bar.
$tax_filters = $params['tax_filters'] ?? array();
$filter_index = 0;
foreach ( $tax_filters as $taxonomy_slug => $term_ids ) {
if ( empty( $term_ids ) || ! is_array( $term_ids ) ) {
continue;
}

$alias_tr = 'tr_filter_' . $filter_index;
$alias_tt = 'tt_filter_' . $filter_index;

$join_clauses[] = "INNER JOIN {$wpdb->term_relationships} {$alias_tr} ON p.ID = {$alias_tr}.object_id";
$join_clauses[] = "INNER JOIN {$wpdb->term_taxonomy} {$alias_tt} ON {$alias_tr}.term_taxonomy_id = {$alias_tt}.term_taxonomy_id";
$where_clauses[] = "{$alias_tt}.taxonomy = %s";
$query_values[] = sanitize_key( $taxonomy_slug );

$placeholders = implode( ', ', array_fill( 0, count( $term_ids ), '%d' ) );
$where_clauses[] = "{$alias_tt}.term_id IN ({$placeholders})";
foreach ( $term_ids as $term_id ) {
$query_values[] = (int) $term_id;
}

++$filter_index;
}

$joins = implode( ' ', $join_clauses );
$where = implode( ' AND ', $where_clauses );

// Fetch start/end dates without IDs — DATE() in SQL avoids gmdate() in PHP.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$rows = $wpdb->get_results(
empty( $query_values )
? "SELECT DATE(ed.start_datetime) AS start_date, DATE(ed.end_datetime) AS end_date
FROM {$wpdb->posts} p
INNER JOIN {$ed_table} ed ON p.ID = ed.post_id
{$joins}
WHERE {$where}
ORDER BY ed.start_datetime ASC"
: $wpdb->prepare(
"SELECT DATE(ed.start_datetime) AS start_date, DATE(ed.end_datetime) AS end_date
FROM {$wpdb->posts} p
INNER JOIN {$ed_table} ed ON p.ID = ed.post_id
{$joins}
WHERE {$where}
ORDER BY ed.start_datetime ASC",
...$query_values
)
);

$total_events = count( $rows );
$events_per_date = array();

foreach ( $rows as $row ) {
$events_per_date[ $row->start_date ] = ( $events_per_date[ $row->start_date ] ?? 0 ) + 1;

// Multi-day: expand to each spanned date after the start.
if ( $row->end_date && $row->end_date > $row->start_date ) {
$current = new \DateTime( $row->start_date );
$current->modify( '+1 day' );
$end_dt = new \DateTime( $row->end_date );

while ( $current <= $end_dt ) {
$date = $current->format( 'Y-m-d' );

if ( ! $show_past_param && $date < $current_date ) {
$current->modify( '+1 day' );
continue;
}

$events_per_date[ $date ] = ( $events_per_date[ $date ] ?? 0 ) + 1;
$current->modify( '+1 day' );
}
}
}

if ( $show_past_param ) {
krsort( $events_per_date );
} else {
ksort( $events_per_date );
}

return array(
'dates' => array_keys( $events_per_date ),
'total_events' => $total_events,
'events_per_date' => $events_per_date,
);
}

/**
* Get date boundaries for a specific page.
*
Expand Down
2 changes: 1 addition & 1 deletion inc/Blocks/Calendar/Query/UpcomingFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* Single source of truth for the SQL conditions that determine whether
* an event is upcoming or past. All consumers (DateFilter, EventDateQueryAbilities,
* FilterAbilities, Taxonomy\Helper) delegate here.
* FilterAbilities) delegate here.
*
* Definition:
* upcoming = start >= $datetime OR end >= $datetime
Expand Down
Loading
Loading