awesomemotive / sugarcalendar-core

Sugar Calendar plugin for WordPress
https://wordpress.org/plugins/sugar-calendar-lite/
38 stars 14 forks source link

Event archive query missing recurring events #49

Open growdev opened 7 years ago

growdev commented 7 years ago

Adding an event-display query var like this: http://sugarlocal.com/events/?event-display=upcoming

will show a list of events without recurring events.

ref: https://secure.helpscout.net/conversation/385363426/61556/?folderId=875342

pippinsplugins commented 7 years ago

@growdev could you work on a PR for this?

timbowen commented 7 years ago

We handled this by writing a custom query looking at event date OR recurring until date . This doesn't handle correct ordering with recurring events though:

$time = current_time( 'timestamp' );
$time_now = mktime( 0, 0, 0, date( 'n', $time ), date( 'd', $time ), date( 'Y', $time ) );
$event_args = array(
    'post_type'      => 'sc_event',
    'posts_per_page' => 99,
    'orderby'        => 'meta_value_num',
    'order'          => 'asc',
    'post_status'    => 'publish',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'sc_event_date_time',
            'value' => $time_now,
            'compare' => '>='
        ),
        array(
            'key' => 'sc_recur_until',
            'value' => $time_now,
            'compare' => '>='
        )
    )
);
$events = get_posts( apply_filters('sc_event_list_query', $event_args) );
foreach ( $events as $post ) : setup_postdata( $post );
growdev commented 7 years ago

@timbowen thanks for the sample code

@pippinsplugins right now the plugin is using pre_get_posts to modify the archive, but to properly get a list of upcoming events 2-3 queries are required to pull in all the recurring events. Is there a different method to alter the archive?

pippinsplugins commented 7 years ago

No other method that I"m aware of beyond building a completely custom archive.

ianjohn27 commented 7 years ago

This is a function we're using to properly sort the recurring events. It is used in conjunction with @timbowen code above. It merges the first instance of the recurring event into the appropriate place in the list. $events is the result of the loop above.


$events = cs_reorder_sugar_events($events);

/**
 * Given a list of sugar calendar post objects, normalize by sorting by first valid timestamp
 * This gets recurring events in the right place -- with their soonest iteration in the proper spot in the list.
 * @param  [type] $eventList [description]
 * @return array of post objects
 */
function cs_reorder_sugar_events($eventList) {
    $time = current_time( 'timestamp' );
    $time_now = mktime( 0, 0, 0, date( 'n', $time ), date( 'd', $time ), date( 'Y', $time ) );
    $validEvents = array();
    // First, get the first timestamp for every event and assign to startts. If no future recurring event, will not be included.
    foreach($eventList as $event) {
        if( sc_is_recurring( $event->ID ) ) {
            if ($recurring = get_post_meta($event->ID, 'sc_all_recurring', true)) :
                foreach($recurring as $item) {
                    if ($item >= $time_now) {
                        $event->startts = $item;
                        break;
                    }
                }
            endif;
            if (isset($event->startts)) $validEvents[] = $event;
        } else {
            $event->startts = sc_get_event_date( $event->ID, false );
            $validEvents[] = $event;
        }
    }
    usort($validEvents, function ($a, $b) {
        if ($a->startts == $b->startts) {
            return 0;
        }
        return ($a->startts > $b->startts) ? +1 : -1;
    });
    return $validEvents;
}
pippinsplugins commented 7 years ago

Pretty simple PR submitted that fixes it.

JJJ commented 6 years ago

This is going to be handled quite a bit differently in release/2.0, so will need revisiting.