WordPress.org

Plugin Directory

Changeset 1786433


Ignore:
Timestamp:
12/13/17 17:38:31 (6 weeks ago)
Author:
netweblogic
Message:

5.8.1.20 (timezone dev beta)

Location:
events-manager/trunk
Files:
1 added
35 edited

Legend:

Unmodified
Added
Removed
  • events-manager/trunk/admin/bookings/em-events.php

    r1720802 r1786433  
    88    //TODO Simplify panel for events, use form flags to detect certain actions (e.g. submitted, etc) 
    99    global $wpdb; 
    10     global $EM_Event; 
    1110 
    1211    $scope_names = array ( 
     
    3736    } 
    3837    $owner = !current_user_can('manage_others_bookings') ? get_current_user_id() : false; 
    39     $events = EM_Events::get( array('scope'=>$scope, 'limit'=>$limit, 'offset' => $offset, 'order'=>$order, 'bookings'=>true, 'owner' => $owner, 'pagination' => 1 ) ); 
     38    $events = EM_Events::get( array('scope'=>$scope, 'limit'=>$limit, 'offset' => $offset, 'order'=>$order, 'orderby'=>'event_start', 'bookings'=>true, 'owner' => $owner, 'pagination' => 1 ) ); 
    4039    $events_count = EM_Events::$num_rows_found; 
    4140     
     
    9998                    <?php  
    10099                    $rowno = 0; 
    101                     foreach ( $events as $event ) { 
     100                    foreach ( $events as $EM_Event ) { 
    102101                        /* @var $event EM_Event */ 
    103102                        $rowno++; 
    104103                        $class = ($rowno % 2) ? ' class="alternate"' : ''; 
    105                         // FIXME set to american 
    106                         $localised_start_date = date_i18n(get_option('date_format'), $event->start); 
    107                         $localised_end_date = date_i18n(get_option('date_format'), $event->end); 
    108104                        $style = ""; 
    109                         $today = date ( "Y-m-d" ); 
    110105                         
    111                         if ($event->start_date < $today && $event->end_date < $today){ 
     106                        if ($EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time()){ 
    112107                            $style = "style ='background-color: #FADDB7;'"; 
    113108                        }                            
     
    116111                            <td> 
    117112                                <strong> 
    118                                     <?php echo $event->output('#_BOOKINGSLINK'); ?> 
     113                                    <?php echo $EM_Event->output('#_BOOKINGSLINK'); ?> 
    119114                                </strong> 
    120115                                &ndash;  
    121                                 <?php esc_html_e("Booked Spaces",'events-manager') ?>: <?php echo $event->get_bookings()->get_booked_spaces()."/".$event->get_spaces() ?> 
     116                                <?php esc_html_e("Booked Spaces",'events-manager') ?>: <?php echo $EM_Event->get_bookings()->get_booked_spaces()."/".$EM_Event->get_spaces() ?> 
    122117                                <?php if( get_option('dbem_bookings_approval') == 1 ) : ?> 
    123                                     | <?php esc_html_e("Pending",'events-manager') ?>: <?php echo $event->get_bookings()->get_pending_spaces(); ?> 
     118                                    | <?php esc_html_e("Pending",'events-manager') ?>: <?php echo $EM_Event->get_bookings()->get_pending_spaces(); ?> 
    124119                                <?php endif; ?> 
    125120                            </td> 
    126121                     
    127122                            <td> 
    128                                 <?php echo $localised_start_date; ?> 
    129                                 <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?> 
    130                                 &ndash; 
    131                                 <?php 
    132                                     //TODO Should 00:00 - 00:00 be treated as an all day event?  
    133                                     echo substr ( $event->start_time, 0, 5 ) . " - " . substr ( $event->end_time, 0, 5 );  
    134                                 ?> 
     123                                <?php echo $EM_Event->output_dates(false, " - "). ' @ ' . $EM_Event->output_times('H:i', ' - '); ?> 
    135124                            </td> 
    136125                        </tr> 
  • events-manager/trunk/admin/em-bookings.php

    r1694715 r1786433  
    8080        return false; 
    8181    } 
    82     $localised_start_date = date_i18n('D d M Y', $EM_Event->start); 
    83     $localised_end_date = date_i18n('D d M Y', $EM_Event->end); 
    8482    $header_button_classes = is_admin() ? 'page-title-action':'button add-new-h2'; 
    8583    ?> 
     
    107105            <p> 
    108106                <strong><?php esc_html_e('Date','events-manager'); ?></strong> :  
    109                 <?php echo $localised_start_date; ?> 
    110                 <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?> 
    111                 <?php echo substr ( $EM_Event->event_start_time, 0, 5 ) . " - " . substr ( $EM_Event->event_end_time, 0, 5 ); ?>                             
     107                <?php echo $EM_Event->output_dates(false, " - "). ' @ ' . $EM_Event->output_times(false, ' - '); ?>                      
    112108            </p> 
    113109            <p> 
     
    159155                <tr><td><?php echo __('Min','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_min) ? $EM_Ticket->ticket_min : '-'; ?></td></tr> 
    160156                <tr><td><?php echo __('Max','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_max) ? $EM_Ticket->ticket_max : '-'; ?></td></tr> 
    161                 <tr><td><?php echo __('Start','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_start) ? $EM_Ticket->ticket_start : '-'; ?></td></tr> 
    162                 <tr><td><?php echo __('End','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_end) ? $EM_Ticket->ticket_end : '-'; ?></td></tr> 
     157                <tr><td><?php echo __('Start','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_start) ? $EM_Ticket->start()->formatDefault() : '-'; ?></td></tr> 
     158                <tr><td><?php echo __('End','events-manager'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_end) ? $EM_Ticket->end()->formatDefault() : '-'; ?></td></tr> 
    163159                <?php do_action('em_booking_admin_ticket_row', $EM_Ticket); ?> 
    164160            </table> 
     
    203199                            <?php 
    204200                            $EM_Event = $EM_Booking->get_event(); 
    205                             $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start); 
    206                             $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end); 
    207201                            ?> 
    208202                            <table> 
     
    211205                                    <td><strong><?php esc_html_e('Date/Time','events-manager'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td> 
    212206                                    <td> 
    213                                         <?php echo $localised_start_date; ?> 
    214                                         <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?> 
    215                                         <?php echo substr ( $EM_Event->event_start_time, 0, 5 ) . " - " . substr ( $EM_Event->event_end_time, 0, 5 ); ?> 
     207                                        <?php echo $EM_Event->output('#_EVENTDATES @ #_EVENTTIMES'); ?>  
    216208                                    </td> 
    217209                                </tr> 
     
    266258                            <?php 
    267259                            $EM_Event = $EM_Booking->get_event(); 
    268                             $localised_start_date = date_i18n(get_option('date_format'), $EM_Event->start); 
    269                             $localised_end_date = date_i18n(get_option('date_format'), $EM_Event->end); 
    270260                            $shown_tickets = array(); 
    271261                            ?> 
  • events-manager/trunk/admin/em-options.php

    r1720802 r1786433  
    241241        header('Content-Disposition: attachment; filename="events-manager-settings.txt"'); 
    242242        echo json_encode($options); 
     243        exit(); 
     244    } 
     245     
     246    //reset timezones 
     247    if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset_timezones' && check_admin_referer('reset_timezones') && em_wp_is_super_admin() ){ 
     248        include(EM_DIR.'/em-install.php'); 
     249        if( empty($_REQUEST['timezone_reset_value']) ) return; 
     250        $timezone = str_replace('UTC ', '', $_REQUEST['timezone_reset_value']); 
     251        if( is_multisite() ){ 
     252            if( !empty($_REQUEST['timezone_reset_blog']) && is_numeric($_REQUEST['timezone_reset_blog']) ){ 
     253                $blog_id = $_REQUEST['timezone_reset_blog']; 
     254                switch_to_blog($blog_id); 
     255                $blog_name = get_bloginfo('name'); 
     256                $result = em_migrate_datetime_timezones(true, true, $timezone); 
     257                restore_current_blog(); 
     258            }else{ 
     259                $result = __('A valid blog ID must be provided, you can only reset one blog at a time.','events-manager'); 
     260            } 
     261        }else{ 
     262            $result = em_migrate_datetime_timezones(true, true, $timezone); 
     263        } 
     264        if( $result !== true ){ 
     265            $EM_Notices->add_error($result, true); 
     266        }else{ 
     267            if( is_multisite() ){ 
     268                $EM_Notices->add_confirm(sprintf(__('Event timezones for blog %s have been reset to %s.','events-manager'), '<code>'.$blog_name.'</code>', '<code>'.$timezone.'</code>'), true); 
     269            }else{ 
     270                $EM_Notices->add_confirm(sprintf(__('Event timezones have been reset to %s.','events-manager'), '<code>'.$timezone.'</code>'), true); 
     271            } 
     272        } 
     273        wp_redirect(em_wp_get_referer()); 
    243274        exit(); 
    244275    } 
     
    660691        $import_nonce = wp_create_nonce('import_em_settings'); 
    661692    } 
     693    $reset_timezone_nonce = wp_create_nonce('reset_timezones'); 
    662694    ?> 
    663695    <div  class="postbox" id="em-opt-admin-tools" > 
     
    746778            <table class="form-table"> 
    747779                <tr class="em-header"><td colspan="2"> 
     780                    <h4><?php _e ( 'Reset Timezones', 'events-manager'); ?></h4> 
     781                </td></tr> 
     782                <tr> 
     783                    <th style="text-align:right;"> 
     784                        <a href="#" class="button-secondary" id="em-reset-event-timezones"><?php esc_html_e('Reset Event Timezones','events-manager'); ?></a> 
     785                    </th> 
     786                    <td> 
     787                        <select name="timezone_reset_value" class="em-reset-event-timezones"> 
     788                            <?php echo wp_timezone_choice(''); ?> 
     789                        </select> 
     790                        <?php if( is_multisite() ): ?> 
     791                            <select name="timezone_reset_blog" class="em-reset-event-timezones"> 
     792                                <option value="0"><?php esc_html_e('Select a blog...', 'events-manager'); ?></option> 
     793                                <?php 
     794                                foreach( get_sites() as $WP_Site){ /* @var WP_Site $WP_Site */ 
     795                                    echo '<option value="'.esc_attr($WP_Site->blog_id).'">'. esc_html($WP_Site->blogname) .'</option>'; 
     796                                } 
     797                                ?> 
     798                            </select> 
     799                        <?php endif; ?> 
     800                        <p> 
     801                            <em><?php esc_html_e('Select a Timezone to reset all your blog events to.','events-manager'); ?></em><br /> 
     802                            <em><strong><?php esc_html_e('WARNING! This cannot be undone and will overwrite all event timezones, you may want to back up your database first!','events-manager'); ?></strong></em> 
     803                        </p> 
     804                    </td> 
     805                    <script type="text/javascript" charset="utf-8"> 
     806                        jQuery(document).ready(function($){ 
     807                            $('select[name="timezone_reset_value"]').change( function( e ){ 
     808                                if( $(this).val() == '' ){ 
     809                                    $('a#em-reset-event-timezones').css({opacity:0.5, cursor:'default'}); 
     810                                }else{ 
     811                                    $('a#em-reset-event-timezones').css({opacity:1, cursor:'pointer'}); 
     812                                } 
     813                            }).trigger('change'); 
     814                            $('a#em-reset-event-timezones').click(function(e,el){ 
     815                                if( $('select[name="timezone_reset_value"]').val() == '' ) return false; 
     816                                var thisform = $(this).closest('form'); 
     817                                thisform.find('input, textarea, select').prop('disabled', true); 
     818                                thisform.find('select.em-reset-event-timezones').prop('disabled', false); 
     819                                thisform.find('input[name=_wpnonce]').val('<?php echo esc_attr($reset_timezone_nonce); ?>').prop('disabled', false); 
     820                                thisform.append($('<input type="hidden" name="action" value="<?php echo is_multisite() ? 'reset_timezones':'reset_timezones'; ?>" />')); 
     821                                thisform.submit(); 
     822                            }); 
     823                        }); 
     824                    </script> 
     825                </td></tr> 
     826            </table> 
     827             
     828            <table class="form-table"> 
     829                <tr class="em-header"><td colspan="2"> 
    748830                    <h4><?php _e ( 'Uninstall/Reset', 'events-manager'); ?></h4> 
    749831                    <p><?php _e('Use the buttons below to uninstall Events Manager completely from your system or reset Events Manager to original settings and keep your event data.','events-manager'); ?></p> 
  • events-manager/trunk/admin/settings/tabs/general.php

    r1720802 r1786433  
    1010                <td colspan="2"> 
    1111                    <h4><?php echo sprintf(__('%s Settings','events-manager'),__('Event','events-manager')); ?></h4> 
     12                </td> 
     13            </tr> 
     14            <?php 
     15            em_options_radio_binary ( __( 'Enable Timezone Support?', 'events-manager'), 'dbem_timezone_enabled', sprintf(__( 'Each event can have its own timezone if enabled. If set to no, then all newly created events will have the blog timezone, which currently is set to %s','events-manager'), '<code>'.EM_DateTimeZone::create()->getName().'</code>'), '', '.event-timezone-option' ); 
     16            ?> 
     17            <tr class="event-timezone-option"> 
     18                <th> 
     19                    <label for="event-timezone"><?php esc_html_e('Default Timezone', 'events-manager'); ?></label> 
     20                </th> 
     21                <td> 
     22                    <select id="event-timezone" name="dbem_timezone_default"> 
     23                        <?php echo wp_timezone_choice( get_option('dbem_timezone_default') ); ?> 
     24                    </select><br /> 
     25                    <i><?php esc_html_e('When creating a new event, this timezone will be applied by default.','events-manager'); ?></i> 
    1226                </td> 
    1327            </tr> 
  • events-manager/trunk/admin/settings/tabs/pages.php

    r1720802 r1786433  
    8989                            <?php  
    9090                                $event_archive_orderby_options = apply_filters('em_settings_events_default_archive_orderby_ddm', array( 
    91                                     '_start_ts' => __('Order by start date, start time','events-manager'), 
     91                                    '_event_start' => __('Order by start date, start time','events-manager'), 
    9292                                    'title' => __('Order by name','events-manager') 
    93                                 ));  
     93                                )); 
    9494                            ?> 
    9595                            <?php foreach($event_archive_orderby_options as $key => $value) : ?>    
  • events-manager/trunk/classes/em-booking.php

    r1753147 r1786433  
    5959     */ 
    6060    var $notes; 
    61     var $timestamp; 
     61    /** 
     62     * Deprecated as of 5.8.2, previously used to store timestamp of booking date. Use EM_Booking->date()->getTimestamp() instead. 
     63     * @var int 
     64     */ 
     65    private $timestamp; 
     66    /** 
     67     * The date of the booking, in UTC time, represented as a DATETIME mysql value. 
     68     * @var string 
     69     */ 
     70    protected $booking_date; 
     71    /** 
     72     * Contains the booking date in EM_DateTime object form. 
     73     * @var EM_DateTime 
     74     */ 
     75    protected $date; 
    6276    var $person; 
    6377    var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces'); 
     
    126140            $this->previous_status = $this->booking_status; 
    127141            $this->get_person(); 
    128             $this->timestamp = !empty($booking['booking_date']) ? strtotime($booking['booking_date'], current_time('timestamp')):false; 
     142            $this->booking_date = !empty($booking['booking_date']) ? $booking['booking_date']:false; 
    129143        } 
    130144        //Do it here so things appear in the po file. 
     
    145159        } 
    146160        do_action('em_booking', $this, $booking_data); 
     161    } 
     162 
     163     
     164    function __get( $var ){ 
     165        //get the modified or created date from the DB only if requested, and save to object 
     166        if( $var == 'timestamp' ){ 
     167            if( $this->date() === false ) return 0; 
     168            return $this->date()->getTimestampWithOffset(); 
     169        } 
     170        return null; 
     171    } 
     172     
     173    public function __set( $prop, $val ){ 
     174        if( $prop == 'timestamp' ){ 
     175            if( $this->date() !== false ); 
     176            $this->date()->setTimestamp($val); 
     177        } 
     178    } 
     179     
     180    public function __isset( $prop ){ 
     181        if( $prop == 'timestamp' ) $this->date()->getTimestamp() > 0; 
    147182    } 
    148183     
     
    188223                $update = false; 
    189224                $data_types = $this->get_types($data); 
    190                 $data['booking_date'] = current_time('mysql'); 
     225                $data['booking_date'] = gmdate('Y-m-d H:i:s'); 
    191226                $data_types[] = '%s'; 
    192227                $result = $wpdb->insert($table, $data, $data_types); 
     
    637672        if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->event_id == $this->event_id ){ 
    638673            return $this->event; 
    639         }elseif( is_object($EM_Event) && ( (is_object($this->event) && $this->event->event_id == $this->event_id) || empty($this->booking_id)) ){ 
     674        }elseif( is_object($EM_Event) && $EM_Event->event_id == $this->event_id ){ 
    640675            $this->event = $EM_Event; 
    641676        }else{ 
    642             $this->event = new EM_Event($this->event_id, 'event_id'); 
    643         } 
    644         return apply_filters('em_booking_get_event',$this->event, $this); 
     677            $this->event = em_get_event($this->event_id, 'event_id'); 
     678        } 
     679        return apply_filters('em_booking_get_event', $this->event, $this); 
    645680    } 
    646681     
     
    956991        if( $this->can_manage() ){ 
    957992            $this->get_notes(); 
    958             $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp')); 
     993            $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>time()); 
    959994            $this->notes[] = wp_kses_data($note); 
    960995            $this->feedback_message = __('Booking note successfully added.','events-manager'); 
     
    10061041                    break; 
    10071042                case '#_BOOKINGDATE': 
    1008                     $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format'), $this->timestamp):'n/a'; 
     1043                    $replace = ( $this->date() !== false ) ? $this->date()->i18( em_get_date_format() ):'n/a'; 
    10091044                    break; 
    10101045                case '#_BOOKINGTIME': 
    1011                     $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_time_format'), $this->timestamp):'n/a'; 
     1046                    $replace = ( $this->date() !== false ) ?  $this->date()->i18( em_get_hour_format() ):'n/a'; 
    10121047                    break; 
    10131048                case '#_BOOKINGDATETIME': 
    1014                     $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format').' '.get_option('dbem_time_format'), $this->timestamp):'n/a'; 
     1049                    $replace = ( $this->date() !== false ) ? $this->date()->i18( em_get_date_format().' '.em_get_hour_format()):'n/a'; 
    10151050                    break; 
    10161051                case '#_BOOKINGLISTURL': 
     
    11771212     
    11781213    /** 
     1214     * Returns an EM_DateTime representation of when booking was made in UTC timezone. If no valid date defined, false will be returned 
     1215     * @return EM_DateTime 
     1216     */ 
     1217    public function date( $utc_timezone = false ){ 
     1218        if( empty($this->date) || !$this->date->valid ){ 
     1219            if( !empty($this->booking_date ) ){ 
     1220                $this->date = new EM_DateTime($this->booking_date, 'UTC'); 
     1221            }else{ 
     1222                //we retrn a date regardless but it's not based on a 'valid' booking date 
     1223                $this->date = new EM_DateTime(); 
     1224                $this->date->valid = false; 
     1225            } 
     1226        } 
     1227        //Set to UTC timezone if requested, local blog time by default 
     1228        if( $utc_timezone ){ 
     1229            $timezone = 'UTC'; 
     1230        }else{ 
     1231            //we could set this to false but this way we might avoid creating a new timezone if it's already in this one 
     1232            $timezone = get_option( 'timezone_string' ); 
     1233            if( !$timezone ) $timezone = get_option('gmt_offset'); 
     1234        } 
     1235        $this->date->setTimezone($timezone); 
     1236        return $this->date; 
     1237    } 
     1238     
     1239    /** 
    11791240     * Can the user manage this event?  
    11801241     */ 
  • events-manager/trunk/classes/em-bookings-table.php

    r1765726 r1786433  
    449449                                if( $this->show_tickets ){ 
    450450                                    foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){ 
    451                                         ?><td><?php echo implode('</td><td>', $this->get_row($EM_Ticket_Booking)); ?></td><?php 
     451                                        $row = $this->get_row($EM_Ticket_Booking); 
     452                                        foreach( $row as $row_cell ){ 
     453                                        ?><td><?php echo $row_cell; ?></td><?php 
     454                                        } 
    452455                                    } 
    453456                                }else{ 
    454                                     ?><td><?php echo implode('</td><td>', $this->get_row($EM_Booking)); ?></td><?php 
     457                                    $row = $this->get_row($EM_Booking); 
     458                                    foreach( $row as $row_cell ){ 
     459                                    ?><td><?php echo $row_cell; ?></td><?php 
     460                                    } 
    455461                                } 
    456462                                ?> 
     
    509515     * @return array() 
    510516     */ 
    511     function get_row( $object, $csv = false ){ 
     517    function get_row( $object, $format = 'html' ){ 
    512518        /* @var $EM_Ticket EM_Ticket */ 
    513519        /* @var $EM_Ticket_Booking EM_Ticket_Booking */ 
    514520        /* @var $EM_Booking EM_Booking */ 
     521        if( $format === true ) $format = 'csv'; //backwards compatibility, previously $format was $csv which was a boolean  
    515522        if( get_class($object) == 'EM_Ticket_Booking' ){ 
    516523            $EM_Ticket_Booking = $object; 
     
    528535                $val = $EM_Booking->get_person()->user_email; 
    529536            }elseif($col == 'dbem_phone'){ 
    530                 $val = esc_html($EM_Booking->get_person()->phone); 
     537                $val = $EM_Booking->get_person()->phone; 
    531538            }elseif($col == 'user_name'){ 
    532                 if( $csv || $EM_Booking->is_no_user() ){ 
     539                if( $format == 'csv' ){ 
    533540                    $val = $EM_Booking->get_person()->get_name(); 
     541                }elseif( $EM_Booking->is_no_user() ){ 
     542                    $val = esc_html($EM_Booking->get_person()->get_name()); 
    534543                }else{ 
    535                     $val = '<a href="'.esc_url(add_query_arg(array('person_id'=>$EM_Booking->person_id, 'event_id'=>null), $EM_Booking->get_event()->get_bookings_url())).'">'. $EM_Booking->person->get_name() .'</a>'; 
     544                    $val = '<a href="'.esc_url(add_query_arg(array('person_id'=>$EM_Booking->person_id, 'event_id'=>null), $EM_Booking->get_event()->get_bookings_url())).'">'. esc_html($EM_Booking->person->get_name()) .'</a>'; 
    536545                } 
    537546            }elseif($col == 'first_name'){ 
    538                 $val = esc_html($EM_Booking->get_person()->first_name); 
     547                $val = $EM_Booking->get_person()->first_name; 
    539548            }elseif($col == 'last_name'){ 
    540                 $val = esc_html($EM_Booking->get_person()->last_name); 
     549                $val = $EM_Booking->get_person()->last_name; 
    541550            }elseif($col == 'event_name'){ 
    542                 if( $csv ){ 
     551                if( $format == 'csv' ){ 
    543552                    $val = $EM_Booking->get_event()->event_name; 
    544553                }else{ 
     
    558567                $val = $EM_Booking->get_status(true); 
    559568            }elseif($col == 'booking_date'){ 
    560                 $val = date_i18n(get_option('dbem_date_format').' '. get_option('dbem_time_format'), $EM_Booking->timestamp); 
     569                $val = $EM_Booking->date()->i18n( get_option('dbem_date_format').' '. get_option('dbem_time_format') ); 
    561570            }elseif($col == 'actions' ){ 
    562                 if( $csv ) continue;  
     571                if( $format == 'csv' ) continue;  
    563572                $val = implode(' | ', $this->get_booking_actions($EM_Booking)); 
    564573            }elseif( $col == 'booking_spaces' ){ 
     
    567576                $val = $EM_Booking->booking_id; 
    568577            }elseif( $col == 'ticket_name' && $this->show_tickets && !empty($EM_Ticket) ){ 
    569                 $val = $csv ? $EM_Ticket->$col : esc_html($EM_Ticket->$col); 
     578                $val = $EM_Ticket->$col; 
    570579            }elseif( $col == 'ticket_description' && $this->show_tickets && !empty($EM_Ticket) ){ 
    571                 $val = $csv ? $EM_Ticket->$col : esc_html($EM_Ticket->$col); 
     580                $val = $EM_Ticket->$col; 
    572581            }elseif( $col == 'ticket_price' && $this->show_tickets && !empty($EM_Ticket) ){ 
    573582                $val = $EM_Ticket->get_price(true); 
     
    575584                $val = $EM_Ticket->ticket_id; 
    576585            }elseif( $col == 'booking_comment' ){ 
    577                 $val = $csv ? $EM_Booking->booking_comment : esc_html($EM_Booking->booking_comment); 
     586                $val = $EM_Booking->booking_comment; 
     587            } 
     588            //escape all HTML if destination is HTML or not defined 
     589            if( $format == 'html' || empty($format) ){ 
     590                if( !in_array($col, array('user_name', 'event_name', 'actions')) ) $val = esc_html($val); 
    578591            } 
    579592            //use this  
    580             $val = apply_filters('em_bookings_table_rows_col_'.$col, $val, $EM_Booking, $this, $csv, $object); 
    581             $cols[] = apply_filters('em_bookings_table_rows_col', $val, $col, $EM_Booking, $this, $csv, $object); //deprecated, use the above filter instead for better performance 
    582         } 
    583         //clean up the cols to prevent nasty html or xss 
    584         global $allowedposttags; 
    585         foreach($cols as $key => $col){ 
    586             $cols[$key] = wp_kses($col, $allowedposttags); 
     593            $val = apply_filters('em_bookings_table_rows_col_'.$col, $val, $EM_Booking, $this, $format, $object); 
     594            $cols[] = apply_filters('em_bookings_table_rows_col', $val, $col, $EM_Booking, $this, $format, $object); //deprecated, use the above filter instead for better performance 
    587595        } 
    588596        return $cols; 
     
    590598     
    591599    function get_row_csv($EM_Booking){ 
    592         $row = $this->get_row($EM_Booking, true); 
     600        $row = $this->get_row($EM_Booking, 'csv'); 
    593601        foreach($row as $k=>$v) $row[$k] = html_entity_decode($v); //remove things like &amp; which may have been saved to the DB directly 
    594602        return $row; 
  • events-manager/trunk/classes/em-bookings.php

    r1753147 r1786433  
    199199        if( !is_object($this->tickets) || $force_reload ){ 
    200200            $this->tickets = new EM_Tickets($this->event_id); 
    201             if( get_option('dbem_bookings_tickets_single') && count($this->tickets->tickets) == 1 && !empty($this->get_event()->rsvp_end) ){ 
     201            if( get_option('dbem_bookings_tickets_single') && count($this->tickets->tickets) == 1 ){ 
    202202                //if in single ticket mode, then the event booking cut-off is the ticket end date 
    203203                $EM_Ticket = $this->tickets->get_first(); 
     
    206206                if( !empty($EM_Ticket->ticket_end) ){ 
    207207                    //if ticket end dates are set, move to event 
    208                     $EM_Event->event_rsvp_date = date('Y-m-d', $EM_Ticket->end_timestamp); 
    209                     $EM_Event->event_rsvp_time = date('H:i:00', $EM_Ticket->end_timestamp); 
    210                     $EM_Event->rsvp_end = $EM_Ticket->end_timestamp; 
     208                    $EM_Event->event_rsvp_date = $EM_Ticket->end()->format('Y-m-d'); 
     209                    $EM_Event->event_rsvp_time = $EM_Ticket->end()->format('H:i:00'); 
    211210                    if( $EM_Event->is_recurring() && !empty($EM_Ticket->ticket_meta['recurrences']) ){ 
    212211                        $EM_Event->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];                        
    213212                    } 
    214213                }else{ 
    215                     //if no end date is set, use event end date (which will have defaulted to the event start date  
    216                     $EM_Ticket->ticket_end = $EM_Event->event_rsvp_date." ".$EM_Event->event_rsvp_time; 
    217                     $EM_Ticket->end_timestamp = $EM_Event->rsvp_end; 
     214                    //if no end date is set, use event end date (which will have defaulted to the event start date 
     215                    if( !$EM_Event->is_recurring() ){ 
     216                        $EM_Ticket->ticket_end = $EM_Event->rsvp_end()->getDateTime(); 
     217                    }else{ 
     218                        if( !isset($EM_Ticket->ticket_meta['recurrences']['end_days']) ){ 
     219                            //for recurrences, we take the recurrence_rsvp_days and feed it into the ticket meta that'll handle recurrences 
     220                            $EM_Ticket->ticket_meta['recurrences']['end_days'] = $EM_Event->recurrence_rsvp_days; 
     221                            if( !isset($EM_Ticket->ticket_meta['recurrences']['time']) ){ 
     222                                $EM_Ticket->ticket_meta['recurrences']['end_time'] = $EM_Event->event_rsvp_time; 
     223                            } 
     224                            $EM_Ticket->ticket_end = date('Y-m-d ') . $EM_Ticket->ticket_meta['recurrences']['end_time']; 
     225                        } 
     226                    } 
    218227                } 
    219228            } 
     
    273282        $return = false; 
    274283        $EM_Event = $this->get_event(); 
    275         if(!empty($EM_Event->event_rsvp_date) && $EM_Event->rsvp_end > current_time('timestamp')){ 
    276             $return = true; 
    277         }elseif( empty($EM_Event->event_rsvp_date) && $EM_Event->start > current_time('timestamp') ){ 
     284        if( $EM_Event->rsvp_end()->getTimestamp() > time()){ 
    278285            $return = true; 
    279286        } 
  • events-manager/trunk/classes/em-calendar.php

    r1765726 r1786433  
    2020        if( empty($args['month']) && is_array($args['scope']) ){ 
    2121            //if a scope is supplied, figure out the month/year we're after, which will be between these two dates. 
    22             $scope_start = strtotime($args['scope'][0]); 
    23             $scope_end = strtotime($args['scope'][1]); 
    24             $scope_middle = $scope_start + ($scope_end - $scope_start)/2; 
    25             $month = $args['month'] = date('n', $scope_middle); 
    26             $year = $args['year'] = date('Y', $scope_middle); 
     22            $EM_DateTime = new EM_DateTime($args['scope'][0]); 
     23            $scope_start = $EM_DateTime->getTimestamp(); 
     24            $scope_end = $EM_DateTime->modify($args['scope'][1])->getTimestamp(); 
     25            $EM_DateTime->setTimestamp( $scope_start + ($scope_end - $scope_start)/2 ); 
     26            $month = $args['month'] = $EM_DateTime->format('n'); 
     27            $year = $args['year'] = $EM_DateTime->format('Y'); 
    2728        }else{ 
    2829            //if month/year supplied, we use those or later on default to current month/year 
     
    201202         
    202203        //query the database for events in this time span with $offset days before and $outset days after this month to account for these cells in the calendar 
    203         $scope_datetime_start = new DateTime("{$year}-{$month}-1"); 
    204         $scope_datetime_end = new DateTime($scope_datetime_start->format('Y-m-t')); 
    205         $scope_datetime_start->modify("-$offset days"); 
    206         $scope_datetime_end->modify("+$outset days"); 
     204        $scope_datetime_start = new EM_DateTime("{$year}-{$month}-1"); 
     205        $scope_datetime_end = new EM_DateTime($scope_datetime_start->format('Y-m-t')); 
     206        $scope_datetime_start->sub('P'.$offset.'D'); 
     207        $scope_datetime_end->add('P'.$outset.'D'); 
    207208        //we have two methods here, one for high-volume event sites i.e. many thousands of events per month, and another for thousands or less per month. 
    208209        $args['array'] = true; //we're getting an array first to avoid extra queries during object creation 
     
    245246                if( $long_events ){ 
    246247                    //If $long_events is set then show a date as eventful if there is an multi-day event which runs during that day 
    247                     $event_start_ts = strtotime($event['event_start_date']); 
    248                     $event_end_ts = strtotime($event['event_end_date']); 
    249                     $event_end_ts = $event_end_ts > $scope_datetime_end->format('U') ? $scope_datetime_end->format('U') : $event_end_ts; 
    250                     while( $event_start_ts <= $event_end_ts ){ //we loop until the last day of our time-range, not the end date of the event, which could be in a year 
     248                    $event_start = new EM_DateTime($event['event_start_date'], $event['event_timezone']); 
     249                    $event_end = new EM_DateTime($event['event_end_date'], $event['event_timezone']); 
     250                    if( $event_end->getTimestamp() > $scope_datetime_end->getTimestamp() ) $event_end = $scope_datetime_end; 
     251                    while( $event_start->getTimestamp() <= $event_end->getTimestamp() ){ //we loop until the last day of our time-range, not the end date of the event, which could be in a year 
    251252                        //Ensure date is within event dates and also within the limits of events to show per day, if so add to eventful days array 
    252                         $event_eventful_date = date('Y-m-d', $event_start_ts); 
     253                        $event_eventful_date = $event_start->getDate(); 
    253254                        if( empty($eventful_days_count[$event_eventful_date]) || !$limit || $eventful_days_count[$event_eventful_date] < $limit ){ 
    254255                            //now we know this is an event that'll be used, convert it to an object 
     
    256257                            if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array(); 
    257258                            //add event to array with a corresponding timestamp for sorting of times including long and all-day events 
    258                             $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) strtotime($event_eventful_date.' '.$EM_Event->event_start_time); 
     259                            $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $event_start->getTimestamp(); 
    259260                            while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){ 
    260261                                $event_ts_marker++; //add a second 
     
    264265                        //count events for that day 
    265266                        $eventful_days_count[$event_eventful_date] = empty($eventful_days_count[$event_eventful_date]) ? 1 : $eventful_days_count[$event_eventful_date]+1; 
    266                         $event_start_ts += (86400); //add a day 
     267                        $event_start->add('P1D'); 
    267268                    } 
    268269                }else{ 
     
    273274                        if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array(); 
    274275                        //add event to array with a corresponding timestamp for sorting of times including long and all-day events 
    275                         $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $EM_Event->start; 
     276                        $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $EM_Event->start()->getTimestamp(); 
    276277                        while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){ 
    277278                            $event_ts_marker++; //add a second 
  • events-manager/trunk/classes/em-event-post-admin.php

    r1753147 r1786433  
    244244            add_meta_box('em-event-where', __('Where','events-manager'), array('EM_Event_Post_Admin','meta_box_location'),EM_POST_TYPE_EVENT, 'normal','high'); 
    245245        } 
    246         if( defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_DISPLAY') && WP_DEBUG_DISPLAY ){ 
     246        if( defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_DISPLAY') && WP_DEBUG_DISPLAY  && (!defined('EM_DEBUG_DISPLAY') || EM_DEBUG_DISPLAY) ){ 
    247247            add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),EM_POST_TYPE_EVENT, 'normal','high'); 
    248248        } 
     
    273273    public static function meta_box_metadump(){ 
    274274        global $post,$EM_Event; 
    275         echo "<pre>"; print_r($EM_Event); echo "</pre>"; 
     275        echo "<pre>"; print_r($EM_Event); echo "</pre>";         
    276276    } 
    277277     
  • events-manager/trunk/classes/em-event-post.php

    r1766136 r1786433  
    159159            $EM_Event = em_get_event($post); 
    160160            if ( '' == $d ){ 
    161                 $the_date = date_i18n(get_option('date_format'), $EM_Event->start); 
    162             }else{ 
    163                 $the_date = date_i18n($d, $EM_Event->start); 
     161                $the_date = $EM_Event->start()->i18n(get_option('date_format')); 
     162            }else{ 
     163                $the_date = $EM_Event->start()->i18n($d); 
    164164            } 
    165165        } 
     
    172172            $EM_Event = em_get_event($post); 
    173173            if ( '' == $f ){ 
    174                 $the_time = date_i18n(get_option('time_format'), $EM_Event->start); 
    175             }else{ 
    176                 $the_time = date_i18n($f, $EM_Event->start); 
     174                $the_time = $EM_Event->start()->i18n(get_option('time_format')); 
     175            }else{ 
     176                $the_time = $EM_Event->start()->i18n($f); 
    177177            } 
    178178        } 
     
    266266                } 
    267267            } 
    268             $time = current_time('timestamp'); 
    269             if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) { 
    270                 $today = strtotime($scope); 
    271                 $tomorrow = $today + 60*60*24-1; 
     268            if ( $scope == 'today' || $scope == 'tomorrow' || preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) { 
     269                $EM_DateTime = new EM_DateTime($scope); //create default time in blog timezone 
    272270                if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    273                     $query[] = array( 'key' => '_start_ts', 'value' => array($today,$tomorrow), 'compare' => 'BETWEEN' ); 
    274                 }else{ 
    275                     $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' ); 
    276                     $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
     271                    $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate() ); 
     272                }else{ 
     273                    $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate(), 'compare' => '<=', 'type' => 'DATE' ); 
     274                    $query[] = array( 'key' => '_event_end_date', 'value' => $EM_DateTime->getDate(), 'compare' => '>=', 'type' => 'DATE' ); 
    277275                }                
    278             }elseif ($scope == "future"){ 
    279                 $today = strtotime(date('Y-m-d', $time)); 
     276            }elseif ($scope == "future" || $scope == 'past' ){ 
     277                $EM_DateTime = new EM_DateTime(); //create default time in blog timezone 
     278                $EM_DateTime->setTimezone('UTC'); 
     279                $compare = $scope == 'future' ? '>=' : '<'; 
    280280                if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    281                     $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' ); 
    282                 }else{ 
    283                     $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
    284                 } 
    285             }elseif ($scope == "past"){ 
    286                 $today = strtotime(date('Y-m-d', $time)); 
     281                    $query[] = array( 'key' => '_event_start', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' ); 
     282                }else{ 
     283                    $query[] = array( 'key' => '_event_end', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' ); 
     284                } 
     285            }elseif ($scope == "month" || $scope == "next-month" ){ 
     286                $EM_DateTime = new EM_DateTime(); //create default time in blog timezone 
     287                if( $scope == 'next-month' ) $EM_DateTime->add( new DateInterval('P1M') ); 
     288                $start_month = $EM_DateTime->modify('first day of this month')->getDate(); 
     289                $end_month = $EM_DateTime->modify('last day of this month')->getDate(); 
    287290                if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    288                     $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<' ); 
    289                 }else{ 
    290                     $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '<' ); 
    291                 } 
    292             }elseif ($scope == "today"){ 
    293                 $today = strtotime(date('Y-m-d', $time)); 
    294                 $tomorrow = strtotime(date('Y-m-d',$time+60*60*24)); 
     291                    $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN'); 
     292                }else{ 
     293                    $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' ); 
     294                    $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' ); 
     295                } 
     296            }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month. 
     297                $EM_DateTime = new EM_DateTime(); //create default time in blog timezone 
     298                $months_to_add = $matches[1]; 
     299                $start_month = $EM_DateTime->getDate(); 
     300                $end_month = $EM_DateTime->add( new DateInterval('P'.$months_to_add.'M') )->format('Y-m-t'); 
    295301                if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    296                     //date must be only today 
    297                     $query[] = array( 'key' => '_start_ts', 'value' => array($today, $tomorrow), 'compare' => 'BETWEEN'); 
    298                 }else{ 
    299                     $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<' ); 
    300                     $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
    301                 } 
    302             }elseif ($scope == "tomorrow"){ 
    303                 $tomorrow = strtotime(date('Y-m-d',$time+60*60*24)); 
    304                 $after_tomorrow = $tomorrow + 60*60*24; 
    305                 if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    306                     //date must be only tomorrow 
    307                     $query[] = array( 'key' => '_start_ts', 'value' => array($tomorrow, $after_tomorrow), 'compare' => 'BETWEEN'); 
    308                 }else{ 
    309                     $query[] = array( 'key' => '_start_ts', 'value' => $after_tomorrow, 'compare' => '<' ); 
    310                     $query[] = array( 'key' => '_end_ts', 'value' => $tomorrow, 'compare' => '>=' ); 
    311                 } 
    312             }elseif ($scope == "month"){ 
    313                 $start_month = strtotime(date('Y-m-d',$time)); 
    314                 $end_month = strtotime(date('Y-m-t',$time)) + 86399; 
    315                 if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    316                     $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
    317                 }else{ 
    318                     $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' ); 
    319                     $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' ); 
    320                 } 
    321             }elseif ($scope == "next-month"){ 
    322                 $start_month_timestamp = strtotime('+1 month', $time); //get the end of this month + 1 day 
    323                 $start_month = strtotime(date('Y-m-1',$start_month_timestamp)); 
    324                 $end_month = strtotime(date('Y-m-t',$start_month_timestamp)) + 86399; 
    325                 if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    326                     $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
    327                 }else{ 
    328                     $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' ); 
    329                     $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' ); 
    330                 } 
    331             }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month. 
    332                 $months_to_add = $matches[1]; 
    333                 $start_month = strtotime(date('Y-m-d',$time)); 
    334                 $end_month = strtotime(date('Y-m-t',strtotime("+$months_to_add month", $time))) + 86399; 
    335                 if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    336                     $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
    337                 }else{ 
    338                     $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' ); 
    339                     $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' ); 
     302                    $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN'); 
     303                }else{ 
     304                    $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' ); 
     305                    $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' ); 
    340306                } 
    341307            } 
     
    345311            if( is_admin() ){ 
    346312                //admin areas don't need special ordering, so make it simple 
    347                 $wp_query->query_vars['orderby'] = (!empty($_REQUEST['orderby']) && $_REQUEST['orderby'] != 'date-time') ? $_REQUEST['orderby']:'meta_value_num'; 
    348                 $wp_query->query_vars['meta_key'] = '_start_ts'; 
     313                if( !empty($_REQUEST['orderby']) && $_REQUEST['orderby'] != 'date-time' ){ 
     314                    $wp_query->query_vars['orderby'] = $_REQUEST['orderby']; 
     315                }else{ 
     316                    $wp_query->query_vars['orderby'] = 'meta_value'; 
     317                    $wp_query->query_vars['meta_key'] = '_event_start_local'; 
     318                    $wp_query->query_vars['meta_type'] = 'DATETIME'; 
     319                } 
    349320                $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC'; 
    350321            }else{ 
     
    353324                    $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC'); 
    354325                }else{ 
    355                     $wp_query->query_vars['orderby'] = 'meta_value_num'; 
    356                     $wp_query->query_vars['meta_key'] = '_start_ts';         
     326                    $wp_query->query_vars['orderby'] = 'meta_value'; 
     327                    $wp_query->query_vars['meta_key'] = '_event_start_local'; 
     328                    $wp_query->query_vars['meta_type'] = 'DATETIME';         
    357329                } 
    358330                $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC'); 
     
    361333            $wp_query->query_vars['scope'] = 'all'; 
    362334            if( $wp_query->query_vars['post_status'] == 'pending' ){ 
    363                 $wp_query->query_vars['orderby'] = 'meta_value_num'; 
     335                $wp_query->query_vars['orderby'] = 'meta_value'; 
    364336                $wp_query->query_vars['order'] = 'ASC'; 
    365                 $wp_query->query_vars['meta_key'] = '_start_ts'; 
     337                $wp_query->query_vars['meta_key'] = '_event_start_local'; 
     338                $wp_query->query_vars['meta_type'] = 'DATETIME';     
    366339            } 
    367340        } 
  • events-manager/trunk/classes/em-event-posts-admin.php

    r1720802 r1786433  
    225225            case 'date-time': 
    226226                //get meta value to see if post has location, otherwise 
    227                 $localised_start_date = date_i18n(get_option('date_format'), $EM_Event->start); 
    228                 $localised_end_date = date_i18n(get_option('date_format'), $EM_Event->end); 
     227                $localised_start_date = $EM_Event->start()->i18n(get_option('date_format')); 
     228                $localised_end_date = $EM_Event->end()->i18n(get_option('date_format')); 
    229229                echo $localised_start_date; 
    230230                echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":''; 
    231231                echo "<br />"; 
    232232                if(!$EM_Event->event_all_day){ 
    233                     echo date_i18n(get_option('time_format'), $EM_Event->start) . " - " . date_i18n(get_option('time_format'), $EM_Event->end); 
     233                    echo $EM_Event->start()->i18n(get_option('time_format')) . " - " . $EM_Event->end()->i18n(get_option('time_format')); 
    234234                }else{ 
    235235                    echo get_option('dbem_event_all_day_message'); 
    236236                } 
     237                if( $EM_Event->get_timezone()->getName() != EM_DateTimeZone::create()->getName() ) echo '<span class="dashicons dashicons-info" style="font-size:16px; color:#ccc; padding-top:2px;" title="'.esc_attr(str_replace('_', ' ', $EM_Event->event_timezone)).'"></span>'; 
    237238                break; 
    238239            case 'extra': 
  • events-manager/trunk/classes/em-event.php

    r1768279 r1786433  
    22/** 
    33 * Get an event in a db friendly way, by checking globals, cache and passed variables to avoid extra class instantiations. 
    4  * @param mixed $id 
    5  * @param mixed $search_by 
     4 * @param mixed $id can be either a post object, event object, event id or post id 
     5 * @param mixed $search_by default is post_id, otherwise it can be by event_id as well. In multisite global mode, a blog id can be supplied to load events from another blog. 
    66 * @return EM_Event 
    77 */ 
     
    6262    var $event_owner; 
    6363    var $event_name; 
    64     var $event_start_time = '00:00:00'; 
    65     var $event_end_time = '00:00:00'; 
     64    /** 
     65     * The event start time in local time, represented by a mysql TIME format or 00:00:00 default. 
     66     * Protected so when set in PHP it will reset the EM_Event->start property (EM_DateTime object) so it will have the correct UTC time according to timezone. 
     67     * @var string 
     68     */ 
     69    protected $event_start_time = '00:00:00'; 
     70    /** 
     71     * The event end time in local time, represented by a mysql TIME format or 00:00:00 default. 
     72     * Protected so when set in PHP it will reset the EM_Event->end property (EM_DateTime object) so it will have the correct UTC time according to timezone. 
     73     * @var string 
     74     */ 
     75    protected $event_end_time = '00:00:00'; 
     76    /** 
     77     * The event start date in local time. represented by a mysql DATE format. 
     78     * Protected so when set in PHP it will reset the EM_Event->start property (EM_DateTime object) so it will have the correct UTC time according to timezone. 
     79     * @var string 
     80     */ 
     81    protected $event_start_date; 
     82    /** 
     83     * The event end date in local time. represented by a mysql DATE format. 
     84     * Protected so when set in PHP it will reset the EM_Event->start property (EM_DateTime object) so it will have the correct UTC time according to timezone. 
     85     * @var string 
     86     */ 
     87    protected $event_end_date; 
     88    /** 
     89     * The event start date/time in UTC timezone, represented as a mysql DATETIME value. Protected non-accessible property.  
     90     * Use $EM_Event->start() to obtain the date/time via the returned EM_DateTime object. 
     91     * @var string 
     92     */ 
     93    protected $event_start; 
     94    /** 
     95     * The event end date/time in UTC timezone, represented as a mysql DATETIME value. Protected non-accessible property. 
     96     * Use $EM_Event->end() to obtain the date/time via the returned EM_DateTime object. 
     97     * @var string 
     98     */ 
     99    protected $event_end; 
     100    /** 
     101     * Whether an event is all day or at specific start/end times. When set to true, event start/end times are assumed to be 00:00:00 and 11:59:59 respectively. 
     102     * @var boolean 
     103     */ 
    66104    var $event_all_day; 
    67     var $event_start_date; 
    68     var $event_end_date; 
     105    /** 
     106     * Timezone representation in PHP string or WP-style UTC offset. 
     107     * @var string 
     108     */ 
     109    protected $event_timezone; 
    69110    var $post_content; 
    70     var $event_rsvp; 
    71     var $event_rsvp_date; 
    72     var $event_rsvp_time = "00:00:00"; 
     111    var $event_rsvp = 0; 
     112    protected $event_rsvp_date; 
     113    protected $event_rsvp_time = "00:00:00"; 
    73114    var $event_rsvp_spaces; 
    74115    var $event_spaces; 
     
    106147        'event_owner' => array( 'name'=>'owner', 'type'=>'%d', 'null'=>true ), 
    107148        'event_name' => array( 'name'=>'name', 'type'=>'%s', 'null'=>true ), 
     149        'event_timezone' => array('type'=>'%s', 'null'=>true ), 
    108150        'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s', 'null'=>true ), 
    109151        'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s', 'null'=>true ), 
     152        'event_start' => array('type'=>'%s', 'null'=>true ), 
     153        'event_end' => array('type'=>'%s', 'null'=>true ), 
    110154        'event_all_day' => array( 'name'=>'all_day', 'type'=>'%d', 'null'=>true ), 
    111155        'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s', 'null'=>true ), 
     
    136180    var $image_url = ''; 
    137181    /** 
    138      * Timestamp of start date/time 
    139      * @var int 
    140      */ 
    141     var $start; 
    142     /** 
    143      * Timestamp of end date/time 
    144      * @var int 
    145      */ 
    146     var $end; 
     182     * EM_DateTime of start date/time in local timezone. 
     183     * As of EM 5.8 this property is protected and accessible via __get(). For backwards compatibility accessing this property directly returns the timestamp as before with an offset to timezone. 
     184     * To access the object use EM_Event::start(), do not try to access it directly for better accuracy use EM_Event::start()->getTimestamp(); 
     185     * @var EM_DateTime 
     186     */ 
     187    protected $start; 
     188    /** 
     189     * EM_DateTime of end date/time in local timezone. 
     190     * As of EM 5.8 this property is protected and accessible via __get(). For backwards compatibility accessing this property directly returns the timestamp as before, with an offset to timezone. 
     191     * To access the object use EM_Event::end(), do not try to access it directly for better accuracy use EM_Event::start()->getTimestamp(); 
     192     * @var EM_DateTime 
     193     */ 
     194    protected $end; 
    147195    /** 
    148196     * Timestamp for booking cut-off date/time 
    149      * @var int 
    150      */ 
    151     var $rsvp_end; 
    152     /** 
    153      * Created on timestamp, taken from DB, converted to TS 
    154      * @var int 
    155      */ 
    156     var $created; 
    157     /** 
    158      * Created on timestamp, taken from DB, converted to TS 
    159      * @var int 
    160      */ 
    161     var $modified; 
     197     * @var EM_DateTime 
     198     */ 
     199    protected $rsvp_end; 
    162200     
    163201    /** 
     
    175213    var $contact; 
    176214    /** 
    177      * The category object 
    178      * @var EM_Category 
    179      */ 
    180     var $category; 
     215     * The categories object containing the event categories 
     216     * @var EM_Categories 
     217     */ 
     218    var $categories; 
     219    /** 
     220     * The tags object containing the event tags 
     221     * @var EM_Tags 
     222     */ 
     223    var $tags; 
    181224    /** 
    182225     * If there are any errors, they will be added here. 
     
    257300     * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event. 
    258301     * @param mixed $event_data 
    259      * @param mixed $search_by default is post_id, otherwise it can be by event_id as well. 
     302     * @param mixed $search_by default is post_id, otherwise it can be by event_id as well. In multisite global mode, a blog id can be supplied to load events from another blog. 
    260303     * @return null 
    261304     */ 
     
    305348            $this->load_postdata($event_post, $search_by); 
    306349        } 
     350        //set default timezone 
     351        if( empty($this->event_timezone) ){ 
     352            if( get_option('dbem_timezone_enabled') ){ 
     353                //get default timezone for event, and sanitize UTC variations 
     354                $this->event_timezone = get_option('dbem_timezone_default'); 
     355                if( $this->event_timezone == 'UTC+0' || $this->event_timezone == 'UTC +0' ){ $this->event_timezone = 'UTC'; } 
     356            }else{ 
     357                $this->event_timezone = EM_DateTimeZone::create()->getName(); //set a default timezone if none exists 
     358            } 
     359        } 
     360        //set recurrence value already 
    307361        $this->recurrence = $this->is_recurring() ? 1:0; 
    308362        //Do it here so things appear in the po file. 
     
    317371        } 
    318372        do_action('em_event', $this, $id, $search_by); 
     373    } 
     374     
     375    function __get( $var ){ 
     376        //get the modified or created date from the DB only if requested, and save to object 
     377        if( $var == 'event_date_modified' || $var == 'event_date_created'){ 
     378            global $wpdb; 
     379            $row = $wpdb->get_row($wpdb->prepare("SELECT event_date_created, event_date_modified FROM ".EM_EVENTS_TABLE.' WHERE event_id=%s', $this->event_id)); 
     380            if( $row ){ 
     381                $this->event_date_modified = $row->event_date_modified; 
     382                $this->event_date_created = $row->event_date_created; 
     383                return $this->$var; 
     384            } 
     385        }elseif( in_array($var, array('event_start_date', 'event_start_time', 'event_end_date', 'event_end_time', 'event_rsvp_date', 'event_rsvp_time')) ){ 
     386            return $this->$var; 
     387        }elseif( $var == 'event_timezone' ){ 
     388            return $this->get_timezone()->getName(); 
     389        } 
     390        //deprecated properties for external access, use the start(), end() and rsvp_end() functions to access any of this data. 
     391        if( $var == 'start' ) return $this->start()->getTimestampWithOffset(); 
     392        if( $var == 'end' ) return $this->end()->getTimestampWithOffset();       
     393        if( $var == 'rsvp_end' ) return $this->rsvp_end()->getTimestampWithOffset(); 
     394        return null; 
     395    } 
     396     
     397    public function __set( $prop, $val ){ 
     398        if( $prop == 'event_start_date' || $prop == 'event_end_date' || $prop == 'event_rsvp_date' ){ 
     399            //if date is valid, set it, if not set it to null 
     400            $this->$prop = preg_match('/^\d{4}-\d{2}-\d{2}$/', $val) ? $val : null; 
     401            if( $prop == 'event_start_date') $this->start = $this->event_start = null; 
     402            elseif( $prop == 'event_end_date') $this->end = $this->event_end = null; 
     403            elseif( $prop == 'event_rsvp_date') $this->rsvp_end = null; 
     404        }elseif( $prop == 'event_start_time' || $prop == 'event_end_time' || $prop == 'event_rsvp_time' ){ 
     405            //if time is valid, set it, otherwise set it to midnight 
     406            $this->$prop = preg_match('/^\d{2}:\d{2}:\d{2}$/', $val) ? $val : '00:00:00'; 
     407            if( $prop == 'event_start_date') $this->start = null; 
     408            elseif( $prop == 'event_end_date') $this->end = null; 
     409            elseif( $prop == 'event_rsvp_date') $this->rsvp_end = null; 
     410        } 
     411        //deprecated properties, use start()->setTimestamp() instead 
     412        elseif( $prop == 'start' || $prop == 'end' ){ 
     413            if( is_numeric($val) ){ 
     414                if( $prop == 'start' ){ 
     415                    $this->start()->setTimestamp($val); 
     416                }else{ 
     417                    $this->end()->setTimestamp($val); 
     418                } 
     419            }elseif( is_string($val) ){ 
     420                $this->$val = new EM_DateTime($val, $this->event_timezone); 
     421            } 
     422        } 
     423    } 
     424     
     425    public function __isset( $prop ){ 
     426        if( in_array($prop, array('event_start_date', 'event_end_date', 'event_start_time', 'event_end_time', 'event_rsvp_date', 'event_rsvp_time', 'event_start', 'event_end')) ){ 
     427            return !empty($this->$prop); 
     428        }elseif( $prop == 'event_timezone' ){ 
     429            return true; 
     430        }elseif( $prop == 'start' || $prop == 'end' || $prop == 'rsvp_end' ){ 
     431            return $this->$prop()->valid; 
     432        } 
    319433    } 
    320434     
     
    357471                    } 
    358472                } 
    359                 //Start/End times should be available as timestamp 
    360                 $this->start = strtotime($this->event_start_date." ".$this->event_start_time, current_time('timestamp')); 
    361                 $this->end = strtotime($this->event_end_date." ".$this->event_end_time, current_time('timestamp')); 
    362                 if( !empty($this->event_rsvp_date ) ){ 
    363                     $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));  
    364                 } 
    365473                //quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta 
    366474                if( empty($this->event_id) && !$this->is_recurring() ){ 
     
    404512                $this->to_object($event_array); 
    405513            } 
    406             //Start/End times should be available as timestamp 
    407             $this->start = strtotime($this->event_start_date." ".$this->event_start_time, current_time('timestamp')); 
    408             $this->end = strtotime($this->event_end_date." ".$this->event_end_time, current_time('timestamp')); 
    409514        } 
    410515        if( empty($this->location_id) && !empty($this->event_id) ) $this->location_id = 0; //just set location_id to 0 and avoid any doubt 
     
    469574            $this->post_type = 'event-recurring'; 
    470575        } 
    471          
     576        //Set Event Timezone to supplied value or alternatively use blog timezone value by default. 
     577        if( !empty($_REQUEST['event_timezone']) ){ 
     578            $this->event_timezone = EM_DateTimeZone::create($_REQUEST['event_timezone'])->getName(); 
     579        }elseif( empty($this->event_timezone ) ){ //if timezone was already set but not supplied, we don't change it 
     580            $this->event_timezone = EM_DateTimeZone::create()->getName(); 
     581        } 
    472582        //Dates and Times - dates ignored if event is recurring being updated (not new) and not specifically chosen to reschedule event 
     583        $this->event_start = $this->event_end = null; 
    473584        if( !$this->is_recurring() || (empty($this->event_id) || !empty($_REQUEST['event_reschedule'])) ){ 
    474585            //Event Dates 
    475             $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : ''; 
     586            $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : null; 
    476587            $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date; 
    477588        } 
     
    500611            } 
    501612        } 
    502         //Start/End times should be available as timestamp 
    503         $this->start = strtotime($this->event_start_date." ".$this->event_start_time); 
    504         $this->end = strtotime($this->event_end_date." ".$this->event_end_time); 
     613        //reset start and end objects so they are recreated with the new dates/times if and when needed 
     614        $this->start = $this->end = null; 
    505615         
    506616        //Get Location info 
     
    525635            } 
    526636            $this->event_rsvp = 1; 
     637            $this->rsvp_end = null; 
    527638            //RSVP cuttoff TIME is set up above where start/end times are as well  
    528639            if( !$this->is_recurring() ){ 
     
    530641                    //single ticket mode will use the ticket end date/time as cut-off date/time 
    531642                    $EM_Ticket = $this->get_tickets()->get_first(); 
    532                     $this->event_rsvp_date = ''; 
    533                     if( !empty($EM_Ticket->end_timestamp) ){ 
    534                         $this->event_rsvp_date = date('Y-m-d', $EM_Ticket->end_timestamp); 
    535                         $this->event_rsvp_time = date('H:i:00', $EM_Ticket->end_timestamp); 
     643                    $this->event_rsvp_date = null; 
     644                    if( !empty($EM_Ticket->ticket_end) ){ 
     645                        $this->event_rsvp_date = $EM_Ticket->end()->getDate(); 
     646                        $this->event_rsvp_time = $EM_Ticket->end()->getTime(); 
    536647                    }else{ 
    537648                        //no default ticket end time, so make it default to event start date/time 
     
    546657                    if( $this->event_all_day && empty($_POST['event_rsvp_date']) ){ $this->event_rsvp_time = '00:00:00'; } //all-day events start at 0 hour 
    547658                } 
    548                 //create timestamp 
    549                 if( empty($this->event_rsvp_date) ){  
    550                     //falback in case nothing gets set for rsvp cut-off 
    551                     $this->event_rsvp_time = '00:00:00'; 
    552                     $this->rsvp_end = 0; //empty value but timestamp compatible  
    553                 }else{ 
    554                     $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp')); 
    555                 } 
    556             }else{ 
    557                 //recurring events may have a cut-off date x days before or after the recurrence start dates 
    558                 $this->recurrence_rsvp_days = null; 
    559                 if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){ 
    560                     //if in single ticket mode then ticket cut-off date determines event cut-off date 
    561                     $EM_Ticket = $this->get_tickets()->get_first(); 
    562                     if( !empty($EM_Ticket->ticket_meta['recurrences']) ){ 
    563                         $this->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days']; 
    564                         $this->event_rsvp_time = $EM_Ticket->ticket_meta['recurrences']['end_time']; 
    565                     } 
    566                 }else{ 
    567                     if( array_key_exists('recurrence_rsvp_days', $_POST) ){ 
    568                         if( !empty($_POST['recurrence_rsvp_days_when']) && $_POST['recurrence_rsvp_days_when'] == 'after' ){ 
    569                             $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']); 
    570                         }else{ //by default the start date is the point of reference 
    571                             $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']) * -1; 
    572                         } 
    573                     } 
    574                 } 
    575                 //create timestamps and set rsvp date/time for a normal event 
    576                 if( !is_numeric($this->recurrence_rsvp_days) ){  
    577                     //falback in case nothing gets set for rsvp cut-off 
    578                     $this->event_rsvp_date = ''; 
    579                     $this->event_rsvp_time = '00:00:00'; 
    580                     $this->rsvp_end = 0; //empty value but timestamp compatible 
    581                 }else{ 
    582                     $this->event_rsvp_date = date('Y-m-d', strtotime($this->recurrence_rsvp_days.' days', $this->start)); 
    583                     $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp')); 
    584                 } 
     659                //reset EM_DateTime object 
     660                $this->rsvp_end = null; 
    585661            } 
    586662            $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0; 
     
    589665            if( empty($_POST['event_rsvp']) && $this->event_rsvp ) $deleting_bookings = true; 
    590666            $this->event_rsvp = 0; 
    591             $this->event_rsvp_time = null; 
     667            $this->event_rsvp_date = $this->event_rsvp_time = $this->rsvp_end = null; 
    592668        } 
    593669         
     
    693769                $this->recurring_reschedule = $this->recurring_recreate_bookings = true; 
    694770            } 
     771            //recurring events may have a cut-off date x days before or after the recurrence start dates 
     772            $this->recurrence_rsvp_days = null; 
     773            if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){ 
     774                //if in single ticket mode then ticket cut-off date determines event cut-off date 
     775                $EM_Ticket = $this->get_tickets()->get_first(); 
     776                if( !empty($EM_Ticket->ticket_meta['recurrences']) ){ 
     777                    $this->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days']; 
     778                    $this->event_rsvp_time = $EM_Ticket->ticket_meta['recurrences']['end_time']; 
     779                } 
     780            }else{ 
     781                if( array_key_exists('recurrence_rsvp_days', $_POST) ){ 
     782                    if( !empty($_POST['recurrence_rsvp_days_when']) && $_POST['recurrence_rsvp_days_when'] == 'after' ){ 
     783                        $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']); 
     784                    }else{ //by default the start date is the point of reference 
     785                        $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']) * -1; 
     786                    } 
     787                } 
     788            } 
     789            //create timestamps and set rsvp date/time for a normal event 
     790            if( !is_numeric($this->recurrence_rsvp_days) ){ 
     791                //falback in case nothing gets set for rsvp cut-off 
     792                $this->event_rsvp_date = $this->event_rsvp_time = $this->rsvp_end = null; 
     793            }else{ 
     794                $this->event_rsvp_date = $this->start()->clone()->modify($this->recurrence_rsvp_days.' days')->getDate(); 
     795            } 
    695796        }else{ 
    696797            foreach( $this->recurrence_fields as $recurrence_field ){ 
     
    738839        } 
    739840        if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_end_date) ){ 
    740             if( strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_end_date . $this->event_end_time) ){ 
     841            if( $this->start()->getTimestamp() > $this->end()->getTimestamp() ){ 
    741842                $this->add_error(__('Events cannot start after they end.','events-manager')); 
    742             }elseif( $this->is_recurring() && $this->recurrence_days == 0 && strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_start_date . $this->event_end_time) ){ 
     843            }elseif( $this->is_recurring() && $this->recurrence_days == 0 && $this->start()->getTimestamp() > $this->end()->getTimestamp() ){ 
    743844                $this->add_error(__('Events cannot start after they end.','events-manager').' '.__('For recurring events that end the following day, ensure you make your event last 1 or more days.')); 
    744845            } 
     
    805906        $post_array['post_type'] = ($this->recurrence && get_option('dbem_recurrence_enabled')) ? 'event-recurring':EM_POST_TYPE_EVENT; 
    806907        $post_array['post_title'] = $this->event_name; 
    807         $post_array['post_content'] = $this->post_content; 
     908        $post_array['post_content'] = !empty($this->post_content) ? $this->post_content : ''; 
    808909        $post_array['post_excerpt'] = $this->post_excerpt; 
    809910        //decide on post status 
     
    896997                    //ignore certain fields and delete if not new 
    897998                    $save_meta_key = true; 
    898                     $recurrence_array = array('recurrence', 'recurrence_interval', 'recurrence_freq', 'recurrence_days', 'recurrence_byday', 'recurrence_byweekno', 'recurrence_rsvp_days'); 
    899                     if( !$this->is_recurring() && in_array($key, $recurrence_array) ) $save_meta_key = false; 
     999                    if( !$this->is_recurring() && in_array($key, $this->recurrence_fields) ) $save_meta_key = false; 
    9001000                    if( !$this->is_recurrence() && $key == 'recurrence_id' ) $save_meta_key = false; 
    9011001                    $ignore_zero_keys = array('location_id', 'group_id', 'event_all_day' ); 
     
    9271027                } 
    9281028            } 
    929             //update timestampes 
    930             update_post_meta($this->post_id, '_start_ts', str_pad($this->start, 10, 0, STR_PAD_LEFT)); 
    931             update_post_meta($this->post_id, '_end_ts', str_pad($this->end, 10, 0, STR_PAD_LEFT)); 
     1029            //update timestamps, dates and times 
     1030            update_post_meta($this->post_id, '_event_start_local', $this->start()->getDateTime()); 
     1031            update_post_meta($this->post_id, '_event_end_local', $this->end()->getDateTime()); 
     1032            //Deprecated, only for backwards compatibility, these meta fields will eventually be deleted! 
     1033            $admin_data = get_option('dbem_admin_data'); 
     1034            if( $admin_data['datetime_backcompat'] ){ 
     1035                update_post_meta($this->post_id, '_start_ts', str_pad($this->start()->getTimestamp(), 10, 0, STR_PAD_LEFT)); 
     1036                update_post_meta($this->post_id, '_end_ts', str_pad($this->end()->getTimestamp(), 10, 0, STR_PAD_LEFT)); 
     1037            } 
    9321038            //sort out event status          
    9331039            $result = count($this->errors) == 0; 
     
    9701076                    $this->feedback_message = sprintf(__('Successfully saved %s','events-manager'),__('Event','events-manager')); 
    9711077                    $this->just_added_event = true; //make an easy hook 
     1078                    $this->get_bookings()->bookings = array(); //set bookings array to 0 to avoid an extra DB query 
    9721079                    do_action('em_event_save_new', $this); 
    9731080                } 
     
    9941101            //Add/Delete Tickets 
    9951102            if($this->event_rsvp == 0){ 
    996                 $this->get_bookings()->delete(); 
    997                 $this->get_tickets()->delete(); 
     1103                if( !$this->just_added_event ){ 
     1104                    $this->get_bookings()->delete(); 
     1105                    $this->get_tickets()->delete(); 
     1106                } 
    9981107            }elseif( $this->can_manage('manage_bookings','manage_others_bookings') ){ 
    9991108                if( !$this->get_bookings()->get_tickets()->save() ){ 
     
    12411350    } 
    12421351     
     1352    public function set_timezone( $timezone = false ){ 
     1353        //reset UTC times and objects so they're recreated with local time and new timezone 
     1354        $this->event_start = $this->event_end = $this->start = $this->end = $this->rsvp_end = null; 
     1355        $EM_DateTimeZone = EM_DateTimeZone::create($timezone); 
     1356        //modify the timezone string name itself 
     1357        $this->event_timezone = $EM_DateTimeZone->getName(); 
     1358    } 
     1359     
     1360    public function get_timezone(){ 
     1361        return $this->start()->getTimezone(); 
     1362    } 
     1363     
    12431364    function is_published(){ 
    12441365        return apply_filters('em_event_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this); 
     1366    } 
     1367     
     1368    /** 
     1369     * Returns an EM_DateTime object of the event start date/time in local timezone of event. 
     1370     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. 
     1371     * @return EM_DateTime 
     1372     * @see EM_Event::get_datetime() 
     1373     */ 
     1374    public function start( $utc_timezone = false ){ 
     1375        return apply_filters('em_event_start', $this->get_datetime('start', $utc_timezone), $this); 
     1376    } 
     1377     
     1378    /** 
     1379     * Returns an EM_DateTime object of the event end date/time in local timezone of event 
     1380     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. 
     1381     * @return EM_DateTime 
     1382     * @see EM_Event::get_datetime() 
     1383     */ 
     1384    public function end( $utc_timezone = false ){ 
     1385        return apply_filters('em_event_end', $this->get_datetime('end', $utc_timezone), $this); 
     1386    } 
     1387     
     1388    /** 
     1389     * Returns an EM_DateTime representation of when bookings close in local event timezone. If no valid date defined, event start date/time will be used. 
     1390     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. 
     1391     * @return EM_DateTime 
     1392     */ 
     1393    public function rsvp_end( $utc_timezone = false ){ 
     1394        if( empty($this->rsvp_end) || !$this->rsvp_end->valid ){ 
     1395            if( !empty($this->event_rsvp_date ) ){ 
     1396                $this->rsvp_end = new EM_DateTime($this->event_rsvp_date." ".$this->event_rsvp_time, $this->event_timezone); 
     1397                if( !$this->rsvp_end->valid ){ 
     1398                    //invalid date will revert to start time 
     1399                    $this->rsvp_end = $this->start()->clone(); 
     1400                } 
     1401            }else{ 
     1402                //no date defined means event start date/time is used 
     1403                $this->rsvp_end = $this->start()->clone(); 
     1404            } 
     1405        } 
     1406        //Set to UTC timezone if requested, local by default 
     1407        $tz = $utc_timezone ? 'UTC' : $this->event_timezone; 
     1408        $this->rsvp_end->setTimezone($tz); 
     1409        return $this->rsvp_end; 
     1410    } 
     1411     
     1412    /** 
     1413     * Generates an EM_DateTime for the the start/end date/times of the event in local timezone, as well as setting a valid flag if dates and times are valid. 
     1414     * The generated object will be derived from the local date and time values. If no date exists, then 1970-01-01 will be used, and 00:00:00 if no valid time exists.  
     1415     * If date is invalid but time is, only use local timezones since a UTC conversion will provide inaccurate timezone differences due to unknown DST status.   *  
     1416     * @param string $when 'start' or 'end' date/time 
     1417     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. Do not use if EM_DateTime->valid is false.  
     1418     * @return EM_DateTime 
     1419     */ 
     1420    public function get_datetime( $when = 'start', $utc_timezone = false ){ 
     1421        if( $when != 'start' && $when != 'end') return new EM_DateTime(); //currently only start/end dates are relevant 
     1422        //Initialize EM_DateTime if not already initialized, or if previously initialized object is invalid (e.g. draft event with invalid dates being resubmitted) 
     1423        $when_date = 'event_'.$when.'_date'; 
     1424        $when_time = 'event_'.$when.'_time'; 
     1425        //we take a pass at creating a new datetime object if it's empty, invalid or a different time to the current start date 
     1426        if( empty($this->$when) || !$this->$when->valid ){ 
     1427            $when_utc = 'event_'.$when; 
     1428            $date_regex = '/^\d{4}-\d{2}-\d{2}$/'; 
     1429            $valid_time = !empty($this->$when_time) && preg_match('/^\d{2}:\d{2}:\d{2}$/', $this->$when_time); 
     1430            //If there now is a valid date string for local or UTC timezones, create a new object which will set the valid flag to true by default 
     1431            if( !empty($this->$when_date) && preg_match($date_regex, $this->$when_date) && $valid_time ){ 
     1432                $EM_DateTime = new EM_DateTime(trim($this->$when_date.' '.$this->$when_time), $this->event_timezone); 
     1433                if( $EM_DateTime->valid && empty($this->$when_utc) ){ 
     1434                    $EM_DateTime->setTimezone('UTC'); 
     1435                    $this->$when_utc = $EM_DateTime->format(); 
     1436                } 
     1437            } 
     1438            //If we didn't attempt to create a date above, or it didn't work out, create an invalid date based on time. 
     1439            if( empty($EM_DateTime) || !$EM_DateTime->valid ){ 
     1440                //create a new datetime just with the time (if set), fake date and set the valid flag to false 
     1441                $time = $valid_time ? $this->$when_time : '00:00:00'; 
     1442                $EM_DateTime = new EM_DateTime('1970-01-01 '.$time, $this->event_timezone); 
     1443                $EM_DateTime->valid = false; 
     1444            }  
     1445            //set new datetime 
     1446            $this->$when = $EM_DateTime; 
     1447        }else{ 
     1448            /* @var EM_DateTime $EM_DateTime */ 
     1449            $EM_DateTime = $this->$when; 
     1450        } 
     1451        //Set to UTC timezone if requested, local by default 
     1452        $tz = $utc_timezone ? 'UTC' : $this->event_timezone; 
     1453        $EM_DateTime->setTimezone($tz); 
     1454        return $EM_DateTime; 
    12451455    } 
    12461456     
     
    15041714        foreach($results[0] as $result) { 
    15051715            if(substr($result, 0, 3 ) == "#@_"){ 
    1506                 $date = 'end_date'; 
     1716                $date = 'end'; 
    15071717                $offset = 4; 
    15081718            }else{ 
    1509                 $date = 'start_date'; 
     1719                $date = 'start'; 
    15101720                $offset = 3; 
    15111721            } 
    1512             if( $date == 'end_date' && $this->event_end_date == $this->event_start_date ){ 
     1722            if( $date == 'end' && $this->event_end_date == $this->event_start_date ){ 
    15131723                $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) ); 
    15141724            }else{ 
    1515                 $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) ); 
     1725                $date_format = substr( $result, $offset, (strlen($result)-($offset+1)) ); 
     1726                $replace = apply_filters('em_event_output_placeholder', $this->$date()->i18n($date_format), $this, $result, $target); 
    15161727            } 
    15171728            $event_string = str_replace($result,$replace,$event_string ); 
     
    15711782                        //are the booking times exactly the same and it's not an all-day event. 
    15721783                        $show_condition = ( $this->event_start_time == $this->event_end_time && !$this->event_all_day ); 
     1784                    }elseif ($condition == 'different_timezone'){ 
     1785                        //current event timezone is different to blog timezone 
     1786                        $show_condition = $this->event_timezone != EM_DateTimeZone::create()->getName(); 
     1787                    }elseif ($condition == 'same_timezone'){ 
     1788                        //current event timezone is different to blog timezone 
     1789                        $show_condition = $this->event_timezone == EM_DateTimeZone::create()->getName(); 
    15731790                    }elseif ($condition == 'all_day'){ 
    15741791                        //is it an all day event 
     
    16071824                        //if event is past 
    16081825                        if( get_option('dbem_events_current_are_past') ){ 
    1609                             $show_condition = $this->start <= current_time('timestamp'); 
     1826                            $show_condition = $this->start()->getTimestamp() <= time(); 
    16101827                        }else{ 
    1611                             $show_condition = $this->end <= current_time('timestamp'); 
     1828                            $show_condition = $this->end()->getTimestamp() <= time(); 
    16121829                        } 
    16131830                    }elseif ($condition == 'is_future'){ 
    16141831                        //if event is upcoming 
    1615                         $show_condition = $this->start > current_time('timestamp'); 
     1832                        $show_condition = $this->start()->getTimestamp() > time(); 
    16161833                    }elseif ($condition == 'is_current'){ 
    16171834                        //if event is currently happening 
    1618                         $ts = current_time('timestamp'); 
    1619                         $show_condition = $this->start <= $ts && $this->end >= $ts; 
     1835                        $show_condition = $this->start()->getTimestamp() <= time() && $this->end()->getTimestamp() >= time(); 
    16201836                    }elseif ($condition == 'is_recurrence'){ 
    16211837                        //if event is a recurrence 
     
    17651981                case '#_24HSTARTTIME': 
    17661982                case '#_24HENDTIME': 
    1767                     $time = ($result == '#_24HSTARTTIME') ? $this->event_start_time:$this->event_end_time; 
    1768                     $replace = substr($time, 0,5); 
     1983                    $replace = ($result == '#_24HSTARTTIME') ? $this->start()->format('H:i'):$this->end()->format('H:i'); 
    17691984                    break; 
    17701985                case '#_12HSTARTTIME': 
    17711986                case '#_12HENDTIME': 
    1772                     $time = ($result == '#_12HSTARTTIME') ? $this->event_start_time:$this->event_end_time; 
    1773                     $replace = date('g:i A', strtotime($time)); 
     1987                    $replace = ($result == '#_12HSTARTTIME') ? $this->start()->format('g:i A'):$this->end()->format('g:i A'); 
    17741988                    break; 
    17751989                case '#_EVENTTIMES': 
     
    17801994                    //get format of time to show 
    17811995                    $replace = $this->output_dates(); 
     1996                    break; 
     1997                case '#_EVENTTIMEZONE': 
     1998                    $replace = str_replace('_', ' ', $this->event_timezone); 
     1999                    break; 
     2000                case '#_EVENTTIMEZONERAW': 
     2001                    $replace = $this->event_timezone; 
    17822002                    break; 
    17832003                //Links 
     
    19282148                case '#_BOOKINGSCUTOFFTIME': 
    19292149                    $replace = ''; 
    1930                     if ($this->event_rsvp && get_option('dbem_rsvp_enabled') && !empty($this->rsvp_end)) { 
    1931                         $replace_format = get_option('dbem_date_format').' '. get_option('dbem_time_format'); 
    1932                         if( $result == '#_BOOKINGSCUTOFFDATE' ) $replace_format = get_option('dbem_date_format'); 
    1933                         if( $result == '#_BOOKINGSCUTOFFTIME' ) $replace_format = get_option('dbem_time_format'); 
    1934                         $replace = date($replace_format, $this->rsvp_end); 
     2150                    if ($this->event_rsvp && get_option('dbem_rsvp_enabled') ) { 
     2151                        $replace_format = em_get_date_format() .' '. em_get_hour_format(); 
     2152                        if( $result == '#_BOOKINGSCUTOFFDATE' ) $replace_format = em_get_date_format(); 
     2153                        if( $result == '#_BOOKINGSCUTOFFTIME' ) $replace_format = em_get_hour_format(); 
     2154                        $replace = $this->rsvp_end()->format($replace_format); 
    19352155                    } 
    19362156                    break; 
     
    20342254                    //get dates in UTC/GMT time 
    20352255                    if($this->event_all_day && $this->event_start_date == $this->event_end_date){ 
    2036                         $dateStart  = get_gmt_from_date(date('Y-m-d H:i:s', $this->start), 'Ymd'); 
    2037                         $dateEnd    = get_gmt_from_date(date('Y-m-d H:i:s', $this->start + 60*60*24), 'Ymd'); 
     2256                        $dateStart  = $this->start()->format('Ymd'); 
     2257                        $dateEnd    = $this->end()->clone()->add( new DateInterval('P1D') )->format('Ymd'); 
    20382258                    }else{ 
    2039                         $dateStart  = get_gmt_from_date(date('Y-m-d H:i:s', $this->start), 'Ymd\THis\Z'); 
    2040                         $dateEnd = get_gmt_from_date(date('Y-m-d H:i:s', $this->end), 'Ymd\THis\Z'); 
     2259                        $dateStart  = $this->start()->format('Ymd\THis'); 
     2260                        $dateEnd = $this->end()->format('Ymd\THis'); 
    20412261                    } 
    20422262                    //build url 
    2043                     $gcal_url = 'http://www.google.com/calendar/event?action=TEMPLATE&text=event_name&dates=start_date/end_date&details=post_content&location=location_name&trp=false&sprop=event_url&sprop=name:blog_name'; 
     2263                    $gcal_url = 'http://www.google.com/calendar/event?action=TEMPLATE&text=event_name&dates=start_date/end_date&details=post_content&location=location_name&trp=false&sprop=event_url&sprop=name:blog_name&ctz=event_timezone'; 
    20442264                    $gcal_url = str_replace('event_name', urlencode($this->event_name), $gcal_url); 
    20452265                    $gcal_url = str_replace('start_date', urlencode($dateStart), $gcal_url); 
     
    20482268                    $gcal_url = str_replace('blog_name', urlencode(get_bloginfo()), $gcal_url); 
    20492269                    $gcal_url = str_replace('event_url', urlencode($this->get_permalink()), $gcal_url); 
     2270                    $gcal_url = str_replace('event_timezone', urlencode($this->event_timezone), $gcal_url); 
    20502271                    //calculate URL length so we know how much we can work with to make a description. 
    20512272                    if( !empty($this->post_excerpt) ){ 
     
    20892310            // matches all PHP START date and time placeholders 
    20902311            if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) { 
    2091                 $replace = date_i18n(ltrim($result, "#"), $this->start); 
     2312                $replace = $this->start()->i18n(ltrim($result, "#")); 
    20922313                $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target); 
    20932314                $event_string = str_replace($result, $replace, $event_string ); 
     
    20952316            // matches all PHP END time placeholders for endtime 
    20962317            if (preg_match('/^#@[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) { 
    2097                 $replace = date_i18n(ltrim($result, "#@"), $this->end); 
     2318                $replace = $this->end()->i18n(ltrim($result, "#@")); 
    20982319                $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target); 
    20992320                $event_string = str_replace($result, $replace, $event_string );  
     
    21402361    } 
    21412362     
    2142     function output_times(){ 
     2363    function output_times( $time_format = false, $time_separator = false , $all_day_message = false ){ 
    21432364        if( !$this->event_all_day ){ 
    2144             $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format'); 
    2145             if($this->event_start_time != $this->event_end_time ){ 
    2146                 $replace = date_i18n($time_format, $this->start). get_option('dbem_times_separator') . date_i18n($time_format, $this->end); 
     2365            if( empty($time_format) ) $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format'); 
     2366            if( empty($time_separator) ) $time_separator = get_option('dbem_times_separator'); 
     2367            if( $this->event_start_time != $this->event_end_time ){ 
     2368                $replace = $this->start()->i18n($time_format). $time_separator . $this->end()->i18n($time_format); 
    21472369            }else{ 
    2148                 $replace = date_i18n($time_format, $this->start); 
     2370                $replace = $this->start()->i18n($time_format); 
    21492371            } 
    21502372        }else{ 
     
    21542376    } 
    21552377     
    2156     function output_dates(){ 
    2157         $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format'); 
     2378    function output_dates( $date_format = false, $date_separator = false ){ 
     2379        if( empty($date_format) ) $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format'); 
     2380        if( empty($date_separator) ) $date_separator = get_option('dbem_dates_separator'); 
    21582381        if( $this->event_start_date != $this->event_end_date){ 
    2159             $replace = date_i18n($date_format, $this->start). get_option('dbem_dates_separator') . date_i18n($date_format, $this->end); 
     2382            $replace = $this->start()->i18n($date_format). $date_separator . $this->end()->i18n($date_format); 
    21602383        }else{ 
    2161             $replace = date_i18n($date_format, $this->start); 
     2384            $replace = $this->start()->i18n($date_format); 
    21622385        } 
    21632386        return $replace; 
     
    22822505            foreach( $this->recurrence_fields as $recurrence_field){ 
    22832506                $event[$recurrence_field] = null; 
    2284                 unset($meta_fields['_'.$recurrence_field]); 
     2507                if( isset($meta_fields['_'.$recurrence_field]) ) unset($meta_fields['_'.$recurrence_field]); 
    22852508            } 
    22862509            //Set the recurrence ID 
     
    22992522                if( count($matching_days) > 0 ){ 
    23002523                    //first save event post data 
     2524                    $EM_DateTime = $this->start()->clone(); 
    23012525                    foreach( $matching_days as $day ) { 
     2526                        //set start date/time to $EM_DateTime for relative use further on 
     2527                        $EM_DateTime->setTimestamp($day)->setTimeString($event['event_start_time']); 
     2528                        $start_timestamp = $EM_DateTime->getTimestamp(); //for quick access later 
    23022529                        //rewrite post fields if needed 
    2303                         $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $day), $post_fields, $day, $matching_days, $this); 
    2304                         //adjust certain meta information 
    2305                         $event['event_start_date'] = $meta_fields['_event_start_date'] = date("Y-m-d", $day); 
    2306                         $meta_fields['_start_ts'] = strtotime($event['event_start_date'].' '.$event['event_start_time']); 
     2530                        $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.$EM_DateTime->format($recurring_date_format), $post_fields, $day, $matching_days, $this); 
     2531                        //set start date 
     2532                        $event['event_start_date'] = $meta_fields['_event_start_date'] = $EM_DateTime->getDate(); 
     2533                        $event['event_start'] = $meta_fields['_event_start'] = $EM_DateTime->getDateTime(true); 
     2534                        //add rsvp date/time restrictions 
    23072535                        if( !empty($this->recurrence_rsvp_days) && is_numeric($this->recurrence_rsvp_days) ){ 
    23082536                            $event_rsvp_days = $this->recurrence_rsvp_days >= 0 ? '+'. $this->recurrence_rsvp_days: $this->recurrence_rsvp_days; 
    2309                             $event_rsvp_date = date('Y-m-d',  strtotime($event_rsvp_days.' days', $meta_fields['_start_ts'])); 
     2537                            $event_rsvp_date = $EM_DateTime->clone()->add( new DateInterval('P'.$event_rsvp_days.'D') )->getDate(); //cloned so original object isn't modified 
    23102538                            $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date; 
    23112539                        }else{ 
     
    23132541                        } 
    23142542                        $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time']; 
     2543                        //set end date 
     2544                        $EM_DateTime->setTimeString($event['event_end_time']); 
    23152545                        if($this->recurrence_days > 0){ 
    2316                             $event['event_end_date'] = $meta_fields['_event_end_date'] = date("Y-m-d", $meta_fields['_start_ts'] + ($this->recurrence_days * 60*60*24)); 
     2546                            //$EM_DateTime modified here, and used further down for UTC end date 
     2547                            $event['event_end_date'] = $meta_fields['_event_end_date'] = $EM_DateTime->add( new DateInterval('P'.$this->recurrence_days.'D') )->getDate(); 
    23172548                        }else{ 
    23182549                            $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date']; 
    2319                         }    
    2320                         $meta_fields['_end_ts'] = strtotime($event['event_end_date'].' '.$event['event_end_time']); 
     2550                        } 
     2551                        $end_timestamp = $EM_DateTime->getTimestamp(); //for quick access later 
     2552                        $event['event_end'] = $meta_fields['_event_end'] = $EM_DateTime->getDateTime(true); 
     2553                        //add extra date/time post meta 
     2554                        $meta_fields['_event_start_local'] = $event['event_start_date'].' '.$event['event_start_time']; 
     2555                        $meta_fields['_event_end_local'] = $event['event_end_date'].' '.$event['event_end_time']; 
     2556                        //Deprecated meta fields 
     2557                        $admin_data = get_option('dbem_admin_data'); 
     2558                        if( $admin_data['datetime_backcompat'] ){ 
     2559                            $meta_fields['_start_ts'] = $start_timestamp; 
     2560                            $meta_fields['_end_ts'] = $end_timestamp; 
     2561                        } 
    23212562                        //create the event 
    23222563                        if( $wpdb->insert($wpdb->posts, $post_fields ) ){ 
     
    23272568                            $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event); 
    23282569                            $event_ids[$post_id] = $event_id = $wpdb->insert_id; 
    2329                             $event_dates[$event_id] = $meta_fields['_start_ts']; 
     2570                            $event_dates[$event_id] = $start_timestamp; 
    23302571                            //create the meta inserts for each event 
    23312572                            $meta_fields['_event_id'] = $event_id; 
     
    23572598                unset( $post_fields['comment_count'], $post_fields['guid'], $post_fields['menu_order']); 
    23582599                //now we go through the recurrences and check whether things relative to dates need to be changed 
    2359                 //@todo do a direct DB lookup once we have timezones implemented to save processing and memory 
    2360                 $EM_Events = EM_Events::get( array('recurrence'=>$this->event_id, 'scope'=>'all', 'status'=>'everything' ) ); 
    2361                 foreach($EM_Events as $EM_Event){ /* @var $EM_Event EM_Event */ 
    2362                     $event_ids[$EM_Event->post_id] = $EM_Event->event_id; 
    2363                     $event_dates[$EM_Event->event_id] = $EM_Event->start; 
    2364                     $post_ids[] = $EM_Event->post_id; 
     2600                $events = EM_Events::get( array('recurrence'=>$this->event_id, 'scope'=>'all', 'status'=>'everything', 'array' => true ) ); 
     2601                foreach($events as $event_array){ /* @var $EM_Event EM_Event */ 
     2602                    //set new start/end times to obtain accurate timestamp according to timezone and DST 
     2603                    $EM_DateTime = $this->start()->clone()->modify($event_array['event_start_date']. ' ' . $event_array['event_start_time']); 
     2604                    $start_timestamp = $EM_DateTime->getTimestamp(); 
     2605                    $event['event_start'] = $meta_fields['_event_start'] = $EM_DateTime->getDateTime(true); 
     2606                    $end_timestamp = $EM_DateTime->modify($event_array['event_end_date']. ' ' . $event_array['event_end_time'])->getTimestamp(); 
     2607                    $event['event_end'] = $meta_fields['_event_end'] = $EM_DateTime->getDateTime(true); 
     2608                    //set indexes for reference further down 
     2609                    $event_ids[$event_array['post_id']] = $event_array['event_id']; 
     2610                    $event_dates[$event_array['event_id']] = $start_timestamp; 
     2611                    $post_ids[] = $event_array['post_id']; 
    23652612                    //do we need to change the slugs? 
    2366                     $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $EM_Event->start), $post_fields, $EM_Event->start, array(), $this); 
    2367                     //adjust certain meta information relativv 
     2613                    $post_fields['post_name'] = $event['event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.$EM_DateTime->setTimestamp($start_timestamp)->format($recurring_date_format), $post_fields, $start_timestamp, array(), $this); 
     2614                    //adjust certain meta information relative to dates and times 
    23682615                    if( !empty($this->recurrence_rsvp_days) && is_numeric($this->recurrence_rsvp_days) ){ 
    23692616                        $event_rsvp_days = $this->recurrence_rsvp_days >= 0 ? '+'. $this->recurrence_rsvp_days: $this->recurrence_rsvp_days; 
    2370                         $event_rsvp_date = date('Y-m-d',  strtotime($event_rsvp_days.' days', $EM_Event->start)); 
     2617                        $event_rsvp_date = $EM_DateTime->setTimestamp($start_timestamp)->modify($event_rsvp_days.' days')->getDate(); 
    23712618                        $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date; 
    23722619                    }else{ 
    2373                         $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $EM_Event->event_start_date; 
     2620                        $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_array['event_start_date']; 
    23742621                    } 
    23752622                    $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time']; 
    23762623                    //add meta fields we deleted and are specific to this event 
    2377                     $meta_fields['_event_start_date'] = $EM_Event->event_start_date; 
    2378                     $meta_fields['_event_end_date'] = $EM_Event->event_end_date; 
    2379                     $meta_fields['_start_ts'] = strtotime($EM_Event->event_start_date." ".$this->event_start_time); 
    2380                     $meta_fields['_end_ts'] = strtotime($EM_Event->event_end_date." ".$this->event_end_time); 
     2624                    $meta_fields['_event_start_date'] = $event_array['event_start_date']; 
     2625                    $meta_fields['_event_start_local'] = $event_array['event_start_date']. ' ' . $event_array['event_start_time']; 
     2626                    $meta_fields['_event_end_date'] = $event_array['event_end_date']; 
     2627                    $meta_fields['_event_end_local'] = $event_array['event_end_date']. ' ' . $event_array['event_end_time']; 
     2628                    $admin_data = get_option('dbem_admin_data'); 
     2629                    if( $admin_data['datetime_backcompat'] ){ 
     2630                        $meta_fields['_start_ts'] = $start_timestamp; 
     2631                        $meta_fields['_end_ts'] = $end_timestamp; 
     2632                    } 
    23812633                    //overwrite event and post tables 
    2382                     $wpdb->update(EM_EVENTS_TABLE, $event, array('event_id' => $EM_Event->event_id)); 
    2383                     $wpdb->update($wpdb->posts, $post_fields, array('ID' => $EM_Event->post_id)); 
     2634                    $wpdb->update(EM_EVENTS_TABLE, $event, array('event_id' => $event_array['event_id'])); 
     2635                    $wpdb->update($wpdb->posts, $post_fields, array('ID' => $event_array['post_id'])); 
    23842636                    //save meta field data for insertion in one go 
    23852637                    foreach($meta_fields as $meta_key => $meta_val){ 
    2386                         $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($EM_Event->post_id, $meta_key, $meta_val)); 
     2638                        $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($event_array['post_id'], $meta_key, $meta_val)); 
    23872639                    } 
    23882640                } 
     
    24032655                //first, delete all bookings & tickets if we haven't done so during the reschedule above - something we'll want to change later if possible so bookings can be modified without losing all data 
    24042656                if( !$this->recurring_reschedule ){ 
    2405                     foreach($EM_Events as $EM_Event){ //$EM_Events was defined in the else statement above so we reuse it 
    2406                         /* @var $EM_Event EM_Event */ 
    2407                         if($EM_Event->recurrence_id == $this->event_id){ 
    2408                             $EM_Event->get_bookings()->delete(); 
    2409                             $EM_Event->get_tickets()->delete(); 
     2657                    //create empty EM_Bookings and EM_Tickets objects to circumvent extra loading of data and SQL queries 
     2658                    $EM_Bookings = new EM_Bookings(); 
     2659                    $EM_Tickets = new EM_Tickets(); 
     2660                    foreach($events as $event){ //$events was defined in the else statement above so we reuse it 
     2661                        if($event['recurrence_id'] == $this->event_id){ 
     2662                            //trick EM_Bookings and EM_Tickets to think it was loaded, and make use of optimized delete functions since 5.7.3.4 
     2663                            $EM_Bookings->event_id = $EM_Tickets->event_id = $event['event_id']; 
     2664                            $EM_Bookings->delete(); 
     2665                            $EM_Tickets->delete(); 
    24102666                        } 
    24112667                    } 
     
    24362692                            } 
    24372693                        } 
     2694                        //prep ticket meta for insertion with relative info for each event date 
     2695                        $EM_DateTime = $this->start()->clone(); 
    24382696                        foreach($event_ids as $event_id){ 
    24392697                            $ticket['event_id'] = $event_id; 
     
    24412699                            //sort out cut-of dates 
    24422700                            if( !empty($ticket_meta_recurrences) ){ 
     2701                                $EM_DateTime->setTimestamp($event_dates[$event_id]); //by using EM_DateTime we'll generate timezone aware dates 
    24432702                                if( array_key_exists('start_days', $ticket_meta_recurrences) && $ticket_meta_recurrences['start_days'] !== false  ){ 
    24442703                                    $ticket_start_days = $ticket_meta_recurrences['start_days'] >= 0 ? '+'. $ticket_meta_recurrences['start_days']: $ticket_meta_recurrences['start_days']; 
    2445                                     $ticket_start_date = date('Y-m-d',  strtotime($ticket_start_days.' days', $event_dates[$event_id])); 
     2704                                    $ticket_start_date = $EM_DateTime->modify($ticket_start_days.' days')->getDate(); 
    24462705                                    $ticket['ticket_start'] = "'". $ticket_start_date . ' '. $ticket_meta_recurrences['start_time'] ."'"; 
    24472706                                } 
    24482707                                if( array_key_exists('end_days', $ticket_meta_recurrences) && $ticket_meta_recurrences['end_days'] !== false ){ 
    24492708                                    $ticket_end_days = $ticket_meta_recurrences['end_days'] >= 0 ? '+'. $ticket_meta_recurrences['end_days']: $ticket_meta_recurrences['end_days']; 
    2450                                     $ticket_end_date = date('Y-m-d',  strtotime($ticket_end_days.' days', $event_dates[$event_id])); 
     2709                                    $EM_DateTime->setTimestamp($event_dates[$event_id]); 
     2710                                    $ticket_end_date = $EM_DateTime->modify($ticket_end_days.' days')->getDate(); 
    24512711                                    $ticket['ticket_end'] = "'". $ticket_end_date . ' '. $ticket_meta_recurrences['end_time'] . "'"; 
    24522712                                } 
     
    24622722                } 
    24632723            }elseif( $this->recurring_delete_bookings ){ 
    2464                 foreach($EM_Events as $EM_Event){ //$EM_Events was defined in the else statement above so we reuse it 
    2465                     /* @var $EM_Event EM_Event */ 
    2466                     if($EM_Event->recurrence_id == $this->event_id){ 
    2467                         $EM_Event->get_bookings()->delete(); 
    2468                         $EM_Event->get_tickets()->delete(); 
     2724                //create empty EM_Bookings and EM_Tickets objects to circumvent extra loading of data and SQL queries 
     2725                $EM_Bookings = new EM_Bookings(); 
     2726                $EM_Tickets = new EM_Tickets(); 
     2727                foreach($events as $event){ //$events was defined in the else statement above so we reuse it 
     2728                    if($event['recurrence_id'] == $this->event_id){ 
     2729                        //trick EM_Bookings and EM_Tickets to think it was loaded, and make use of optimized delete functions since 5.7.3.4 
     2730                        $EM_Bookings->event_id = $EM_Tickets->event_id = $event['event_id']; 
     2731                        $EM_Bookings->delete(); 
     2732                        $EM_Tickets->delete(); 
    24692733                    } 
    24702734                } 
     
    25412805     * @return array 
    25422806     */ 
    2543     function get_recurrence_days(){          
    2544         $start_date = strtotime($this->event_start_date); 
    2545         $end_date = strtotime($this->event_end_date); 
     2807    function get_recurrence_days(){ 
     2808        $EM_DateTime = new EM_DateTime(); 
     2809        $start_date = $EM_DateTime->modify($this->start()->getDate())->getTimestamp(); 
     2810        $end_date = $EM_DateTime->modify($this->end()->getDate())->getTimestamp(); 
    25462811                 
    25472812        $weekdays = explode(",", $this->recurrence_byday); //what days of the week (or if monthly, one value at index 0) 
     
    26312896                break; 
    26322897            case 'yearly': 
    2633                 //If yearly, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date. 
    2634                 $month = date('m', $this->start); 
    2635                 $day = date('d',$this->start); 
    2636                 $year = date('Y',$this->start); 
    2637                 $end_year = date('Y',$this->end);  
    2638                 if( @mktime(0,0,0,$day,$month,$end_year) < $this->end ) $end_year--; 
    2639                 while( $year <= $end_year ){ 
    2640                     $matching_days[] = mktime(0,0,0,$month,$day,$year); 
    2641                     $year++; 
     2898                //Yearly is easy, we get the start date as a cloned EM_DateTime and keep adding a year until it surpasses the end EM_DateTime value.  
     2899                $EM_DateTime = $this->start()->clone(); 
     2900                while( $EM_DateTime <= $this->end() ){ 
     2901                    $matching_days[] = $EM_DateTime->getTimestamp(); 
     2902                    $EM_DateTime->add('P1Y'); 
    26422903                }            
    26432904                break; 
     
    27212982            } 
    27222983        }elseif ($EM_Event_Recurring->recurrence_freq == 'yearly')  { 
    2723             $freq_desc .= __("every year", 'events-manager'); 
     2984            $freq_desc = __("every year", 'events-manager'); 
    27242985            if ($EM_Event_Recurring->recurrence_interval > 1 ) { 
    27252986                $freq_desc .= sprintf (__("every %s years",'events-manager'), $EM_Event_Recurring->recurrence_interval); 
     
    27352996     * UTILITIES 
    27362997     ***********************************************************/ 
    2737      
    2738     function __get( $var ){ 
    2739         //get the modified or created date from the DB only if requested, and save to object 
    2740         if( $var == 'event_date_modified' || $var == 'event_date_created'){ 
    2741             global $wpdb; 
    2742             $row = $wpdb->get_row($wpdb->prepare("SELECT event_date_created, event_date_modified FROM ".EM_EVENTS_TABLE.' WHERE event_id=%s', $this->event_id)); 
    2743             if( $row ){ 
    2744                 $this->event_date_modified = $row->event_date_modified; 
    2745                 $this->event_date_created = $row->event_date_created; 
    2746                 return $this->$var; 
    2747             } 
    2748         } 
    2749         return null; 
     2998    function to_array( $db = false ){ 
     2999        $event_array = parent::to_array($db); 
     3000        //we reset start/end datetimes here, based on the EM_DateTime objects if they are valid 
     3001        $event_array['event_start'] = $this->start()->valid ? $this->start(true)->format('Y-m-d H:i:s') : null; 
     3002        $event_array['event_end'] = $this->end()->valid ? $this->end(true)->format('Y-m-d H:i:s') : null; 
     3003        return apply_filters('em_event_to_array', $event_array, $this); 
    27503004    } 
    27513005     
  • events-manager/trunk/classes/em-events.php

    r1765726 r1786433  
    361361        $args['offset'] = ($args['page']-1) * $args['limit']; 
    362362        $args['orderby'] = 'event_start_date,event_start_time,event_name'; // must override this to display events in right cronology. 
     363        $long_events = !empty($args['long_events']); 
    363364 
    364365        $args['mode'] = !empty($args['mode']) ? $args['mode'] : get_option('dbem_event_list_groupby'); 
     
    380381                    $events_dates = array(); 
    381382                    foreach($EM_Events as $EM_Event){ /* @var $EM_Event EM_Event */ 
    382                         $year = date('Y',$EM_Event->start); 
     383                        $year = $EM_Event->start()->format('Y'); 
    383384                        $events_dates[$year][] = $EM_Event; 
    384385                        //if long events requested, add event to other dates too 
    385                         if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) { 
     386                        if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) { 
    386387                            $next_year = $year + 1; 
    387                             $year_end = date('Y', $EM_Event->end); 
     388                            $year_end = $EM_Event->end()->format('Y'); 
    388389                            while( $next_year <= $year_end ){ 
    389390                                $events_dates[$next_year][] = $EM_Event; 
     
    402403                    $events_dates = array(); 
    403404                    foreach($EM_Events as $EM_Event){ 
    404                         $events_dates[date('Y-m-'.'01', $EM_Event->start)][] = $EM_Event; 
     405                        $events_dates[$EM_Event->start()->format('Y-m-01')][] = $EM_Event; 
    405406                        //if long events requested, add event to other dates too 
    406                         if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) { 
    407                             $next_month = strtotime("+1 Month", $EM_Event->start); 
    408                             while( $next_month <= $EM_Event->end ){ 
    409                                 $events_dates[date('Y-m-'.'01',$next_month)][] = $EM_Event; 
    410                                 $next_month = strtotime("+1 Month", $next_month); 
     407                        if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) { 
     408                            $next_month = $EM_Event->start()->clone()->add('P1M'); 
     409                            while( $next_month <= $EM_Event->end() ){ 
     410                                $events_dates[$next_month->format('Y-m-01')][] = $EM_Event; 
     411                                $next_month = $next_month->add('P1M'); 
    411412                            } 
    412413                        } 
     
    422423                    foreach($EM_Events as $EM_Event){ 
    423424                        $start_of_week = get_option('start_of_week'); 
    424                         $day_of_week = date('w',$EM_Event->start); 
    425                         $day_of_week = date('w',$EM_Event->start); 
     425                        $day_of_week = $EM_Event->start()->format('w'); 
    426426                        $offset = $day_of_week - $start_of_week; 
    427427                        if($offset<0){ $offset += 7; } 
    428                         $offset = $offset * 60*60*24; //days in seconds 
    429                         $start_day = strtotime($EM_Event->start_date); 
    430                         $events_dates[$start_day - $offset][] = $EM_Event; 
     428                        $EM_DateTime = $EM_Event->start()->sub('P'.$offset.'D'); 
     429                        $events_dates[$EM_DateTime->getTimestamp()][] = $EM_Event; 
    431430                        //if long events requested, add event to other dates too 
    432                         if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) { 
    433                             $next_week = $start_day - $offset + (86400 * 7); 
    434                             while( $next_week <= $EM_Event->end ){ 
     431                        if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) { 
     432                            do{ 
     433                                $EM_DateTime->add('P1W'); 
    435434                                $events_dates[$next_week][] = $EM_Event; 
    436                                 $next_week = $next_week + (86400 * 7); 
    437                             } 
     435                            }while( $EM_DateTime <= $EM_Event->end() ); 
    438436                        } 
    439437                    } 
     
    448446                    $events_dates = array(); 
    449447                    foreach($EM_Events as $EM_Event){ 
    450                         $event_start_date = strtotime($EM_Event->start_date); 
    451                         $events_dates[$event_start_date][] = $EM_Event; 
     448                        $EM_DateTime = $EM_Event->start()->clone()->setTime(0,0,0); /* @var EM_DateTime $EM_DateTime */ 
     449                        $events_dates[$EM_DateTime->getTimestamp()][] = $EM_Event; 
    452450                        //if long events requested, add event to other dates too 
    453                         if( empty($args['limit']) && !empty($args['long_events']) && $EM_Event->event_end_date != $EM_Event->event_start_date ) { 
    454                             $tomorrow = $event_start_date + 86400; 
    455                             while( $tomorrow <= $EM_Event->end ){ 
    456                                 $events_dates[$tomorrow][] = $EM_Event; 
    457                                 $tomorrow = $tomorrow + 86400; 
    458                             } 
     451                        if( empty($args['limit']) && $long_events && $EM_Event->end()->getDate() != $EM_Event->start()->getDate() ) { 
     452                            do{ 
     453                                $EM_DateTime->add('P1D'); 
     454                                $events_dates[$EM_DateTime->getTimestamp()][] = $EM_Event; 
     455                            }while( $EM_DateTime <= $EM_Event->end() ); 
    459456                        } 
    460457                    } 
  • events-manager/trunk/classes/em-object.php

    r1722840 r1786433  
    2727            'limit' => false, 
    2828            'scope' => 'future', 
     29            'timezone' => false, //default blog timezone 
    2930            'order' => 'ASC', //hard-coded at end of this function 
    3031            'orderby' => false, 
     
    114115                if( !array_key_exists($key, $defaults) && !array_key_exists($key, $taxonomies) ) unset($array[$key]);        
    115116            } 
     117            //Timezone 
     118            if( !empty($array['timezone']) ){ 
     119                if( !is_array($array['timezone']) ) { 
     120                    $array['timezone'] = str_replace(' ', '', $array['timezone']); 
     121                    $array['timezone'] = explode(',', $array['timezone']); 
     122                } 
     123            } 
    116124            //return clean array 
    117125            $defaults = array_merge ( $defaults, $array ); //No point using WP's cleaning function, we're doing it already. 
     
    213221        $month = $args['month']; 
    214222        $year = $args['year']; 
    215         $today = date('Y-m-d', current_time('timestamp')); 
    216223        //Create the WHERE statement 
    217224        $conditions = array(); 
     
    271278            } 
    272279        } 
     280         
     281        //Timezone - search for events in a specific timezone 
     282        if( !empty($args['timezone']) ){ 
     283            if( !is_array($args['timezone']) ){ 
     284                $args['timezone'] = explode(',', $args['timezone']); 
     285            } 
     286            foreach( $args['timezone'] as $tz ) $timezones[] = $wpdb->prepare('%s', $tz); 
     287            $conditions['timezone'] = '`event_timezone` IN ('.implode(',', $timezones).')'; 
     288        } 
     289         
    273290        //Dates - first check 'month', and 'year', and adjust scope if needed 
    274291        if( !($month=='' && $year=='') ){ 
     
    296313            $scope = array($date_start,$date_end); //just modify the scope here 
    297314        } 
    298         //No date requested, so let's look at scope 
     315        //Build scope query 
    299316        if ( is_array($scope) ) { 
    300317            //This is an array, let's split it up 
     
    328345            } 
    329346        } else { 
     347            $EM_DateTime = new EM_DateTime(); //the time, now, in blog/site timezone 
    330348            if ($scope == "past"){ 
    331349                if( get_option('dbem_events_current_are_past') ){ 
    332                     $conditions['scope'] = " event_start_date < '$today'"; 
     350                    $conditions['scope'] = " event_start < '".$EM_DateTime->getDateTime(true)."'"; 
    333351                }else{ 
    334                     $conditions['scope'] = " event_end_date < '$today'"; 
     352                    $conditions['scope'] = " event_end < '".$EM_DateTime->getDateTime(true)."'"; 
    335353                }   
    336354            }elseif ($scope == "today"){ 
    337                 $conditions['scope'] = " (event_start_date = CAST('$today' AS DATE))"; 
     355                $conditions['scope'] = " (event_start_date = CAST('".$EM_DateTime->getDate()."' AS DATE))"; 
    338356                if( !get_option('dbem_events_current_are_past') ){ 
    339                     $conditions['scope'] .= " OR (event_start_date <= CAST('$today' AS DATE) AND event_end_date >= CAST('$today' AS DATE))"; 
     357                    $conditions['scope'] .= " OR (event_start_date <= CAST('".$EM_DateTime->getDate()."' AS DATE) AND event_end_date >= CAST('$EM_DateTime' AS DATE))"; 
    340358                } 
    341359            }elseif ($scope == "tomorrow"){ 
    342                 $tomorrow = date('Y-m-d',current_time('timestamp')+60*60*24); 
    343                 $conditions['scope'] = "(event_start_date = CAST('$tomorrow' AS DATE))"; 
     360                $EM_DateTime->modify('+1 day'); 
     361                $conditions['scope'] = "(event_start_date = CAST('".$EM_DateTime->getDate()."' AS DATE))"; 
    344362                if( !get_option('dbem_events_current_are_past') ){ 
    345                     $conditions['scope'] .= " OR (event_start_date <= CAST('$tomorrow' AS DATE) AND event_end_date >= CAST('$tomorrow' AS DATE))"; 
    346                 } 
    347             }elseif ($scope == "month"){ 
    348                 $start_month = date('Y-m-d',current_time('timestamp')); 
    349                 $end_month = date('Y-m-t',current_time('timestamp')); 
     363                    $conditions['scope'] .= " OR (event_start_date <= CAST('".$EM_DateTime->getDate()."' AS DATE) AND event_end_date >= CAST('".$EM_DateTime->getDate()."' AS DATE))"; 
     364                } 
     365            }elseif ($scope == "month" || $scope == "next-month"){ 
     366                if( $scope == 'next-month' ) $EM_DateTime->add( new DateInterval('P1M') ); 
     367                $start_month = $EM_DateTime->modify('first day of this month')->getDate(); 
     368                $end_month = $EM_DateTime->modify('last day of this month')->getDate(); 
    350369                $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))"; 
    351370                if( !get_option('dbem_events_current_are_past') ){ 
    352371                    $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))"; 
    353372                } 
    354             }elseif ($scope == "next-month"){ 
    355                 $start_month_timestamp = strtotime('+1 month', current_time('timestamp')); //get the end of this month + 1 day 
    356                 $start_month = date('Y-m-1',$start_month_timestamp); 
    357                 $end_month = date('Y-m-t',$start_month_timestamp); 
     373            }elseif( preg_match('/([0-9]+)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month. 
     374                $months_to_add = $matches[1]; 
     375                $start_month = $EM_DateTime->getDate(); 
     376                $end_month = $EM_DateTime->add( new DateInterval('P'.$months_to_add.'M') )->format('Y-m-t'); 
    358377                $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))"; 
    359378                if( !get_option('dbem_events_current_are_past') ){ 
    360379                    $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))"; 
    361380                } 
    362             }elseif( preg_match('/([0-9]+)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month. 
    363                 $months_to_add = $matches[1]; 
    364                 $start_month = date('Y-m-d',current_time('timestamp')); 
    365                 $end_month = date('Y-m-t',strtotime("+$months_to_add month", current_time('timestamp'))); 
    366                 $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))"; 
     381            }elseif ($scope == "future"){ 
     382                $conditions['scope'] = " event_start >= '".$EM_DateTime->getDateTime(true)."'"; 
    367383                if( !get_option('dbem_events_current_are_past') ){ 
    368                     $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))"; 
    369                 } 
    370             }elseif ($scope == "future"){ 
    371                 $conditions['scope'] = " event_start_date >= CAST('$today' AS DATE)"; 
    372                 if( !get_option('dbem_events_current_are_past') ){ 
    373                     $conditions['scope'] .= " OR (event_end_date >= CAST('$today' AS DATE) AND event_end_date != '0000-00-00' AND event_end_date IS NOT NULL)"; 
     384                    $conditions['scope'] .= " OR (event_end >= '".$EM_DateTime->getDateTime(true)."')"; 
    374385                } 
    375386            } 
     
    614625     
    615626    /** 
    616      * WORK IN PROGRESS 
     627     * WORK IN PROGRESS - not recommended for production use due to lack of syncing with regular condition builder and timezones feature 
    617628     * Builds an array of SQL query conditions based on regularly used arguments 
    618629     * @param array $args 
     
    637648        $month = $args['month']; 
    638649        $year = $args['year']; 
    639         $today = date('Y-m-d', current_time('timestamp')); 
    640650        //Create the WHERE statement 
    641651         
     
    671681        } 
    672682        //No date requested, so let's look at scope 
    673         $time = current_time('timestamp'); 
    674         if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) { 
    675             $today = strtotime($scope); 
    676             $tomorrow = $today + 60*60*24-1; 
    677             if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    678                 $query[] = array( 'key' => '_start_ts', 'value' => array($today,$tomorrow), 'compare' => 'BETWEEN' ); 
    679             }else{ 
    680                 $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' ); 
    681                 $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
    682             }                
    683         }elseif ( is_array($scope) || preg_match( "/^[0-9]{4}-[0-9]{2}-[0-9]{2},[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) { 
     683        if ( is_array($scope) || preg_match( "/^[0-9]{4}-[0-9]{2}-[0-9]{2},[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) { 
    684684            if( !is_array($scope) ) $scope = explode(',',$scope); 
    685685            if( !empty($scope[0]) ){ 
    686                 $start = strtotime(date('Y-m-d',$scope[0])); 
    687                 $end = !empty($scope[1]) ? strtotime(date('Y-m-t',$scope[1])):$start; 
     686                $EM_DateTime = new EM_DateTime($scope[0]); //create default time in blog timezone 
     687                $start_date = $EM_DateTime->getDate(); 
     688                $end_date = $EM_DateTime->modify($scope[1])->getDate(); 
    688689                if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    689                     $query[] = array( 'key' => '_start_ts', 'value' => array($start,$end), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
     690                    $query[] = array( 'key' => '_event_start_date', 'value' => array($start_date,$end_date), 'type' => 'DATE', 'compare' => 'BETWEEN'); 
    690691                }else{ 
    691                     $query[] = array( 'key' => '_start_ts', 'value' => $end, 'compare' => '<=' ); 
    692                     $query[] = array( 'key' => '_end_ts', 'value' => $start, 'compare' => '>=' ); 
    693                 } 
    694             } 
    695         }elseif ($scope == "future"){ 
    696             $today = strtotime(date('Y-m-d', $time)); 
     692                    $query[] = array( 'key' => '_event_start_date', 'value' => $end_date, 'compare' => '<=', 'type' => 'DATE' ); 
     693                    $query[] = array( 'key' => '_event_end_date', 'value' => $start_date, 'compare' => '>=', 'type' => 'DATE' ); 
     694                } 
     695            } 
     696        }elseif ( $scope == 'today' || $scope == 'tomorrow' || preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) { 
     697            $EM_DateTime = new EM_DateTime($scope); //create default time in blog timezone 
    697698            if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    698                 $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' ); 
     699                $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate() ); 
    699700            }else{ 
    700                 $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
    701             } 
    702         }elseif ($scope == "past"){ 
    703             $today = strtotime(date('Y-m-d', $time)); 
     701                $query[] = array( 'key' => '_event_start_date', 'value' => $EM_DateTime->getDate(), 'compare' => '<=', 'type' => 'DATE' ); 
     702                $query[] = array( 'key' => '_event_end_date', 'value' => $EM_DateTime->getDate(), 'compare' => '>=', 'type' => 'DATE' ); 
     703            }                
     704        }elseif ($scope == "future" || $scope == 'past' ){ 
     705            $EM_DateTime = new EM_DateTime(); //create default time in blog timezone 
     706            $EM_DateTime->setTimezone('UTC'); 
     707            $compare = $scope == 'future' ? '>=' : '<'; 
    704708            if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    705                 $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<' ); 
     709                $query[] = array( 'key' => '_event_start', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' ); 
    706710            }else{ 
    707                 $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '<' ); 
    708             } 
    709         }elseif ($scope == "today"){ 
    710             $today = strtotime(date('Y-m-d', $time)); 
     711                $query[] = array( 'key' => '_event_end', 'value' => $EM_DateTime->getDateTime(), 'compare' => $compare, 'type' => 'DATETIME' ); 
     712            } 
     713        }elseif ($scope == "month" || $scope == "next-month" ){ 
     714            $EM_DateTime = new EM_DateTime(); //create default time in blog timezone 
     715            if( $scope == 'next-month' ) $EM_DateTime->add( new DateInterval('P1M') ); 
     716            $start_month = $EM_DateTime->modify('first day of this month')->getDate(); 
     717            $end_month = $EM_DateTime->modify('last day of this month')->getDate(); 
    711718            if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    712                 //date must be only today 
    713                 $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '='); 
     719                $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN'); 
    714720            }else{ 
    715                 $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<=' ); 
    716                 $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
    717             } 
    718         }elseif ($scope == "tomorrow"){ 
    719             $tomorrow = strtotime(date('Y-m-d',$time+60*60*24)); 
     721                $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' ); 
     722                $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' ); 
     723            } 
     724        }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month. 
     725            $EM_DateTime = new EM_DateTime(); //create default time in blog timezone 
     726            $months_to_add = $matches[1]; 
     727            $start_month = $EM_DateTime->getDate(); 
     728            $end_month = $EM_DateTime->add( new DateInterval('P'.$months_to_add.'M') )->format('Y-m-t'); 
    720729            if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    721                 //date must be only tomorrow 
    722                 $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '='); 
     730                $query[] = array( 'key' => '_event_start_date', 'value' => array($start_month,$end_month), 'type' => 'DATE', 'compare' => 'BETWEEN'); 
    723731            }else{ 
    724                 $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' ); 
    725                 $query[] = array( 'key' => '_end_ts', 'value' => $tomorrow, 'compare' => '>=' ); 
    726             } 
    727         }elseif ($scope == "month"){ 
    728             $start_month = strtotime(date('Y-m-d',$time)); 
    729             $end_month = strtotime(date('Y-m-t',$time)); 
    730             if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    731                 $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
    732             }else{ 
    733                 $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' ); 
    734                 $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' ); 
    735             } 
    736         }elseif ($scope == "next-month"){ 
    737             $start_month_timestamp = strtotime('+1 month', $time); //get the end of this month + 1 day 
    738             $start_month = strtotime(date('Y-m-1',$start_month_timestamp)); 
    739             $end_month = strtotime(date('Y-m-t',$start_month_timestamp)); 
    740             if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    741                 $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
    742             }else{ 
    743                 $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' ); 
    744                 $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' ); 
    745             } 
    746         }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month. 
    747             $months_to_add = $matches[1]; 
    748             $start_month = strtotime(date('Y-m-d',$time)); 
    749             $end_month = strtotime(date('Y-m-t',strtotime("+$months_to_add month", $time))); 
    750             if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){ 
    751                 $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN'); 
    752             }else{ 
    753                 $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' ); 
    754                 $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' ); 
     732                $query[] = array( 'key' => '_event_start_date', 'value' => $end_month, 'compare' => '<=', 'type' => 'DATE' ); 
     733                $query[] = array( 'key' => '_event_end_date', 'value' => $start_month, 'compare' => '>=', 'type' => 'DATE' ); 
    755734            } 
    756735        } 
     
    12341213    function compat_keys(){ 
    12351214        foreach($this->fields as $key => $fieldinfo){ 
    1236             $field_name = $fieldinfo['name']; 
    1237             if(!empty($this->$key)) $this->$field_name = $this->$key; 
     1215            if( !empty($fieldinfo['name']) ){ 
     1216                $field_name = $fieldinfo['name']; 
     1217                if(!empty($this->$key)) $this->$field_name = $this->$key; 
     1218            } 
    12381219        } 
    12391220    } 
  • events-manager/trunk/classes/em-taxonomy-frontend.php

    r1769217 r1786433  
    125125        if( $wp_query->is_tax(self::$taxonomy_name) ){ 
    126126            //Scope is future 
    127             $today = strtotime(date('Y-m-d', current_time('timestamp'))); 
     127            $today = current_time('mysql'); 
    128128            if( get_option('dbem_events_current_are_past') ){ 
    129                 $wp_query->query_vars['meta_query'][] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' ); 
     129                $wp_query->query_vars['meta_query'][] = array( 'key' => '_event_start', 'value' => $today, 'compare' => '>=', 'type' => 'DATETIME' ); 
    130130            }else{ 
    131                 $wp_query->query_vars['meta_query'][] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' ); 
     131                $wp_query->query_vars['meta_query'][] = array( 'key' => '_event_end', 'value' => $today, 'compare' => '>=', 'type' => 'DATETIME' ); 
    132132            } 
    133133            if( get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby') == 'title'){ 
    134134                $wp_query->query_vars['orderby'] = 'title'; 
    135135            }else{ 
    136                 $wp_query->query_vars['orderby'] = 'meta_value_num'; 
    137                 $wp_query->query_vars['meta_key'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby','_start_ts'); 
     136                $wp_query->query_vars['orderby'] = 'meta_value'; 
     137                $wp_query->query_vars['meta_key'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_orderby'); 
     138                if( in_array($wp_query->query_vars['meta_key'], array('_event_start', '_event_end', '_event_start_local', '_event_end_local')) ){ 
     139                    $wp_query->query_vars['meta_type'] = 'DATETIME'; 
     140                } 
    138141            } 
    139142            $wp_query->query_vars['order'] = get_option('dbem_'. self::$option_name_plural .'_default_archive_order','ASC'); 
  • events-manager/trunk/classes/em-ticket.php

    r1765726 r1786433  
    77    var $ticket_description; 
    88    var $ticket_price; 
    9     var $ticket_start; 
    10     var $ticket_end; 
     9    protected $ticket_start; 
     10    protected $ticket_end; 
    1111    var $ticket_min; 
    1212    var $ticket_max; 
     
    2323        'ticket_description' => array('name'=>'description','type'=>'%s','null'=>1), 
    2424        'ticket_price' => array('name'=>'price','type'=>'%f','null'=>1), 
    25         'ticket_start' => array('name'=>'start','type'=>'%s','null'=>1), 
    26         'ticket_end' => array('name'=>'end','type'=>'%s','null'=>1), 
     25        'ticket_start' => array('type'=>'%s','null'=>1), 
     26        'ticket_end' => array('type'=>'%s','null'=>1), 
    2727        'ticket_min' => array('name'=>'min','type'=>'%s','null'=>1), 
    2828        'ticket_max' => array('name'=>'max','type'=>'%s','null'=>1), 
     
    4141    var $bookings = array(); 
    4242    var $required_fields = array('ticket_name'); 
    43     var $start_timestamp; 
    44     var $end_timestamp; 
     43    protected $start; 
     44    protected $end; 
    4545    /** 
    4646     * is this ticket limited by spaces allotted to this ticket? false if no limit (i.e. the events general limit of seats) 
     
    8282            $this->ticket_members_roles = maybe_unserialize($this->ticket_members_roles); 
    8383            if( !is_array($this->ticket_members_roles) ) $this->ticket_members_roles = array(); 
    84             //timestamps 
    85             $this->start_timestamp = (!empty($ticket['ticket_start'])) ? strtotime($ticket['ticket_start'], current_time('timestamp')):false; 
    86             $this->end_timestamp = (!empty($ticket['ticket_end'])) ? strtotime($ticket['ticket_end'], current_time('timestamp')):false; 
    8784            //sort out recurrence meta to save extra empty() checks, the 'true' cut-off info is here for the ticket if part of a recurring event 
    8885            if( !empty($this->ticket_meta['recurrences']) ){ 
    8986                if( !array_key_exists('start_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['start_days'] = false; 
     87                if( !array_key_exists('end_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_days'] = false; 
    9088                if( !array_key_exists('start_time', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['start_time'] = false; 
    91                 if( !array_key_exists('end_days', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_days'] = false; 
    9289                if( !array_key_exists('end_time', $this->ticket_meta['recurrences']) ) $this->ticket_meta['recurrences']['end_time'] = false; 
     90                //if we have start and end times, we'll set the ticket start/end properties 
     91                if( !empty($this->ticket_meta['recurrences']['start_time']) ){ 
     92                    $this->ticket_start = date('Y-m-d ') . $this->ticket_meta['recurrences']['start_time']; 
     93                } 
     94                if( !empty($this->ticket_meta['recurrences']['end_time']) ){ 
     95                    $this->ticket_end = date('Y-m-d ') . $this->ticket_meta['recurrences']['end_time']; 
     96                } 
    9397            } 
    9498        } 
    9599        $this->compat_keys(); 
    96100        do_action('em_ticket',$this, $ticket_data, $ticket); 
     101    } 
     102 
     103     
     104    function __get( $var ){ 
     105        if( $var == 'ticket_start' || $var == 'ticket_end' ){ 
     106            return $this->$var; 
     107        } 
     108       //these are deprecated properties, use the start() and end() functions directly instead 
     109        elseif( $var == 'start_timestamp' || $var == 'start' ){ 
     110            if( !$this->start()->valid ) return 0; 
     111            return $this->start()->getTimestampWithOffset(); 
     112        }elseif( $var == 'end_timestamp' || $var == 'end' ){ 
     113            if( !$this->end()->valid ) return 0; 
     114            return $this->end()->getTimestampWithOffset(); 
     115        } 
     116        return null; 
     117    } 
     118     
     119    public function __set( $prop, $val ){ 
     120        if( $prop == 'ticket_start' ){ 
     121            $this->$prop = $val; 
     122            $this->start = false; 
     123        }elseif( $prop == 'ticket_end' ){ 
     124            $this->$prop = $val; 
     125            $this->end = false; 
     126        } 
     127        //These are deprecated and should not be used. Either use the class start() or end() equivalent methods 
     128        elseif( $prop == 'start_timestamp' ){ 
     129            if( $this->start() !== false ) $this->start()->setTimestamp($val); 
     130        }elseif( $prop == 'end_timestamp' ){ 
     131            if( $this->end() !== false ) $this->end()->setTimestamp($val); 
     132        }elseif( $prop == 'start' || $prop == 'end' ){ 
     133            //start and end properties are inefficient to set, and deprecated. Set ticket_start and ticket_end with a valid MySQL DATETIME value instead. 
     134            $EM_DateTime = new EM_DateTime( $val, $this->get_event()->get_timezone() ); 
     135            if( !$EM_DateTime->valid ) return false; 
     136            $when_prop = 'ticket_'.$prop; 
     137            $this->$when_prop = $EM_DateTime->getDateTime(); 
     138        } 
     139        $this->$prop = $val; 
     140    } 
     141     
     142    public function __isset( $prop ){ 
     143        //start_timestamp and end_timestamp are deprecated, don't use them anymore 
     144        if( $prop == 'ticket_start' || $prop == 'start_timestamp' ){ 
     145            return !empty($this->ticket_start); 
     146        }elseif( $prop == 'ticket_end' || $prop == 'end_timestamp' ){ 
     147            return !empty($this->ticket_end); 
     148        } 
    97149    } 
    98150     
     
    124176            if( !empty($data['ticket_meta']) ) $data['ticket_meta'] = serialize($data['ticket_meta']); 
    125177            if( !empty($data['ticket_members_roles']) ) $data['ticket_members_roles'] = serialize($data['ticket_members_roles']); 
     178            if( !empty($this->ticket_meta['recurrences']) ){ 
     179                $data['ticket_start'] = $data['ticket_end'] = null; 
     180            } 
    126181            if($this->ticket_id != ''){ 
    127182                //since currently wpdb calls don't accept null, let's build the sql ourselves. 
     
    182237        if( !empty($post['ticket_start_time']) && !empty($this->ticket_start) ) $this->ticket_start .= ' '. $this->sanitize_time($post['ticket_start_time']); 
    183238        if( !empty($post['ticket_end_time']) && !empty($this->ticket_end) ) $this->ticket_end .= ' '. $this->sanitize_time($post['ticket_end_time']); 
    184         $this->start_timestamp = ( !empty($post['ticket_start']) ) ? strtotime($this->ticket_start):''; 
    185         $this->end_timestamp = ( !empty($post['ticket_end']) ) ? strtotime($this->ticket_end):''; 
    186239        //sort out user availability restrictions 
    187240        $this->ticket_members = ( !empty($post['ticket_type']) && $post['ticket_type'] == 'members' ) ? 1:0; 
     
    199252        //if event is recurring, store start/end restrictions of this ticket, which are determined by number of days before (negative number) or after (positive number) the event start date 
    200253        if($this->get_event()->is_recurring()){ 
     254            if( empty($this->ticket_meta['recurrences']) ){ 
     255                $this->ticket_meta['recurrences'] = array('start_days'=>false, 'start_time'=>false, 'end_days'=>false, 'end_time'=>false); 
     256            } 
    201257            //start of ticket cut-off 
    202258            if( array_key_exists('ticket_start_recurring_days', $post) && is_numeric($post['ticket_start_recurring_days']) ){ 
    203259                if( !empty($post['ticket_start_recurring_when']) && $post['ticket_start_recurring_when'] == 'after' ){ 
    204260                    $this->ticket_meta['recurrences']['start_days'] = absint($post['ticket_start_recurring_days']); 
    205                     $this->ticket_start = date('Y-m-d', strtotime('+' . $this->ticket_meta['recurrences']['start_days'] . ' days', $this->get_event()->start)); 
    206261                }else{ //by default the start date is the point of reference 
    207262                    $this->ticket_meta['recurrences']['start_days'] = absint($post['ticket_start_recurring_days']) * -1; 
    208                     $this->ticket_start = date('Y-m-d', strtotime($this->ticket_meta['recurrences']['start_days'] . ' days', $this->get_event()->start)); 
    209                 } 
    210                 $this->ticket_meta['recurrences']['start_time'] = ( !empty($post['ticket_start_time']) ) ? $this->sanitize_time($post['ticket_start_time']) : '00:00:00';  
    211                 $this->ticket_start .= ' '. $this->ticket_meta['recurrences']['start_time']; 
    212                 //timestamp - calculated only for purposes of not screwing up interfaces that use timestamps for outputting cut-off times such as booking settings for event 
    213                 $this->start_timestamp  = strtotime($this->ticket_start, current_time('timestamp')); 
     263                } 
     264                $this->ticket_meta['recurrences']['start_time'] = ( !empty($post['ticket_start_time']) ) ? $this->sanitize_time($post['ticket_start_time']) : '00:00:00'; 
    214265            }else{ 
    215266                unset($this->ticket_meta['recurrences']['start_days']); 
    216267                unset($this->ticket_meta['recurrences']['start_time']); 
    217                 $this->ticket_start = $this->start_timestamp = ''; 
    218268            } 
    219269            //end of ticket cut-off 
     
    221271                if( !empty($post['ticket_end_recurring_when']) && $post['ticket_end_recurring_when'] == 'after' ){ 
    222272                    $this->ticket_meta['recurrences']['end_days'] = absint($post['ticket_end_recurring_days']); 
    223                     $this->ticket_end = date('Y-m-d', strtotime('+' . $this->ticket_meta['recurrences']['end_days'] . ' days', $this->get_event()->end)); 
    224273                }else{ //by default the end date is the point of reference 
    225274                    $this->ticket_meta['recurrences']['end_days'] = absint($post['ticket_end_recurring_days']) * -1; 
    226                     $this->ticket_end = date('Y-m-d', strtotime($this->ticket_meta['recurrences']['end_days'] . ' days', $this->get_event()->end)); 
    227                 } 
    228                 $this->ticket_meta['recurrences']['end_time'] = ( !empty($post['ticket_end_time']) ) ? $this->sanitize_time($post['ticket_end_time']) : '00:00:00';  
    229                 $this->ticket_end .= ' '. $this->ticket_meta['recurrences']['end_time']; 
    230                 //timestamp - calculated only for purposes of not screwing up interfaces that use timestamps for outputting cut-off times such as booking settings for event 
    231                 $this->end_timestamp  = strtotime($this->ticket_end, current_time('timestamp')); //we save these timestamps for quicker loading on construct 
     275                } 
     276                $this->ticket_meta['recurrences']['end_time'] = ( !empty($post['ticket_end_time']) ) ? $this->sanitize_time($post['ticket_end_time']) : '00:00:00'; 
    232277            }else{ 
    233278                unset($this->ticket_meta['recurrences']['end_days']); 
    234279                unset($this->ticket_meta['recurrences']['end_time']); 
    235                 $this->ticket_end = $this->end_timestamp = ''; 
    236             } 
     280            } 
     281            $this->ticket_start = $this->ticket_end = null; 
    237282        } 
    238283        $this->compat_keys(); 
     
    264309     
    265310    function is_available( $ignore_member_restrictions = false, $ignore_guest_restrictions = false ){ 
    266         $timestamp = current_time('timestamp'); 
    267311        if( isset($this->is_available) && !$ignore_member_restrictions && !$ignore_guest_restrictions ) return apply_filters('em_ticket_is_available',  $this->is_available, $this); //save extra queries if doing a standard check 
    268312        $is_available = false; 
    269313        $EM_Event = $this->get_event(); 
    270314        $available_spaces = $this->get_available_spaces(); 
    271         $condition_1 = (empty($this->ticket_start) || $this->start_timestamp <= $timestamp); 
    272         $condition_2 = $this->end_timestamp >= $timestamp || empty($this->ticket_end); 
    273         $condition_3 = (empty($EM_Event->event_rsvp_date) && $EM_Event->start > $timestamp) || $EM_Event->rsvp_end > $timestamp; 
     315        $condition_1 = empty($this->ticket_start) || $this->start()->getTimestamp() <= time(); 
     316        $condition_2 = empty($this->ticket_end) || $this->end()->getTimestamp() >= time(); 
     317        $condition_3 = $EM_Event->rsvp_end()->getTimestamp() > time(); //either defined ending rsvp time, or start datetime is used here 
    274318        $condition_4 = !$this->ticket_members || ($this->ticket_members && is_user_logged_in()) || $ignore_member_restrictions; 
    275319        $condition_5 = true; 
     
    551595     
    552596    /** 
     597     * Returns an EM_DateTime object of the ticket start date/time in local timezone of event. 
     598     * If no start date defined or if date is invalid, false is returned. 
     599     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. 
     600     * @return EM_DateTime|false 
     601     * @see EM_Event::get_datetime() 
     602     */ 
     603    public function start( $utc_timezone = false ){ 
     604        return apply_filters('em_ticket_start', $this->get_datetime('start', $utc_timezone), $this); 
     605    } 
     606     
     607    /** 
     608     * Returns an EM_DateTime object of the ticket end date/time in local timezone of event. 
     609     * If no start date defined or if date is invalid, false is returned. 
     610     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. 
     611     * @return EM_DateTime|false 
     612     * @see EM_Event::get_datetime() 
     613     */ 
     614    public function end( $utc_timezone = false ){ 
     615        return apply_filters('em_ticket_end', $this->get_datetime('end', $utc_timezone), $this); 
     616    } 
     617     
     618    /** 
     619     * Generates an EM_DateTime for the the start/end date/times of the ticket in local timezone. 
     620     * If ticket has no start/end date, or an invalid format, false is returned. 
     621     * @param string $when 'start' or 'end' date/time 
     622     * @param bool $utc_timezone Returns EM_DateTime with UTC timezone if set to true, returns local timezone by default. Do not use if EM_DateTime->valid is false.  
     623     * @return EM_DateTime|false 
     624     */ 
     625    public function get_datetime( $when = 'start', $utc_timezone = false ){ 
     626        if( $when != 'start' && $when != 'end') return new EM_DateTime(); //currently only start/end dates are relevant 
     627        //Initialize EM_DateTime if not already initialized, or if previously initialized object is invalid (e.g. draft event with invalid dates being resubmitted) 
     628        $when_date = 'ticket_'.$when; 
     629        //we take a pass at creating a new datetime object if it's empty, invalid or a different time to the current start date 
     630        if( !empty($this->$when_date) ){ 
     631            if( empty($this->$when) || !$this->$when->valid ){ 
     632                $this->$when = new EM_DateTime( $this->$when_date, $this->get_event()->get_timezone() ); 
     633            } 
     634        }else{ 
     635            $this->$when = new EM_DateTime(); 
     636            $this->$when->valid = false; 
     637        } 
     638        //Set to UTC timezone if requested, local by default 
     639        $tz = $utc_timezone ? 'UTC' : $this->get_event()->get_timezone(); 
     640        $this->$when->setTimezone($tz); 
     641        return $this->$when; 
     642    } 
     643     
     644    /** 
    553645     * Can the user manage this event?  
    554646     */ 
     
    561653     
    562654    /** 
    563      * Outputs properties with formatting 
     655     * Deprecated since 5.8.2, just access properties directly or use relevant functions such as $this->start() for ticket_start time - Outputs properties with formatting 
    564656     * @param string $property 
    565657     * @return string 
     
    568660        switch($property){ 
    569661            case 'start': 
    570                 $value = date_i18n( get_option('date_format'), $this->start_timestamp ); 
     662                $value = ( $this->start()->valid ) ? $this->start()->i18n( em_get_date_format() ) : ''; 
    571663                break; 
    572664            case 'end': 
    573                 $value = date_i18n( get_option('date_format'), $this->end_timestamp ); 
    574                 break; 
     665                $value = ( $this->end()->valid ) ? $this->end()->i18n( em_get_date_format() ) : ''; 
    575666                break; 
    576667            default: 
  • events-manager/trunk/em-events.php

    r1766931 r1786433  
    131131    add_filter('the_content', 'em_content'); 
    132132} 
     133//remember that this gets removed by taxonomy pages showing a single taxonomy page, so careful if changing the priority 
    133134add_action('wp_head', 'em_add_content_filter_after_head', 1000); 
    134135 
     
    203204                } 
    204205            } 
    205             return apply_filters('em_content_page_title', $content); 
    206         } 
     206        } 
     207        return apply_filters('em_content_page_title', $content); 
    207208    } 
    208209    return $original_content; 
  • events-manager/trunk/em-install.php

    r1720802 r1786433  
    136136        event_status int(1) NULL DEFAULT NULL, 
    137137        event_name text NULL DEFAULT NULL, 
     138        event_start_date date NULL DEFAULT NULL, 
     139        event_end_date date NULL DEFAULT NULL, 
    138140        event_start_time time NULL DEFAULT NULL, 
    139141        event_end_time time NULL DEFAULT NULL, 
    140         event_all_day int(1) NULL DEFAULT NULL, 
    141         event_start_date date NULL DEFAULT NULL, 
    142         event_end_date date NULL DEFAULT NULL, 
     142        event_all_day int(1) NULL DEFAULT NULL, 
     143        event_start datetime NULL DEFAULT NULL, 
     144        event_end datetime NULL DEFAULT NULL, 
     145        event_timezone tinytext NULL DEFAULT NULL, 
    143146        post_content longtext NULL DEFAULT NULL, 
    144147        event_rsvp bool NOT NULL DEFAULT 0, 
     
    190193        dbDelta($sql); 
    191194    } 
    192     em_sort_out_table_nu_keys($table_name, array('event_status','post_id','blog_id','group_id','location_id')); 
     195    em_sort_out_table_nu_keys($table_name, array('event_status','post_id','blog_id','group_id','location_id','event_start', 'event_end', 'event_start_date', 'event_end_date')); 
    193196    if( em_check_utf8mb4_tables() ) maybe_convert_table_to_utf8mb4( $table_name ); 
    194197} 
     
    390393    //all the options 
    391394    $dbem_options = array( 
     395        'dbem_admin_data' => array(), //used to store admin-related data such as notice flags and other row keys that may not always exist in the wp_options table 
    392396        //time formats 
    393397        'dbem_time_format' => get_option('time_format'), 
     
    656660        'dbem_calendar_direct_links' => 1, 
    657661        //General Settings 
     662        'dbem_timezone_enabled' => 1, 
     663        'dbem_timezone_default' => EM_DateTimeZone::create()->getName(), 
    658664        'dbem_require_location' => 0, 
    659665        'dbem_locations_enabled' => 1, 
     
    781787        'dbem_cp_events_formats' => 1, 
    782788        'dbem_cp_events_has_archive' => 1, 
    783         'dbem_events_default_archive_orderby' => '_start_ts', 
     789        'dbem_events_default_archive_orderby' => '_event_start', 
    784790        'dbem_events_default_archive_order' => 'ASC', 
    785791        'dbem_events_archive_scope' => 'past', 
     
    845851 
    846852function em_upgrade_current_installation(){ 
    847     global $wpdb, $wp_locale; 
     853    global $wpdb, $wp_locale, $EM_Notices; 
    848854    if( !get_option('dbem_version') ){ add_option('dbem_credits',1); } 
    849855    if( get_option('dbem_version') != '' && get_option('dbem_version') < 5 ){ 
     
    9971003            delete_option('dbem_bookings_registration_user'); 
    9981004        } 
     1005    } 
     1006    if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.82 ){ 
     1007        $admin_data = get_option('dbem_admin_data'); 
     1008        $admin_data['datetime_backcompat'] = true; 
     1009        update_option('dbem_admin_data', $admin_data); 
     1010        $migration_result = em_migrate_datetime_timezones( false ); 
     1011        if( $migration_result !== true ){ 
     1012            $EM_Notices->add_error($migration_result); 
     1013        } 
     1014        //migrate certain options 
     1015        $opt = get_option('dbem_tags_default_archive_orderby'); 
     1016        if( $opt == '_start_ts' ) update_option('dbem_tags_default_archive_orderby', '_event_start'); 
     1017        $opt = get_option('dbem_categories_default_archive_orderby'); 
     1018        if( $opt == '_start_ts' ) update_option('dbem_categories_default_archive_orderby', '_event_start'); 
     1019        $opt = get_option('dbem_events_default_archive_orderby'); 
     1020        if( $opt == '_start_ts' ) update_option('dbem_events_default_archive_orderby', '_event_start'); 
    9991021    } 
    10001022} 
     
    13911413    return $result; 
    13921414} 
     1415 
     1416function em_migrate_datetime_timezones( $reset_new_fields = true, $migrate_date_fields = true, $timezone = false ){ 
     1417    global $wpdb; 
     1418    //create AND and WHERE conditions for blog IDs if we're in Multisite Glboal Mode 
     1419    $blog_id_where = $blog_id_and = ''; 
     1420    if( EM_MS_GLOBAL ){ 
     1421        if( is_main_site() ){ 
     1422            $blog_id_cond = $wpdb->prepare('(blog_id = %d OR blog_id IS NULL OR blog_id = 0)', get_current_blog_id()); 
     1423        }else{ 
     1424            $blog_id_cond = $wpdb->prepare('blog_id = %d', get_current_blog_id()); 
     1425        } 
     1426        $blog_id_where = ' WHERE '.$blog_id_cond; 
     1427        $blog_id_and = ' AND '.$blog_id_cond; 
     1428    } 
     1429    //reset all the data for these purposes 
     1430    if( $reset_new_fields || $migrate_date_fields ) $wpdb->query('UPDATE '. EM_EVENTS_TABLE .' SET event_start = NULL, event_end = NULL, event_timezone = NULL'.$blog_id_where); 
     1431    if( !$migrate_date_fields ) return true; 
     1432     
     1433    //start migration of old date formats to new datetime formats in local and UTC mode along with a declared timezone 
     1434    $migration_results = $migration_meta_results = $migration_errors = array(); 
     1435    //firstly, we do a query for all-day events and reset the times, so that UTC times are correct relative to the local time 
     1436    $migration_result = $wpdb->query('UPDATE '.EM_EVENTS_TABLE." SET event_start_time = '00:00:00', event_end_time = '23:59:59' WHERE event_all_day = 1".$blog_id_and); 
     1437    if( $migration_result === false ) $migration_errors[] = array('Local datetime allday event times modification errors', $wpdb->last_error); 
     1438     
     1439    //migration procedure depends on whether we have an actual timezone or just a manual offset of hours in the WP settings page 
     1440    if( empty($timezone) ){ 
     1441        $timezone = get_option('timezone_string'); 
     1442        if( empty($timezone) ){  
     1443            $timezone = get_option('gmt_offset'); 
     1444            $timezone = preg_match('/[+\-]/', $timezone) ? 'UTC'.$timezone : 'UTC+'.$timezone; 
     1445        } 
     1446    } 
     1447    if( !preg_match('/^UTC/', $timezone) ){ 
     1448        //we'll get the minimum start/end dates in our events, and get the transitions for this range 
     1449        $transitions = em_migrate_get_tz_transitions($timezone, $blog_id_where); 
     1450        //now, build the SQL statements with the transitions 
     1451        $query_data = array(); 
     1452        $where_start = $where_end = array(); 
     1453        //go through each transition and add it to the right offset array key 
     1454        foreach( $transitions as $t ){ 
     1455            //format start/end transitions for mysql DATETIME format IN CORRECT TIMEZONE 
     1456            $start = $t['start'] ? date('Y-m-d H:i:s', $t['start'] + $t['offset']) : false; 
     1457            $end = $t['end'] ? date('Y-m-d H:i:s', $t['end'] + $t['offset']) : false; 
     1458            //set up SQL statement for offset if it doesn't exist, but without the WHERE clause, which we'll add later 
     1459            if( empty($query_data[$t['offset']]) ){ 
     1460                $query_data[$t['offset']] = array( 
     1461                        'start' => array( 
     1462                                'sql' => $wpdb->prepare('UPDATE '. EM_EVENTS_TABLE. ' SET event_start = DATE_SUB(TIMESTAMP(event_start_date,event_start_time), INTERVAL %d SECOND)', $t['offset']), 
     1463                                'where' => array() 
     1464                        ), 
     1465                        'end' => array( 
     1466                                'sql' => $wpdb->prepare('UPDATE '. EM_EVENTS_TABLE. ' SET event_end = DATE_SUB(TIMESTAMP(event_end_date, event_end_time), INTERVAL %d SECOND)', $t['offset']), 
     1467                                'where' => array() 
     1468                        ) 
     1469                ); 
     1470            } 
     1471            //create array of conditions, which we'll join into single statements for each unique offset amount 
     1472            if( $start && $end ){ 
     1473                $query_data[$t['offset']]['start']['where'][] = $wpdb->prepare("(TIMESTAMP(event_start_date,event_start_time) BETWEEN %s AND %s)", $start, $end); 
     1474                $query_data[$t['offset']]['end']['where'][] = $wpdb->prepare("(TIMESTAMP(event_end_date, event_end_time) BETWEEN %s AND %s)", $start, $end); 
     1475            }elseif( $start ){ 
     1476                $query_data[$t['offset']]['start']['where'][] = $wpdb->prepare("(TIMESTAMP(event_start_date,event_start_time) > %s)", $start); 
     1477                $query_data[$t['offset']]['end']['where'][] = $wpdb->prepare("(TIMESTAMP(event_end_date, event_end_time) > %s)", $start); 
     1478            }elseif( $end ){ 
     1479                $query_data[$t['offset']]['start']['where'][] = $wpdb->prepare("(TIMESTAMP(event_start_date,event_start_time) < %s)", $end); 
     1480                $query_data[$t['offset']]['end']['where'][] = $wpdb->prepare("(TIMESTAMP(event_end_date, event_end_time) < %s)", $end); 
     1481            } 
     1482        } 
     1483        //glue the where clauses together with SQLs and create the minimum required statements to run this update 
     1484        $sql_array = array(); 
     1485        foreach( $query_data as $offset => $statements ){ 
     1486            $migration_result = $wpdb->query($statements['start']['sql'] .' WHERE event_start IS NULL AND ('. implode(' OR ', $statements['start']['where']).')'.$blog_id_and); 
     1487            if( $migration_result === false ) $migration_errors[] = array('Event start UTC transition',$wpdb->last_error); 
     1488            $migration_result = $wpdb->query($statements['end']['sql'] ." WHERE event_end IS NULL AND (". implode(' OR ', $statements['end']['where']).')'.$blog_id_and); 
     1489            if( $migration_result === false ) $migration_errors[] = array('Event end UTC transation', $wpdb->last_error); 
     1490        } 
     1491    }else{ 
     1492        //This gets very easy... just do a single query that copies over all the times to right columns with relevant offset 
     1493        $offset = $timezone == 'UTC' ? 0 : EM_DateTimeZone::create($timezone)->offset / MINUTE_IN_SECONDS; 
     1494        $migration_result = $wpdb->query($wpdb->prepare('UPDATE '. EM_EVENTS_TABLE. ' SET event_start = DATE_SUB(TIMESTAMP(event_start_date,event_start_time), INTERVAL %d MINUTE), event_end = DATE_SUB(TIMESTAMP(event_end_date, event_end_time), INTERVAL %d MINUTE) WHERE event_end IS NULL '.$blog_id_and, $offset, $offset)); 
     1495        if( $migration_result === false ) $migration_errors[] = array('Event start/end UTC offset', $wpdb->last_error); 
     1496    } 
     1497     
     1498    //set the timezone (on initial migration all events have same timezone of blog) 
     1499    $migration_result = $wpdb->query($wpdb->prepare('UPDATE '.EM_EVENTS_TABLE.' SET event_timezone = %s WHERE event_timezone IS NULL'.$blog_id_and, $timezone)); 
     1500    if( $migration_result === false ) $migration_errors[] = array('Event timezone setting', $wpdb->last_error); 
     1501     
     1502    //reave meta data - at this point once we've copied over all of the dates, so we do 5 queries to postmeta, one for each field we've created above start/end times in local/utc and timezone 
     1503    if( empty($migration_errors) ){ 
     1504        //delete all previously added fields, in case they were added before 
     1505        $sql = 'DELETE FROM '.$wpdb->postmeta." WHERE meta_key IN ('_event_start','_event_end','_event_timezone', '_event_start_local', '_event_end_local') AND post_id IN (SELECT ID FROM ".$wpdb->posts." WHERE post_type='".EM_POST_TYPE_EVENT."' OR post_type='event-recurring')"; 
     1506        $migration_result = $wpdb->query($sql); 
     1507        if( $migration_result === false ) $migration_errors[] = array('Previous meta deletion', $wpdb->last_error); 
     1508        foreach( array('event_start', 'event_end', 'event_timezone', 'start', 'end') as $field ){ 
     1509            if( $field == 'start' || $field == 'end' ){ 
     1510                //create a timestamp combining two given fields, which we'll now use  
     1511                $sql = 'INSERT INTO '.$wpdb->postmeta." (post_id, meta_key, meta_value) SELECT post_id, '_event_{$field}_local', TIMESTAMP(event_{$field}_date, event_{$field}_time) FROM ".EM_EVENTS_TABLE. $blog_id_where; 
     1512                $field = "event_".$field."_local"; 
     1513            }else{ 
     1514                $sql = 'INSERT INTO '.$wpdb->postmeta." (post_id, meta_key, meta_value) SELECT post_id, '_{$field}', {$field} FROM ".EM_EVENTS_TABLE. $blog_id_where; 
     1515            } 
     1516            $migration_result = $wpdb->query($sql); 
     1517            if( $migration_result === false ) $migration_errors[] = array('Adding new meta data key <em>_'.$field.'</em>', $wpdb->last_error); 
     1518        } 
     1519    } 
     1520     
     1521    //return the result of this migration, either true for no errors, or a string of errors. 
     1522    if( !empty($migration_errors) ){ 
     1523        $string = __('There was an error whilst migrating your times to our new timezone-aware formats. Below is a list of errors:', 'events-manager'); 
     1524        $string .= '<ul>'; 
     1525        foreach( $migration_errors as $err ){ 
     1526            $string .= '<li><strong>'. $err[0] .': </strong>'. $err[1] .'</li>'; 
     1527        } 
     1528        $string .= '</ul>'; 
     1529        return $string; 
     1530    } 
     1531    return true; 
     1532} 
     1533 
     1534function em_migrate_get_tz_transitions( $timezone, $blog_id_where = '' ){ 
     1535    global $wpdb; 
     1536    $minmax_dates = $wpdb->get_row('SELECT MIN(event_start_date) AS mindate, MAX(event_end_date) AS maxdate FROM '.EM_EVENTS_TABLE.$blog_id_where); 
     1537    $DTZ = new EM_DateTimeZone( $timezone ); 
     1538    $start = strtotime($minmax_dates->mindate, current_time('timestamp')) - 60*60*24; 
     1539    $end = strtotime($minmax_dates->maxdate, current_time('timestamp')) + 60*60*24; //we add a day just to get the most comprehensive range possible 
     1540    $DTZ_Transitions = $DTZ->getTransitions($start, $end); 
     1541    //get first and next transitions to create a range, if there's only one transition we create a fake transition 
     1542    $transitions = array(); 
     1543    if( count($DTZ_Transitions) == 1 ){ 
     1544        $current_transition = current($DTZ_Transitions); 
     1545        $dst_offset = $current_transition['isdst'] ? 60*60 : 0; 
     1546        $transitions[] = array( 
     1547            'start' => $start, 
     1548            'end' => false, 
     1549            'offset' => $current_transition['offset'] 
     1550        ); 
     1551    }else{ 
     1552        do{ 
     1553            $current_transition = current($DTZ_Transitions); 
     1554            $transition_key = key($DTZ_Transitions); 
     1555            $next_transition = next($DTZ_Transitions); 
     1556            if( $current_transition['ts'] < $start ) continue; 
     1557            $dst_offset = $current_transition['isdst'] ? 60*60 : 0; 
     1558            if( $transition_key == 0 ){ 
     1559                //add the final transition and break this loop 
     1560                $transitions[] = array( 
     1561                'start' => false, 
     1562                'end' => $next_transition['ts'] - 1 - $dst_offset, 
     1563                'offset' => $current_transition['offset'] 
     1564                ); 
     1565            }else{ 
     1566                if( empty($next_transition) ){ 
     1567                    //add the final transition and break this loop 
     1568                    $transitions[] = array( 
     1569                    'start' => $current_transition['ts'] - $dst_offset, 
     1570                    'end' => false, 
     1571                    'offset' => $current_transition['offset'] 
     1572                    ); 
     1573                    break; 
     1574                }else{ 
     1575                    $transitions[] = array( 
     1576                            'start' => $current_transition['ts'] - $dst_offset, 
     1577                            'end' => $next_transition['ts'] - 1 - $dst_offset, 
     1578                            'offset' => $current_transition['offset'] 
     1579                    ); 
     1580                } 
     1581            } 
     1582            if( $current_transition['ts'] > $end ) break; 
     1583        } while( $next_transition !== false ); 
     1584    } 
     1585    return $transitions; 
     1586} 
    13931587?> 
  • events-manager/trunk/em-wpfc.php

    r1399308 r1786433  
    136136     
    137137    //get the month/year between the start/end dates and feed these to EM 
    138     $scope_start = strtotime(substr($_REQUEST['start'],0,10)); 
    139     $scope_end = strtotime(substr($_REQUEST['end'],0,10)); 
     138    $EM_DateTime = new EM_DateTime(substr($_REQUEST['start'],0,10)); 
     139    $scope_start = $EM_DateTime->getTimestamp(); 
     140    $scope_end = $EM_DateTime->modify(substr($_REQUEST['end'],0,10))->getTimestamp(); 
    140141    $scope_middle = $scope_start + ($scope_end - $scope_start)/2; 
    141     $month = date('n', $scope_middle); 
    142     $year = date('Y', $scope_middle); 
     142    $month = $EM_DateTime->setTimestamp($scope_middle)->format('n'); 
     143    $year = $EM_DateTime->format('Y'); 
    143144 
    144145    $args = array ('month'=>$month, 'year'=>$year, 'owner'=>false, 'status'=>1, 'orderby'=>'event_start_time, event_name'); //since wpfc handles date sorting we only care about time and name ordering here 
     
    196197            if( !in_array($EM_Event->event_id, $event_ids) ){ 
    197198                //count events for all days this event may span 
    198                 if( $EM_Event->event_start_date != $EM_Event->event_end_date ){ 
    199                     for( $i = $EM_Event->start; $i <= $EM_Event->end; $i = $i + 86400 ){ 
    200                         $idate = date('Y-m-d',$i); 
    201                         empty($event_day_counts[$idate]) ? $event_day_counts[$idate] = 1 : $event_day_counts[$idate]++; 
     199                if( $EM_Event->start()->getDate() != $EM_Event->end()->getDate() ){ 
     200                    $EM_DateTime = $EM_Event->start()->clone(); 
     201                    while( $EM_DateTime <= $EM_Event->end() ){ 
     202                        $EM_DateTime->add('P1D'); 
     203                        empty($event_day_counts[$EM_DateTime->getDate()]) ? $event_day_counts[$EM_DateTime->getDate()] = 1 : $event_day_counts[$EM_DateTime->getDate()]++; 
    202204                    } 
    203205                }else{ 
     
    208210                    $allDay = $EM_Event->event_all_day == true; 
    209211                    if( $allDay ){ 
    210                         $start_date = date('Y-m-d\TH:i:s', $EM_Event->start); 
    211                         $end_date = date('Y-m-d\T00:00:00', $EM_Event->end + (60*60*24)); //on all day events the end date/time is next day of end date at 00:00:00 - see end attribute on http://fullcalendar.io/docs/event_data/Event_Object/ 
     212                        $start_date = $EM_Event->start()->format('Y-m-d\T00:00:00'); 
     213                        $end_date = $EM_Event->end()->clone()->add('P1D')->format('Y-m-d\T00:00:00'); //on all day events the end date/time is next day of end date at 00:00:00 - see end attribute on http://fullcalendar.io/docs/event_data/Event_Object/ 
    212214                    }else{ 
    213                         $start_date = date('Y-m-d\TH:i:s', $EM_Event->start); 
    214                         $end_date = date('Y-m-d\TH:i:s', $EM_Event->end);                        
     215                        $start_date = $EM_Event->start()->format('Y-m-d\TH:i:s'); 
     216                        $end_date = $EM_Event->end()->format('Y-m-d\TH:i:s');                        
    215217                    } 
    216218                    $event_array = array ("title" => $title, "color" => $color, 'textColor'=>$textColor, 'borderColor'=>$borderColor, "start" => $start_date, "end" => $end_date, "url" => $EM_Event->get_permalink(), 'post_id' => $EM_Event->post_id, 'event_id' => $EM_Event->event_id, 'allDay' => $allDay ); 
  • events-manager/trunk/events-manager.php

    r1769217 r1786433  
    22/* 
    33Plugin Name: Events Manager 
    4 Version: 5.8.1.1 
     4Version: 5.8.1.20 
    55Plugin URI: http://wp-events-plugin.com 
    66Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more! 
     
    2929 
    3030// Setting constants 
    31 define('EM_VERSION', 5.8); //self expanatory 
     31define('EM_VERSION', 5.82); //self expanatory 
    3232define('EM_PRO_MIN_VERSION', 2.392); //self expanatory 
    3333define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory 
     
    6868//Base classes 
    6969include('classes/em-object.php'); 
     70include('classes/em-datetime.php'); 
    7071include('classes/em-taxonomy-term.php'); 
    7172include('classes/em-taxonomy-terms.php'); 
     
    711712function em_modified_monitor($result){ 
    712713    if($result){ 
    713         update_option('em_last_modified', current_time('timestamp', true)); 
     714        update_option('em_last_modified', time()); 
    714715    } 
    715716    return $result; 
  • events-manager/trunk/multilingual/em-ml-io.php

    r1488912 r1786433  
    7979        $EM_Event->event_start_time  = $event->event_start_time ; 
    8080        $EM_Event->event_end_time  = $event->event_end_time ; 
    81         $EM_Event->start  = $event->start ; 
    82         $EM_Event->end  = $event->end ; 
    83         $EM_Event->event_rsvp_date  = $event->event_rsvp_date ; 
    8481             
    8582        $EM_Event->event_rsvp  = $event->event_rsvp ; 
     83        $EM_Event->event_rsvp_date  = $event->event_rsvp_date ; 
    8684        $EM_Event->event_rsvp_time  = $event->event_rsvp_time ; 
    8785                         
  • events-manager/trunk/readme.txt

    r1769217 r1786433  
    101101== Changelog == 
    102102 
     103= 5.8.1.20 (dev) = 
     104* added timezone support 
     105 
    103106= 5.8.1.1 = 
    104107* fixed a bug that arose in 5.8.1 where tag/category pages using formatting will still show the tags/categories list page instead 
     
    135138* fixed taxonomy archive pages returning zero results if taxonomy formatting is disabled and events are excluded from searches (WP Bug workaround) 
    136139* fixed inconsistent line ending causing warnings with PHP compatibility checker 
    137 * unified Tag and Category class functions into sets of parent class functionn 
     140* unified Tag and Category class functions into sets of parent class functions 
    138141* fixed PHP fatal error with BP when disabling notifications 
    139142* fixed calendar day links being incorrect if another plugin adds querystring params to permalinks 
  • events-manager/trunk/templates/buddypress/group-events.php

    r1651260 r1786433  
    5555                    $rowno++; 
    5656                    $class = ($rowno % 2) ? 'alternate' : ''; 
    57                     // FIXME set to american 
    58                     $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start); 
    59                     $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end); 
    60                     $style = ""; 
    61                     $today = date ( "Y-m-d" ); 
    6257                    $location_summary = "<b>" . $EM_Event->get_location()->name . "</b><br/>" . $EM_Event->get_location()->address . " - " . $EM_Event->get_location()->town; 
    6358                     
    64                     if ($EM_Event->start_date < $today && $EM_Event->end_date < $today){ 
     59                    if( $EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time() ){ 
    6560                        $class .= " past"; 
    6661                    } 
     
    6863                    if ( !$EM_Event->status ){ 
    6964                        $class .= " pending"; 
    70                     }                    
     65                    } 
    7166                    ?> 
    72                     <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $EM_Event->event_id ?>"> 
     67                    <tr class="event <?php echo trim($class); ?>" id="event_<?php echo $EM_Event->event_id ?>"> 
    7368                        <?php /* 
    7469                        <td> 
     
    115110                 
    116111                        <td> 
    117                             <?php echo $localised_start_date; ?> 
    118                             <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?> 
     112                            <?php echo $EM_Event->output_dates(); ?> 
    119113                            <br /> 
    120                             <?php 
    121                                 //TODO Should 00:00 - 00:00 be treated as an all day event?  
    122                                 echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 );  
    123                             ?> 
     114                            <?php echo $EM_Event->output_times(); ?> 
    124115                            <br /> 
    125116                            <?php  
  • events-manager/trunk/templates/buddypress/my-group-events.php

    r1311743 r1786433  
    5555                    $rowno++; 
    5656                    $class = ($rowno % 2) ? 'alternate' : ''; 
    57                     // FIXME set to american 
    58                     $localised_start_date = date_i18n(get_option('dbem_date_format'), $event->start); 
    59                     $localised_end_date = date_i18n(get_option('dbem_date_format'), $event->end); 
    60                     $style = ""; 
    61                     $today = current_time('timestamp'); 
    6257                    $location_summary = "<b>" . $event->get_location()->name . "</b><br/>" . $event->get_location()->address . " - " . $event->get_location()->town; 
    6358                     
    64                     if ($event->start < $today && $event->end < $today){ 
     59                    if( $EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time() ){ 
    6560                        $class .= " past"; 
    6661                    } 
     
    7065                    }                    
    7166                    ?> 
    72                     <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $event->event_id ?>"> 
     67                    <tr class="event <?php echo trim($class); ?>" id="event_<?php echo $event->event_id ?>"> 
    7368                        <?php /* 
    7469                        <td> 
     
    110105                 
    111106                        <td> 
    112                             <?php echo $localised_start_date; ?> 
    113                             <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?> 
     107                            <?php echo $EM_Event->output_dates(); ?> 
    114108                            <br /> 
    115                             <?php 
    116                                 if(!$event->event_all_day){ 
    117                                     echo date_i18n(get_option('time_format'), $event->start) . " - " . date_i18n(get_option('time_format'), $event->end); 
    118                                 }else{ 
    119                                     echo get_option('dbem_event_all_day_message'); 
    120                                 } 
    121                             ?> 
     109                            <?php echo $EM_Event->output_times(); ?> 
    122110                        </td> 
    123111                        <td> 
  • events-manager/trunk/templates/forms/event/bookings-ticket-form.php

    r1488912 r1786433  
    4242                <div class="ticket-dates-from-normal"> 
    4343                    <input type="text" name="ticket_start_pub"  class="em-date-input-loc em-date-start" /> 
    44                     <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_start]" class="em-date-input ticket_start" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? date("Y-m-d", $EM_Ticket->start_timestamp):''; ?>" /> 
     44                    <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_start]" class="em-date-input ticket_start" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format("Y-m-d"):''; ?>" /> 
    4545                </div> 
    4646                <div class="ticket-dates-from-recurring"> 
     
    4848                    <?php esc_html_e('day(s)','events-manager'); ?> 
    4949                    <select name="em_tickets[<?php echo $col_count; ?>][ticket_start_recurring_when]" class="ticket-dates-from-recurring-when"> 
    50                         <option value="before" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option> 
     50                        <option value="before" <?php if( isset($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option> 
    5151                        <option value="after" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['start_days']) && $EM_Ticket->ticket_meta['recurrences']['start_days'] > 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('After','events-manager'))); ?></option> 
    5252                    </select> 
    5353                </div> 
    5454                <?php echo esc_html_x('at', 'time','events-manager'); ?> 
    55                 <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_start_time]" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? date( em_get_hour_format(), $EM_Ticket->start_timestamp):''; ?>" /> 
     55                <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_start_time]" value="<?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format( em_get_hour_format() ):''; ?>" /> 
    5656            </div> 
    5757            <div class="ticket-dates-to"> 
     
    6161                <div class="ticket-dates-to-normal"> 
    6262                    <input type="text" name="ticket_end_pub" class="em-date-input-loc em-date-end" /> 
    63                     <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_end]" class="em-date-input ticket_end" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? date("Y-m-d", $EM_Ticket->end_timestamp):''; ?>" /> 
     63                    <input type="hidden" name="em_tickets[<?php echo $col_count; ?>][ticket_end]" class="em-date-input ticket_end" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format("Y-m-d"):''; ?>" /> 
    6464                </div> 
    6565                <div class="ticket-dates-to-recurring"> 
    66                     <input type="text" name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_days]" size="3" value="<?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo absint($EM_Ticket->ticket_meta['recurrences']['end_days']); ?>" /> 
     66                    <input type="text" name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_days]" size="3" value="<?php if( isset($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] !== false ) echo absint($EM_Ticket->ticket_meta['recurrences']['end_days']); ?>" /> 
    6767                    <?php esc_html_e('day(s)','events-manager'); ?> 
    6868                    <select name="em_tickets[<?php echo $col_count; ?>][ticket_end_recurring_when]" class="ticket-dates-to-recurring-when"> 
    69                         <option value="before" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option> 
     69                        <option value="before" <?php if( isset($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] <= 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('Before','events-manager'))); ?></option> 
    7070                        <option value="after" <?php if( !empty($EM_Ticket->ticket_meta['recurrences']['end_days']) && $EM_Ticket->ticket_meta['recurrences']['end_days'] > 0) echo 'selected="selected"'; ?>><?php echo esc_html(sprintf(_x('%s the event starts','before or after','events-manager'),__('After','events-manager'))); ?></option> 
    7171                    </select> 
    7272                </div> 
    7373                <?php echo esc_html_x('at', 'time','events-manager'); ?> 
    74                 <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_end_time]" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? date( em_get_hour_format(), $EM_Ticket->end_timestamp):''; ?>" /> 
     74                <input id="end-time" class="em-time-input em-time-end ticket-times-to-normal" type="text" size="8" maxlength="8" name="em_tickets[<?php echo $col_count; ?>][ticket_end_time]" value="<?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format( em_get_hour_format() ):''; ?>" /> 
    7575            </div> 
    7676        </div> 
  • events-manager/trunk/templates/forms/event/bookings.php

    r1720802 r1786433  
    106106                                </td> 
    107107                                <td class="ticket-time"> 
    108                                     <span class="ticket_start ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date(get_option('dbem_date_format'), $EM_Ticket->start_timestamp):''; ?></span> 
     108                                    <span class="ticket_start ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format(get_option('dbem_date_format')):''; ?></span> 
    109109                                    <span class="ticket_start_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['start_days']; ?></span> 
    110110                                    <span class="ticket_start_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span> 
    111                                     <span class="ticket_start_time"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date( em_get_hour_format(), $EM_Ticket->start_timestamp):''; ?></span> 
     111                                    <span class="ticket_start_time"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? $EM_Ticket->start()->format( em_get_hour_format() ):''; ?></span> 
    112112                                    <br /> 
    113                                     <span class="ticket_end ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date(get_option('dbem_date_format'), $EM_Ticket->end_timestamp):''; ?></span> 
     113                                    <span class="ticket_end ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format(get_option('dbem_date_format')):''; ?></span> 
    114114                                    <span class="ticket_end_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['end_days']; ?></span> 
    115115                                    <span class="ticket_end_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span> 
    116                                     <span class="ticket_end_time"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date( em_get_hour_format(), $EM_Ticket->end_timestamp):''; ?></span> 
     116                                    <span class="ticket_end_time"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? $EM_Ticket->end()->format( em_get_hour_format() ):''; ?></span> 
    117117                                </td> 
    118118                                <td class="ticket-qty"> 
     
    186186            <?php _e('at','events-manager'); ?> 
    187187        </span> 
    188         <input type="text" name="event_rsvp_time" class="em-time-input" maxlength="8" size="8" value="<?php echo date( em_get_hour_format(), $EM_Event->rsvp_end ); ?>" /> 
     188        <input type="text" name="event_rsvp_time" class="em-time-input" maxlength="8" size="8" value="<?php echo $EM_Event->rsvp_end()->format(em_get_hour_format()); ?>" /> 
    189189        <br /> 
    190190        <em><?php esc_html_e('This is the definite date after which bookings will be closed for this event, regardless of individual ticket settings above. Default value will be the event start date.','events-manager'); ?></em> 
  • events-manager/trunk/templates/forms/event/recurring-when.php

    r1677796 r1786433  
    99    <p class="em-time-range"> 
    1010        <?php _e('Events start from','events-manager'); ?> 
    11         <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" /> 
     11        <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo $EM_Event->start()->i18n($hours_format); ?>" /> 
    1212        <?php _e('to','events-manager'); ?> 
    13         <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" /> 
     13        <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo $EM_Event->end()->i18n($hours_format); ?>" /> 
    1414        <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> /> 
    1515    </p> 
     16    <?php if( get_option('dbem_timezone_enabled') ): ?> 
     17    <p class="em-timezone"> 
     18        <label for="event-timezone"><?php esc_html_e('Timezone', 'events-manager'); ?></label> 
     19        <select id="event-timezone" name="event_timezone" aria-describedby="timezone-description"> 
     20            <?php echo wp_timezone_choice( $EM_Event->get_timezone()->getName(), get_user_locale() ); ?> 
     21        </select> 
     22    </p> 
     23    <?php endif; ?> 
    1624    <div class="<?php if( !empty($EM_Event->event_id) ) echo 'em-recurrence-reschedule'; ?>"> 
    1725    <?php if( !empty($EM_Event->event_id) ): ?> 
     
    6775                <?php _e ( 'Recurrences span from ', 'events-manager'); ?>                   
    6876                <input class="em-date-start em-date-input-loc" type="text" /> 
    69                 <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" /> 
     77                <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start()->getDate(); ?>" /> 
    7078                <?php _e('to','events-manager'); ?> 
    7179                <input class="em-date-end em-date-input-loc" type="text" /> 
    72                 <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" /> 
     80                <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end()->getDate(); ?>" /> 
    7381            </p> 
    7482            <p class="em-duration-range"> 
  • events-manager/trunk/templates/forms/event/when-with-recurring.php

    r1765726 r1786433  
    1313        <span class="em-event-text"><?php _e ( 'From ', 'events-manager'); ?></span>                 
    1414        <input class="em-date-start em-date-input-loc" type="text" /> 
    15         <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" /> 
     15        <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start()->getDate(); ?>" /> 
    1616        <span class="em-recurring-text"><?php _e('to','events-manager'); ?></span> 
    1717        <span class="em-event-text"><?php _e('to','events-manager'); ?></span> 
    1818        <input class="em-date-end em-date-input-loc" type="text" /> 
    19         <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" /> 
     19        <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end()->getDate(); ?>" /> 
    2020    </p> 
    2121    <p> 
    2222        <span class="em-recurring-text"><?php _e('Events start from','events-manager'); ?></span> 
    2323        <span class="em-event-text"><?php _e('Event starts at','events-manager'); ?></span> 
    24         <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" /> 
     24        <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo $EM_Event->start()->i18n($hours_format); ?>" /> 
    2525        <?php _e('to','events-manager'); ?> 
    26         <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" /> 
     26        <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo $EM_Event->end()->i18n($hours_format); ?>" /> 
    2727        <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> /> 
    2828    </p> 
     29    <?php if( get_option('dbem_timezone_enabled') ): ?> 
     30    <p class="em-timezone"> 
     31        <label for="event-timezone"><?php esc_html_e('Timezone', 'events-manager'); ?></label> 
     32        <select id="event-timezone" name="event_timezone" aria-describedby="timezone-description"> 
     33            <?php echo wp_timezone_choice( $EM_Event->get_timezone()->getName(), get_user_locale() ); ?> 
     34        </select> 
     35    </p> 
     36    <?php endif; ?> 
    2937    <div class="em-recurring-text"> 
    3038        <p> 
  • events-manager/trunk/templates/forms/event/when.php

    r1311743 r1786433  
    88        <?php _e ( 'From ', 'events-manager'); ?>                    
    99        <input class="em-date-start em-date-input-loc" type="text" /> 
    10         <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" /> 
     10        <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start()->getDate();; ?>" /> 
    1111        <?php _e('to','events-manager'); ?> 
    1212        <input class="em-date-end em-date-input-loc" type="text" /> 
    13         <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" /> 
     13        <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end()->getDate();; ?>" /> 
    1414    </p> 
    1515    <p class="em-time-range"> 
    1616        <span class="em-event-text"><?php _e('Event starts at','events-manager'); ?></span> 
    17         <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" /> 
     17        <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo $EM_Event->start()->format($hours_format); ?>" /> 
    1818        <?php _e('to','events-manager'); ?> 
    19         <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" /> 
     19        <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo $EM_Event->end()->format($hours_format); ?>" /> 
    2020        <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-all-day" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> /> 
    2121    </p> 
     22    <?php if( get_option('dbem_timezone_enabled') ): ?> 
     23    <p class="em-timezone"> 
     24        <label for="event-timezone"><?php esc_html_e('Timezone', 'events-manager'); ?></label> 
     25        <select id="event-timezone" name="event_timezone" aria-describedby="timezone-description"> 
     26            <?php echo wp_timezone_choice( $EM_Event->get_timezone()->getName(), get_user_locale() ); ?> 
     27        </select> 
     28    </p> 
     29    <?php endif; ?> 
    2230    <span id='event-date-explanation'> 
    23     <?php _e( 'This event spans every day between the beginning and end date, with start/end times applying to each day.', 'events-manager'); ?> 
     31    <?php esc_html_e( 'This event spans every day between the beginning and end date, with start/end times applying to each day.', 'events-manager'); ?> 
    2432    </span> 
    2533</div>   
  • events-manager/trunk/templates/tables/events.php

    r1651260 r1786433  
    7575                        $rowno++; 
    7676                        $class = ($rowno % 2) ? 'alternate' : ''; 
    77                         // FIXME set to american                         
    78                         $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start); 
    79                         $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end); 
    80                         $style = ""; 
    81                         $today = current_time('timestamp'); 
    8277                        $location_summary = "<b>" . esc_html($EM_Event->get_location()->location_name) . "</b><br/>" . esc_html($EM_Event->get_location()->location_address) . " - " . esc_html($EM_Event->get_location()->location_town); 
    8378                         
    84                         if ($EM_Event->start < $today && $EM_Event->end < $today){                       
     79                        if( $EM_Event->start()->getTimestamp() < time() && $EM_Event->end()->getTimestamp() < time() ){ 
    8580                            $class .= " past"; 
    8681                        } 
     
    9085                        }                    
    9186                        ?> 
    92                         <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $EM_Event->event_id ?>"> 
     87                        <tr class="event <?php echo trim($class); ?>" id="event_<?php echo $EM_Event->event_id ?>"> 
    9388                            <?php /* 
    9489                            <td> 
     
    125120                                <?php echo $location_summary; ?> 
    126121                            </td> 
    127                      
    128122                            <td> 
    129                                 <?php echo $localised_start_date; ?> 
    130                                 <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?> 
     123                                <?php echo $EM_Event->output_dates(); ?> 
    131124                                <br /> 
    132                                 <?php 
    133                                     if(!$EM_Event->event_all_day){ 
    134                                         echo date_i18n(get_option('time_format'), $EM_Event->start) . " - " . date_i18n(get_option('time_format'), $EM_Event->end); 
    135                                     }else{ 
    136                                         echo get_option('dbem_event_all_day_message'); 
    137                                     } 
    138                                 ?> 
     125                                <?php echo $EM_Event->output_times(); ?> 
    139126                            </td> 
    140127                            <td> 
  • events-manager/trunk/templates/templates/ical.php

    r1651260 r1786433  
    66$parsed_url = parse_url(get_bloginfo('url')); 
    77$site_domain = preg_replace('/^www./', '', $parsed_url['host']); 
     8$timezone_support = defined('EM_ICAL_TIMEZONE_SUPPORT') ? EM_ICAL_TIMEZONE_SUPPORT : true; 
    89 
    910//figure out limits 
     
    1213//get passed on $args and merge with defaults 
    1314$args = !empty($args) ? $args:array(); /* @var $args array */ 
    14 $args = array_merge(array('limit'=>$page_limit, 'page'=>'1', 'owner'=>false, 'orderby'=>'event_start_date', 'scope' => get_option('dbem_ical_scope') ), $args); 
     15$args = array_merge(array('limit'=>$page_limit, 'page'=>'1', 'owner'=>false, 'orderby'=>'event_start_date,event_start_time', 'scope' => get_option('dbem_ical_scope') ), $args); 
    1516$args = apply_filters('em_calendar_template_args',$args); 
    1617//get first round of events to show, we'll start adding more via the while loop 
    1718$EM_Events = EM_Events::get( $args ); 
     19$timezones = array(); 
    1820 
    1921//calendar header 
    20 $output = "BEGIN:VCALENDAR 
     22$output_header = "BEGIN:VCALENDAR 
    2123VERSION:2.0 
    2224PRODID:-//wp-events-plugin.com//".EM_VERSION."//EN"; 
    23 echo preg_replace("/([^\r])\n/", "$1\r\n", $output); 
     25 
     26//if timezone is supported, we output the blog timezone here 
     27if( $timezone_support ){ 
     28    //get default blog timezone and output only if we're not in UTC or with manual offsets 
     29    $blog_timezone = EM_DateTimeZone::create()->getName(); 
     30    if( !preg_match('/^UTC/', $blog_timezone) ){ 
     31        $output_header .= " 
     32TZID:{$blog_timezone} 
     33X-WR-TIMEZONE:{$blog_timezone}"; 
     34    } 
     35} 
     36 
     37echo preg_replace("/([^\r])\n/", "$1\r\n", $output_header); 
    2438 
    2539//loop through events 
     
    2943        /* @var $EM_Event EM_Event */ 
    3044        if( $ical_limit != 0 && $count > $ical_limit ) break; //we've reached our maximum 
     45        //figure out the timezone of this event, or if it's an offset and add to list of timezones and date ranges to define in VTIMEZONE 
     46        $show_timezone = $timezone_support && !preg_match('/^UTC/', $EM_Event->get_timezone()->getName()); 
     47        if( $show_timezone ){ 
     48            $timezone = $EM_Event->start()->getTimezone()->getName(); 
     49            if( empty($timezones[$timezone]) ){ 
     50                $timezones[$timezone] = array( $EM_Event->start()->getTimestamp(), $EM_Event->end()->getTimestamp() ); 
     51            }else{ 
     52                if( $timezones[$timezone][0] > $EM_Event->start()->getTimestamp() ) $timezones[$timezone][0] = $EM_Event->start()->getTimestamp(); 
     53                if( $timezones[$timezone][1] < $EM_Event->end()->getTimestamp() ) $timezones[$timezone][1] = $EM_Event->end()->getTimestamp(); 
     54            } 
     55        } 
    3156        //calculate the times along with timezone offsets 
    3257        if($EM_Event->event_all_day){ 
    33             $dateStart  = ';VALUE=DATE:'.date('Ymd',$EM_Event->start); //all day 
    34             $dateEnd    = ';VALUE=DATE:'.date('Ymd',$EM_Event->end + 86400); //add one day 
     58            //we get local time since we're representing a date not a time 
     59            $dateStart  = ';VALUE=DATE:'.$EM_Event->start()->format('Ymd'); //all day 
     60            $dateEnd    = ';VALUE=DATE:'.$EM_Event->end()->clone()->add( new DateInterval('P1D') )->format('Ymd'); //add one day 
    3561        }else{ 
    36             $dateStart  = ':'.get_gmt_from_date(date('Y-m-d H:i:s', $EM_Event->start), 'Ymd\THis\Z'); 
    37             $dateEnd = ':'.get_gmt_from_date(date('Y-m-d H:i:s', $EM_Event->end), 'Ymd\THis\Z'); 
     62            //get date output with timezone and local time if timezone output is enabled, or UTC time if not and/or if offset is manual 
     63            if( $show_timezone ){ 
     64                //show local time and define a timezone 
     65                $dateStart  = ':'.$EM_Event->start()->format('Ymd\THis'); 
     66                $dateEnd = ':'.$EM_Event->end()->format('Ymd\THis'); 
     67            }else{ 
     68                //create a UTC equivalent time for all events irrespective of timezone 
     69                $dateStart  = ':'.$EM_Event->start(true)->format('Ymd\THis\Z'); 
     70                $dateEnd = ':'.$EM_Event->end(true)->format('Ymd\THis\Z'); 
     71            } 
     72        } 
     73        if( $show_timezone ){ 
     74            $dateStart = ';TZID='.$timezone . $dateStart; 
     75            $dateEnd = ';TZID='.$timezone . $dateEnd; 
    3876        } 
    3977        if( !empty($EM_Event->event_date_modified) && $EM_Event->event_date_modified != '0000-00-00 00:00:00' ){ 
     
    89127if( $image ){ 
    90128    $image = wordwrap("ATTACH;FMTTYPE=image/jpeg:".esc_url_raw($image), 74, "\n ", true); 
    91     $output .= " 
    92 {$image}"; 
     129    $output .= "\r\n" . $image; 
    93130} 
    94131//add categories if there are any 
    95132if( !empty($categories) ){ 
    96133    $categories = wordwrap("CATEGORIES:".implode(',', $categories), 74, "\n ", true); 
    97     $output .= " 
    98 {$categories}"; 
     134    $output .= "\r\n" . $categories; 
    99135} 
    100136//Location if there is one 
    101137if( $location ){ 
    102     $output .= " 
    103 {$location}"; 
     138    $output .= "\r\n" . $location; 
    104139    //geo coordinates if they exist 
    105140    if( $geo ){ 
    106     $output .= " 
    107 {$geo}"; 
     141        $output .= "\r\n" . $geo; 
    108142    } 
    109143    //create apple-compatible feature for locations 
    110144    if( !empty($apple_structured_location) ){ 
    111     $output .= " 
    112 {$apple_structured_location}"; 
     145        $output .= "\r\n" . $apple_structured_location; 
    113146    } 
    114147} 
     
    131164} 
    132165 
     166//Now we sort out timezones and add it to the top of the output 
     167if( $timezone_support && !empty($timezones) ){ 
     168    $vtimezones = array(); 
     169    foreach( $timezones as $timezone => $timezone_range ){ 
     170        $vtimezones[$timezone] = array(); 
     171        $previous_offset = false; 
     172        //get the range of transitions, with a year's cushion so we can calculate the TZOFFSETFROM value 
     173        $EM_DateTimeZone = EM_DateTimeZone::create($timezone); 
     174        $timezone_transitions = $EM_DateTimeZone->getTransitions($timezone_range[0] - YEAR_IN_SECONDS, $timezone_range[1] + YEAR_IN_SECONDS); 
     175        do{ 
     176            $current_transition = current($timezone_transitions); 
     177            $transition_key = key($timezone_transitions); 
     178            $next_transition = next($timezone_transitions); 
     179            //format the offset to a UTC-OFFSET 
     180            $current_offset_sign = $current_transition['offset'] < 0 ? '-' : '+'; 
     181            $current_offset_hours = absint(floor($current_transition['offset'] / HOUR_IN_SECONDS)); 
     182            $current_offset_minute_seconds = absint($current_transition['offset']) - $current_offset_hours*HOUR_IN_SECONDS; 
     183            $current_offset_minutes = $current_offset_minute_seconds == 0 ? 0 : absint($current_offset_minute_seconds / MINUTE_IN_SECONDS); 
     184            $current_transition['offset'] = $current_offset_sign . str_pad($current_offset_hours, 2, "0", STR_PAD_LEFT) . str_pad($current_offset_minutes, 2, "0", STR_PAD_LEFT); 
     185            //skip transitions before and after the event date range, assuming we have some in between 
     186            if( !empty($next_transition) && $next_transition['ts'] < $timezone_range[0] ){ 
     187                //remember previous offset 
     188                $previous_offset = $current_transition['offset']; 
     189                continue; 
     190            } 
     191            if( $current_transition['ts'] > $timezone_range[1] ) break; 
     192            //modify the transition array directly and add it to vtimezones array 
     193            unset( $current_transition['time'] ); 
     194            $current_transition['isdst'] = $current_transition['isdst'] ? 'DAYLIGHT':'STANDARD'; 
     195            $EM_DateTime = new EM_DateTime($current_transition['ts'], $EM_DateTimeZone); 
     196            $current_transition['ts'] = $EM_DateTime->format('Ymd\THis'); 
     197            $current_transition['offsetfrom'] = $previous_offset === false ? $current_transition['offset'] : $previous_offset; 
     198            $vtimezones[$timezone][] = $current_transition; 
     199            //remember previous offset 
     200            $previous_offset = $current_transition['offset']; 
     201        } while( $next_transition !== false ); 
     202    } 
     203    foreach( $vtimezones as $timezone => $timezone_transitions ){ 
     204        $output = " 
     205BEGIN:VTIMEZONE 
     206TZID:{$timezone} 
     207X-LIC-LOCATION:{$timezone}"; 
     208        foreach( $timezone_transitions as $transition ){ 
     209            $output .= " 
     210BEGIN:{$transition['isdst']} 
     211DTSTART:{$transition['ts']} 
     212TZOFFSETFROM:{$transition['offsetfrom']} 
     213TZOFFSETTO:{$transition['offset']} 
     214TZNAME:{$transition['abbr']} 
     215END:{$transition['isdst']}"; 
     216        } 
     217        $output .= " 
     218END:VTIMEZONE"; 
     219        echo preg_replace("/([^\r])\n/", "$1\r\n", $output); 
     220    } 
     221} 
     222 
    133223//calendar footer 
    134 $output = "\r\n"."END:VCALENDAR"; 
    135 echo preg_replace("/([^\r])\n/", "$1\r\n", $output); 
     224echo "\r\n"."END:VCALENDAR"; 
  • events-manager/trunk/templates/templates/my-bookings.php

    r1311743 r1786433  
    5757                                <tr> 
    5858                                    <td><?php echo $EM_Event->output("#_EVENTLINK"); ?></td> 
    59                                     <td><?php echo date_i18n( get_option('dbem_date_format'), $EM_Event->start ); ?></td> 
     59                                    <td><?php echo $EM_Event->start()->i18n( get_option('dbem_date_format') ); ?></td> 
    6060                                    <td><?php echo $EM_Booking->get_spaces() ?></td> 
    6161                                    <td> 
  • events-manager/trunk/templates/templates/rss.php

    r1234828 r1786433  
    1515        <description><?php echo esc_html(get_option('dbem_rss_main_description')); ?></description> 
    1616        <docs>http://blogs.law.harvard.edu/tech/rss</docs> 
    17         <pubDate><?php echo date('D, d M Y H:i:s +0000', get_option('em_last_modified', current_time('timestamp',true))); ?></pubDate> 
     17        <pubDate><?php echo date('D, d M Y H:i:s +0000', get_option('em_last_modified')); ?></pubDate> 
    1818        <atom:link href="<?php echo esc_attr(EM_RSS_URI); ?>" rel="self" type="application/rss+xml" /> 
    1919        <?php 
     
    3737                    <link><?php echo $event_url; ?></link> 
    3838                    <guid><?php echo $event_url; ?></guid> 
    39                     <pubDate><?php echo get_gmt_from_date(date('Y-m-d H:i:s', $EM_Event->start), 'D, d M Y H:i:s +0000'); ?></pubDate> 
     39                    <pubDate><?php echo $EM_Event->start(true)->format('D, d M Y H:i:s +0000'); ?></pubDate> 
    4040                    <description><![CDATA[<?php echo $description; ?>]]></description> 
    4141                </item> 
  • events-manager/trunk/widgets/em-calendar.php

    r1311743 r1786433  
    3636        }else{ 
    3737            $instance['month'] = date("m"); 
     38            $instance['year'] = date('Y'); 
    3839        } 
    3940         
Note: See TracChangeset for help on using the changeset viewer.