Home / Widgets / Days of the Week Filter Fix (Events List Block)
Duplicate Snippet

Embed Snippet on Your Site

Days of the Week Filter Fix (Events List Block)

Fixes the Events List block's "Days of the Week" filter so it re-queries the server instead of only masking whatever page is already loaded. Without this, filtering to a day (e.g. Tuesday) can show "no events" even when matching events exist on other pages. Known limitation: excludes recurring event occurrences from day-filtered results.

Code Preview
php
<?php
// 1) Send the checked "Days of the Week" values to the server - the block's
// own JS never does this, it only masks already-loaded events with them.
add_action(
	'wp_enqueue_scripts',
	function () {
		if ( ! wp_script_is( 'sc-frontend-blocks-event-list-js', 'registered' ) ) {
			return;
		}
		$js = <<<'JS'
		jQuery( document ).on( 'ajaxSend', function ( event, xhr, settings ) {
			if (
				typeof settings.data !== 'string' ||
				settings.data.indexOf( 'action=sugar_calendar_event_list_block_update' ) === -1
			) {
				return;
			}
			jQuery( '.sugar-calendar-block__popover__calendar_selector__container__options__val__day:checked' ).each( function () {
				settings.data += '&block[daysOfWeek][]=' + encodeURIComponent( jQuery( this ).val() );
			} );
		} );
		JS;
		wp_add_inline_script( 'sc-frontend-blocks-event-list-js', $js, 'after' );
	},
	20
);
// 2) Apply the day filter server-side. Runs at a very late priority so it
// overrides Pro's Advanced Recurring callback on the same filter (that
// callback ignores its input and always wins otherwise) - but only when a
// day filter was actually requested; otherwise it leaves the result untouched.
add_filter(
	'sugar_calendar_helpers_get_upcoming_events_list_with_recurring',
	function ( $upcoming_events, $args, $attributes ) {
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$days_raw = isset( $_POST['block']['daysOfWeek'] ) ? (array) $_POST['block']['daysOfWeek'] : [];
		// $wp_locale->weekday keys: 0 (Sunday) - 6 (Saturday). MySQL DAYOFWEEK(): 1-7.
		$mysql_days = array_unique(
			array_filter(
				array_map(
					function ( $day ) {
						$day = absint( $day );
						return ( $day >= 0 && $day <= 6 ) ? $day + 1 : 0;
					},
					$days_raw
				)
			)
		);
		if ( empty( $mysql_days ) ) {
			return $upcoming_events;
		}
		global $wpdb;
		$calendars_left_join = '';
		$where_calendars     = '';
		if ( ! empty( $args['calendar_ids'] ) ) {
			$term_taxonomy_ids = array_filter( array_map( 'absint', (array) $args['calendar_ids'] ) );
			$term_taxonomy_ids = get_terms(
				[
					'taxonomy'   => 'sc_event_category',
					'include'    => $term_taxonomy_ids,
					'fields'     => 'tt_ids',
					'hide_empty' => false,
				]
			);
			if ( ! empty( $term_taxonomy_ids ) ) {
				$calendars_left_join = 'LEFT JOIN ' . $wpdb->term_relationships . ' AS cal_terms ON ' . $wpdb->prefix . 'sc_events.object_id = cal_terms.object_id';
				$where_calendars     = $wpdb->prepare(
					'AND ( cal_terms.term_taxonomy_id IN (%1$s) )',
					implode( ',', $term_taxonomy_ids )
				);
			}
		}
		$select_query = 'SELECT ' . $wpdb->prefix . 'sc_events.id FROM ' . $wpdb->prefix . 'sc_events';
		$filter_password_protected =
			isset( $args['has_password'] )
			&& $args['has_password'] === false
			&& \Sugar_Calendar\Helpers::should_filter_password_protected_events();
		$exclude_ghost = apply_filters( 'sugar_calendar_exclude_ghost_events', true );
		if ( $exclude_ghost || $filter_password_protected ) {
			$select_query .= ' INNER JOIN ' . $wpdb->posts . ' ON ' . $wpdb->prefix . 'sc_events.object_id = ' . $wpdb->posts . '.ID';
		}
		if ( ! empty( $calendars_left_join ) ) {
			$select_query .= ' ' . $calendars_left_join;
		}
		$tz  = sugar_calendar_get_timezone_type() === 'off' ? 'UTC' : sugar_calendar_get_timezone();
		$now = sugar_calendar_get_request_time( 'mysql', $tz );
		$date_operator = ! empty( $args['show_past_only'] ) ? '<' : '>=';
		$date_column   = ! empty( $args['show_past_only'] ) ? '`end`' : 'start';
		$where_query = $wpdb->prepare(
			'WHERE ' . $wpdb->prefix . 'sc_events.status = "publish" AND ' . $wpdb->prefix . 'sc_events.object_subtype = "sc_event" AND '
			. $wpdb->prefix . 'sc_events.`end` ' . $date_operator . ' %s'
			. ' AND DAYOFWEEK( ' . $wpdb->prefix . 'sc_events.' . $date_column . ' ) IN ( ' . implode( ',', array_fill( 0, count( $mysql_days ), '%d' ) ) . ' )',
			array_merge( [ $now ], $mysql_days )
		);
		if ( $filter_password_protected ) {
			$where_query .= ' AND ' . $wpdb->posts . '.post_password = \'\'';
		}
		if ( ! empty( $where_calendars ) ) {
			$where_query .= ' ' . $where_calendars;
		}
		if ( ! empty( $args['search'] ) ) {
			$where_query .= $wpdb->prepare(
				' AND ' . $wpdb->prefix . 'sc_events.title LIKE %s',
				'%' . $wpdb->esc_like( $args['search'] ) . '%'
			);
		}
		if ( ! empty( $attributes['tags'] ) && class_exists( '\Sugar_Calendar\Features\Tags\Common\Helpers' ) ) {
			$tag_ids = array_filter( array_map( 'absint', (array) $attributes['tags'] ) );
			if ( ! empty( $tag_ids ) ) {
				$tag_taxonomy_id = \Sugar_Calendar\Features\Tags\Common\Helpers::get_tags_taxonomy_id();
				$tags_join  = 'INNER JOIN ' . $wpdb->term_relationships . ' AS tag_terms ON ' . $wpdb->prefix . 'sc_events.object_id = tag_terms.object_id';
				$tags_join .= ' INNER JOIN ' . $wpdb->term_taxonomy . ' AS tag_taxonomy ON tag_terms.term_taxonomy_id = tag_taxonomy.term_taxonomy_id';
				$select_query .= ' ' . $tags_join;
				$placeholders = implode( ',', array_fill( 0, count( $tag_ids ), '%d' ) );
				$where_query .= $wpdb->prepare(
					' AND tag_taxonomy.taxonomy = %s AND tag_taxonomy.term_id IN (' . $placeholders . ')',
					array_merge( [ $tag_taxonomy_id ], $tag_ids )
				);
			}
		}
		$order_column = $wpdb->prefix . 'sc_events.' . ( ! empty( $args['show_past_only'] ) ? '`end`' : 'start' );
		$order_by = $wpdb->prepare(
			'ORDER BY ' . $order_column . ' ' . $args['event_order'] . ' LIMIT %d OFFSET %d',
			$args['number'],
			$args['offset']
		);
		$final_query = $select_query . ' ' . $where_query . ' ' . $order_by;
		$event_ids = $wpdb->get_results( $final_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		if ( empty( $event_ids ) ) {
			return [];
		}
		return sugar_calendar_get_events(
			[
				'id__in'  => wp_list_pluck( $event_ids, 'id' ),
				'orderby' => ! empty( $args['show_past_only'] ) ? 'end' : 'start',
				'order'   => $args['event_order'],
			]
		);
	},
	9999,
	3
);

Comments

Add a Comment