function widget($args, $instance)
 {
     extract($args, EXTR_SKIP);
     $template = $instance['template'];
     $no_events = isset($instance['no_events']) ? $instance['no_events'] : '';
     unset($instance['template']);
     unset($instance['no_events']);
     $events = eo_get_events($instance);
     echo $before_widget;
     echo $before_title;
     echo esc_html($instance['title']);
     echo $after_title;
     global $post;
     $tmp_post = $post;
     echo '<ul class="eo-events eo-events-widget">';
     if ($events) {
         foreach ($events as $post) {
             setup_postdata($post);
             if (empty($template)) {
                 //Use default template
                 //Check if all day, set format accordingly
                 if ($post->event_allday) {
                     $format = get_option('date_format');
                 } else {
                     $format = get_option('date_format') . '  ' . get_option('time_format');
                 }
                 echo '<li><a title="' . the_title_attribute(array('echo' => false)) . '" href="' . get_permalink() . '">' . esc_html(get_the_title()) . '</a> ' . __('on', 'eventorganiser') . ' ' . eo_format_date($post->StartDate . ' ' . $post->StartTime, $format) . '</li>';
             } else {
                 echo '<li>' . EventOrganiser_Shortcodes::read_template($template) . '</li>';
             }
         }
         $post = $tmp_post;
         wp_reset_postdata();
     } else {
         echo $no_events;
     }
     echo '</ul>';
     echo $after_widget;
 }
/**
 * Selects posts which satisfy custom WHERE statements
 * Hooked onto posts_where
 *
 *@since 1.0.0
 *@access private
 *@ignore
 *@param string $where WHERE part of the SQL statement
 *@param string $query WP_Query
 *@return string
 */
function eventorganiser_events_where($where, $query)
{
    global $wpdb;
    //Only alter event queries
    if (eventorganiser_is_event_query($query, true)) {
        //If we only want events (or occurrences of events) that belong to a particular 'event'
        if (isset($query->query_vars['event_series'])) {
            $series_id = $query->query_vars['event_series'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.post_id =%d ", $series_id);
        }
        if (isset($query->query_vars['event_occurrence_id'])) {
            $occurrence_id = $query->query_vars['event_occurrence_id'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.event_id=%d ", $occurrence_id);
        }
        if (isset($query->query_vars['event_occurrence__not_in'])) {
            $occurrence__not_in = implode(', ', array_map('intval', $query->query_vars['event_occurrence__not_in']));
            $where .= " AND {$wpdb->eo_events}.event_id NOT IN({$occurrence__not_in}) ";
        }
        if (isset($query->query_vars['event_occurrence__in'])) {
            $occurrence__in = implode(', ', array_map('intval', $query->query_vars['event_occurrence__in']));
            $where .= " AND {$wpdb->eo_events}.event_id IN({$occurrence__in}) ";
        }
        //Check date ranges were are interested in.
        $date_queries = array('event_start_after' => array('notstrict' => " AND {$wpdb->eo_events}.StartDate >= %s ", 'strict' => " AND ({$wpdb->eo_events}.StartDate > %s OR ({$wpdb->eo_events}.StartDate = %s AND {$wpdb->eo_events}.StartTime > %s)) "), 'event_start_before' => array('notstrict' => " AND {$wpdb->eo_events}.StartDate <= %s ", 'strict' => " AND ({$wpdb->eo_events}.StartDate < %s OR ({$wpdb->eo_events}.StartDate = %s AND {$wpdb->eo_events}.StartTime < %s)) "), 'event_end_after' => array('notstrict' => " AND {$wpdb->eo_events}.EndDate >= %s ", 'strict' => " AND ({$wpdb->eo_events}.EndDate > %s OR ({$wpdb->eo_events}.EndDate = %s AND {$wpdb->eo_events}.FinishTime > %s)) "), 'event_end_before' => array('notstrict' => " AND {$wpdb->eo_events}.EndDate <= %s ", 'strict' => " AND ({$wpdb->eo_events}.EndDate < %s OR ({$wpdb->eo_events}.EndDate = %s AND {$wpdb->eo_events}.FinishTime < %s)) "));
        //Construct sql query.
        foreach ($date_queries as $prop => $_sql) {
            $datetime = $query->get($prop);
            if (!empty($datetime)) {
                $date = eo_format_date($datetime, 'Y-m-d');
                $time = eo_format_date($datetime, 'H:i:s');
                if ($time == '00:00:00') {
                    $sql = $_sql['notstrict'];
                    $where .= $wpdb->prepare($sql, $date);
                } else {
                    $sql = $_sql['strict'];
                    $where .= $wpdb->prepare($sql, $date, $date, $time);
                }
            }
        }
    }
    return $where;
}
function eventorganiser_events_where($where, $query)
{
    global $wpdb;
    //Only alter event queries
    if (isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'event') {
        //Ensure all date queries are yyyy-mm-dd format. Process relative strings ('today','tomorrow','+1 week')
        $dates = array('ondate', 'event_start_after', 'event_start_before', 'event_end_after', 'event_end_before');
        foreach ($dates as $prop) {
            if (!empty($query->query_vars[$prop])) {
                $date = $query->query_vars[$prop];
                $dateString = eo_format_date($date, 'Y-m-d');
                $query->set($prop, $dateString);
            }
        }
        //If we only want events (or occurrences of events) that belong to a particular 'event'
        if (isset($query->query_vars['event_series'])) {
            $series_id = $query->query_vars['event_series'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.post_id =%d ", $series_id);
        }
        if (isset($query->query_vars['event_occurrence_id'])) {
            $occurrence_id = $query->query_vars['event_occurrence_id'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.event_id=%d ", $occurrence_id);
        }
        //Retrieve blog's time and date
        $blog_now = new DateTIme(null, eo_get_blog_timezone());
        $now_date = $blog_now->format('Y-m-d');
        $now_time = $blog_now->format('H:i:s');
        $eo_settings_array = get_option('eventorganiser_options');
        $running_event_is_past = empty($eo_settings_array['runningisnotpast']) ? true : false;
        //Query by interval
        if (isset($query->query_vars['eo_interval'])) {
            switch ($query->query_vars['eo_interval']) {
                case 'future':
                    $query->set('showpastevents', 0);
                    $running_event_is_past = true;
                    break;
                case 'expired':
                    $now_date = $blog_now->format('Y-m-d');
                    $now_time = $blog_now->format('H:i:s');
                    $where .= $wpdb->prepare(" \n\t\t\t\t\t\tAND {$wpdb->eo_events}.post_id NOT IN (\n\t\t\t\t\t\t\tSELECT post_id FROM {$wpdb->eo_events} \n\t\t\t\t\t\t\tWHERE ({$wpdb->eo_events}.EndDate > %s)\n\t\t\t\t\t\t\tOR ({$wpdb->eo_events}.EndDate=%s AND {$wpdb->eo_events}.FinishTime >= %s)\n\t\t\t\t\t\t)", $now_date, $now_date, $now_time);
                    break;
                case 'P1D':
                case 'P1W':
                case 'P1M':
                case 'P6M':
                case 'P1Y':
                    if (!isset($cutoff)) {
                        $interval = new DateInterval($query->query_vars['eo_interval']);
                        $cutoff = clone $blog_now;
                        $cutoff->add($interval);
                    }
                    if (empty($query->query_vars['showrepeats'])) {
                        $where .= $wpdb->prepare(" \n\t\t\t\t\t\t\tAND {$wpdb->eo_events}.post_id IN (\n\t\t\t\t\t\t\t\tSELECT post_id FROM {$wpdb->eo_events} \n\t\t\t\t\t\t\t\tWHERE {$wpdb->eo_events}.StartDate <= %s\n\t\t\t\t\t\t\t\tAND {$wpdb->eo_events}.EndDate >= %s)", $cutoff->format('Y-m-d'), $blog_now->format('Y-m-d'));
                    } else {
                        $where .= $wpdb->prepare(" \n\t\t\t\t\t\t\tAND {$wpdb->eo_events}.StartDate <=%s'\n\t\t\t\t\t\t\tAND {$wpdb->eo_events}.EndDate >= %s", $cutoff->format('Y-m-d'), $blog_now->format('Y-m-d'));
                    }
                    break;
            }
        }
        /*
         * If requested, retrieve only future events. 
         * Single pages behave differently - WordPress sees them as displaying the first event
         * There could be options in the future to change this behaviour.
         * Currently we show single pages, even if they don't appear in archive listings.
         * There could be options in the future to change this behaviour too.
         *
         * 'Future events' only works if we are showing all reoccurrences, and not wanting just the first occurrence of an event.
         */
        if (isset($query->query_vars['showpastevents']) && !$query->query_vars['showpastevents']) {
            //If quering for all occurrences, look at start/end date
            if (!$query->get('group_events_by') || $query->get('group_events_by') == 'occurrence') {
                $query_date = $wpdb->eo_events . '.' . ($running_event_is_past ? 'StartDate' : 'EndDate');
                $query_time = $wpdb->eo_events . '.' . ($running_event_is_past ? 'StartTime' : 'FinishTime');
                $where .= $wpdb->prepare(" AND ( \n\t\t\t\t\t({$query_date} > %s) OR\n\t\t\t\t\t({$query_date} = %s AND {$query_time}>= %s))", $now_date, $now_date, $now_time);
                //If querying for an 'event schedule': event is past if it all of its occurrences are 'past'.
            } else {
                if ($running_event_is_past) {
                    //Check if each occurrence has started, i.e. just check reoccurrence_end
                    $query_date = $wpdb->eo_events . '.reoccurrence_end';
                    $query_time = $wpdb->eo_events . '.StartTime';
                    $where .= $wpdb->prepare(" AND ( \n\t\t\t\t\t\t({$query_date} > %s) OR\n\t\t\t\t\t\t({$query_date} = %s AND {$query_time}>= %s))", $now_date, $now_date, $now_time);
                } else {
                    //Check each occurrence has finished, need to do a sub-query.
                    $where .= $wpdb->prepare(" \n\t\t\t\t\t\tAND {$wpdb->eo_events}.post_id IN (\n\t\t\t\t\t\t\tSELECT post_id FROM {$wpdb->eo_events} \n\t\t\t\t\t\t\tWHERE ({$wpdb->eo_events}.EndDate > %s)\n\t\t\t\t\t\t\tOR ({$wpdb->eo_events}.EndDate=%s AND {$wpdb->eo_events}.FinishTime >= %s)\n\t\t\t\t\t\t\t)", $now_date, $now_date, $now_time);
                }
            }
        }
        //Check date ranges were are interested in
        if (isset($query->query_vars['event_start_before']) && $query->query_vars['event_start_before'] != '') {
            $s_before = $query->query_vars['event_start_before'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.StartDate <= %s ", $s_before);
        }
        if (isset($query->query_vars['event_start_after']) && $query->query_vars['event_start_after'] != '') {
            $s_after = $query->query_vars['event_start_after'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.StartDate >= %s ", $s_after);
        }
        if (isset($query->query_vars['event_end_before']) && $query->query_vars['event_end_before'] != '') {
            $e_before = $query->query_vars['event_end_before'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.EndDate <= %s ", $e_before);
        }
        if (isset($query->query_vars['event_end_after']) && $query->query_vars['event_end_after'] != '') {
            $e_after = $query->query_vars['event_end_after'];
            $where .= $wpdb->prepare(" AND {$wpdb->eo_events}.EndDate >= %s ", $e_after);
        }
    }
    return $where;
}
/**
* Returns the end date of occurrence of event. 
* 
* If used inside the loop, with no id no set, returns end date of
* current event occurrence.
* 
* **Please note:** This function used to accept 3 arguments, it now accepts 4, but with the third deprecated. 
* The third argument specified the occurrence (are 3 for the 3rd occurrence of an event). 
* Instead now use the fourth argument - which specifies the occurrence by ID.
* 
* ### Examples
* Inside the loop, you can output the end date of event (occurrence)
* <code>
*       <php echo eo_get_the_end('jS M YY'); ?>
* </code> 
* Get the end date of the event with id 7 and occurrence ID 3
* <code>
*       <?php $date = eo_get_the_end('jS M YY',7,null, 3); ?>
* </code>
* Print a list of upcoming events with their start and end date
* <code>
*     //Get upcoming events
*     $events = eo_get_events(array(
*          'numberposts'=>5,
*          'events_start_after'=>'today',
*          'showpastevents'=>true,//Will be deprecated, but set it to true to play it safe.
*       ));
*
*
*     if( $events ){
*         echo '<ul>';
*         foreach( $events as $event ){
*           printf("<li><a href='%s' >%s</a> from %s to %s </li>",
*                get_the_permalink($post->ID),
*                get_the_title($post->ID),
*                eo_get_the_start('jS F Y', $post->ID,null,$post->occurrence_id),
*                eo_get_the_end('jS F Y', $post->ID,null,$post->occurrence_id)
*           );
*          }
*         echo '</ul>';
*     }else{
*         echo 'No Upcoming Events';
*     }
* </code>
* 
* @since 1.0.0
* @package event-date-functions
* @param string $format String of format as accepted by PHP date
* @param int $post_id The event (post) ID. Uses current event if empty.
* @param int $deprecated The occurrence number. Deprecated. Use $occurrence_id instead
* @param int $occurrence_id  The occurrence ID
* @return string the end date formated to given format, as accepted by PHP date
*/
function eo_get_the_end($format = 'd-m-Y', $post_id = 0, $deprecated = 0, $occurrence_id = 0)
{
    global $post;
    $event = $post;
    if (!empty($deprecated)) {
        _deprecated_argument(__FUNCTION__, '1.5.6', 'Third argument is depreciated. Please use a fourth argument - occurrence ID. Available from $post->occurrence_id');
        //Backwards compatiblity
        if (!empty($post_id)) {
            $event = eo_get_by_postid($post_id, $deprecated, $occurrence_id);
        }
        if (empty($event)) {
            return false;
        }
        $date = trim($event->EndDate) . ' ' . trim($event->FinishTime);
        if (empty($date) || $date == " ") {
            return false;
        }
        return eo_format_date($date, $format);
    }
    $post_id = (int) (empty($post_id) ? get_the_ID() : $post_id);
    $occurrence_id = (int) (empty($occurrence_id) && isset($event->occurrence_id) ? $event->occurrence_id : $occurrence_id);
    $occurrences = eo_get_the_occurrences_of($post_id);
    if (!$occurrences || !isset($occurrences[$occurrence_id])) {
        return false;
    }
    $end = $occurrences[$occurrence_id]['end'];
    /**
     * Filters the value returned by `eo_get_the_end()`
     *
     * @param string|DateTime $formatted_end The DateTime object or formatted returned value (as determined by $format)
     * @param DateTime $end The end date as a DateTime object
     * @param string $format The format the end date should be returned in
     * @param int $post_id Post ID of the event
     * @param int $occurrence_id  The occurrence ID
     */
    $formatted_date = apply_filters('eventorganiser_get_the_end', eo_format_datetime($end, $format), $end, $format, $post_id, $occurrence_id);
    return $formatted_date;
}
/**
* Returns the formated date of the last occurrence of an event
*
* @param string - the format to use, using PHP Date format
* @param id - Optional, the event (post) ID, 
*
* @return string the formatted date 
*
* @since 1.0.0
*/
function eo_get_schedule_end($format = 'd-m-Y', $id = '')
{
    global $post;
    $event = $post;
    if (isset($id) && $id != '') {
        $event = eo_get_by_postid($id);
    }
    $date = esc_html($event->reoccurrence_end . ' ' . $event->StartTime);
    if (empty($date) || $date == " ") {
        return false;
    }
    return eo_format_date($date, $format);
}
/**
* Returns the end date of occurrence of event. 
* 
* If used inside the loop, with no id no set, returns end date of
* current event occurrence.
* 
* **Please note:** This function used to accept 3 arguments, it now accepts 4, but with the third deprecated. 
* The third argument specified the occurrence (are 3 for the 3rd occurrence of an event). 
* Instead now use the fourth argument - which specifies the occurrence by ID.
* 
* ### Examples
* Inside the loop, you can output the end date of event (occurrence)
* <code>
*       <php echo eo_get_the_end('jS M YY'); ?>
* </code> 
* Get the end date of the event with id 7 and occurrence ID 3
* <code>
*       <?php $date = eo_get_the_end('jS M YY',7,null, 3); ?>
* </code>
* Print a list of upcoming events with their start and end date
* <code>
*     //Get upcoming events
*     $events = eo_get_events(array(
*          'numberposts'=>5,
*          'events_start_after'=>'today',
*          'showpastevents'=>true,//Will be deprecated, but set it to true to play it safe.
*       ));
*
*
*     if( $events ){
*         echo '<ul>';
*         foreach( $events as $event ){
*           printf("<li><a href='%s' >%s</a> from %s to %s </li>",
*                get_the_permalink($post->ID),
*                get_the_title($post->ID),
*                eo_get_the_start('jS F Y', $post->ID,null,$post->occurrence_id),
*                eo_get_the_end('jS F Y', $post->ID,null,$post->occurrence_id)
*           );
*          }
*         echo '</ul>';
*     }else{
*         echo 'No Upcoming Events';
*     }
* </code>
* 
* @since 1.0.0
* @package event-date-functions
* @param string $format String of format as accepted by PHP date
* @param int $post_id The event (post) ID. Uses current event if empty.
* @param int $deprecated The occurrence number. Deprecated. Use $occurrence_id instead
* @param int $occurrence_id  The occurrence ID
* @return string the end date formated to given format, as accepted by PHP date
*/
function eo_get_the_end($format = 'd-m-Y', $post_id = 0, $deprecated = 0, $occurrence_id = 0)
{
    global $post;
    $event = $post;
    if (!empty($deprecated)) {
        _deprecated_argument(__FUNCTION__, '1.5.6', 'Third argument is depreciated. Please use a fourth argument - occurrence ID. Available from $post->occurrence_id');
        //Backwards compatiblity
        if (!empty($post_id)) {
            $event = eo_get_by_postid($post_id, $deprecated, $occurrence_id);
        }
        if (empty($event)) {
            return false;
        }
        $date = trim($event->EndDate) . ' ' . trim($event->FinishTime);
        if (empty($date) || $date == " ") {
            return false;
        }
        return eo_format_date($date, $format);
    }
    $occurrence_id = (int) (empty($occurrence_id) && isset($event->occurrence_id) ? $event->occurrence_id : $occurrence_id);
    $occurrences = eo_get_the_occurrences_of($post_id);
    if (!$occurrences || !isset($occurrences[$occurrence_id])) {
        return false;
    }
    $end = $occurrences[$occurrence_id]['end'];
    return apply_filters('eventorganiser_get_the_end', eo_format_datetime($end, $format), $end, $format, $post_id, $occurrence_id);
}
 function parse_template($matches)
 {
     global $post;
     $replacement = '';
     $col = array('start' => array('date' => 'StartDate', 'time' => 'StartTime'), 'end' => array('date' => 'EndDate', 'time' => 'FinishTime'), 'schedule_start' => array('date' => 'reoccurrence_start', 'time' => 'StartTime'), 'schedule_end' => array('date' => 'reoccurrence_end', 'time' => 'FinishTime'));
     switch ($matches[1]) {
         case 'event_title':
             $replacement = get_the_title();
             break;
         case 'start':
         case 'end':
         case 'schedule_start':
         case 'schedule_end':
             switch (count($matches)) {
                 case 2:
                     $dateFormat = get_option('date_format');
                     $dateTime = get_option('time_format');
                     break;
                 case 3:
                     $dateFormat = self::eo_clean_input($matches[2]);
                     $dateTime = '';
                     break;
                 case 5:
                     $dateFormat = self::eo_clean_input($matches[3]);
                     $dateTime = self::eo_clean_input($matches[4]);
                     break;
             }
             if (eo_is_all_day(get_the_ID())) {
                 $replacement = eo_format_date($post->{$col}[$matches[1]]['date'] . ' ' . $post->{$col}[$matches[1]]['time'], $dateFormat);
             } else {
                 $replacement = eo_format_date($post->{$col}[$matches[1]]['date'] . ' ' . $post->{$col}[$matches[1]]['time'], $dateFormat . $dateTime);
             }
             break;
         case 'event_tags':
             $replacement = get_the_term_list(get_the_ID(), 'event-tag', '', ', ', '');
             break;
         case 'event_cats':
             $replacement = get_the_term_list(get_the_ID(), 'event-category', '', ', ', '');
             break;
         case 'event_venue':
             $replacement = eo_get_venue_name();
             break;
         case 'event_venue_map':
             if (eo_get_venue()) {
                 $class = isset($matches[2]) ? self::eo_clean_input($matches[2]) : '';
                 $class = !empty($class) ? 'class=' . $class : '';
                 $replacement = do_shortcode('[eo_venue_map ' . $class . ']');
             }
             break;
         case 'event_venue_url':
             $venue_link = eo_get_venue_link();
             $replacement = !is_wp_error($venue_link) ? $venue_link : '';
             break;
         case 'event_venue_address':
             $address = eo_get_venue_address();
             $replacement = $address['address'];
             break;
         case 'event_venue_postcode':
             $address = eo_get_venue_address();
             $replacement = $address['postcode'];
             break;
         case 'event_venue_country':
             $address = eo_get_venue_address();
             $replacement = $address['country'];
             break;
         case 'event_thumbnail':
             $size = isset($matches[2]) ? self::eo_clean_input($matches[2]) : '';
             $size = !empty($size) ? $size : 'thumbnail';
             $replacement = get_the_post_thumbnail(get_the_ID(), $size);
             break;
         case 'event_url':
             $replacement = get_permalink();
             break;
         case 'event_custom_field':
             $field = $matches[2];
             $meta = get_post_meta(get_the_ID(), $field);
             $replacement = implode($meta);
             break;
         case 'event_excerpt':
             //Using get_the_excerpt adds a link....
             if (post_password_required($post)) {
                 $output = __('There is no excerpt because this is a protected post.');
             } else {
                 $output = $post->post_excerpt;
             }
             $replacement = wp_trim_excerpt($output);
             break;
         case 'cat_color':
             $replacement = eo_event_color();
             break;
     }
     return $replacement;
 }