post_id == $id->ID ){ return apply_filters('em_get_event', $EM_Event); }elseif( !is_object($id) ){ if( $search_by == 'event_id' && $EM_Event->event_id == $id ){ return apply_filters('em_get_event', $EM_Event); }elseif( $search_by == 'post_id' && $EM_Event->post_id == $id ){ return apply_filters('em_get_event', $EM_Event); } } } if( is_object($id) && get_class($id) == 'EM_Event' ){ return apply_filters('em_get_event', $id); }else{ return apply_filters('em_get_event', new EM_Event($id,$search_by)); } } /** * Event Object. This holds all the info pertaining to an event, including location and recurrence info. * An event object can be one of three "types" a recurring event, recurrence of a recurring event, or a single event. * The single event might be part of a set of recurring events, but if loaded by specific event id then any operations and saves are * specifically done on this event. However, if you edit the recurring group, any changes made to single events are overwritten. * * @author marcus */ //TODO Can add more recurring functionality such as "also update all future recurring events" or "edit all events" like google calendar does. //TODO Integrate recurrences into events table //FIXME If you create a super long recurrence timespan, there could be thousands of events... need an upper limit here. class EM_Event extends EM_Object{ /* Field Names */ var $event_id; var $post_id; var $event_slug; var $event_owner; var $event_name; var $event_start_time; var $event_end_time; var $event_all_day; var $event_start_date; var $event_end_date; var $post_content; var $event_rsvp; var $event_rsvp_date; var $event_rsvp_time = "00:00:00"; var $event_spaces; var $location_id; var $recurrence_id; var $event_status; var $event_date_created; var $event_date_modified; var $blog_id; var $group_id; /** * Populated with the non-hidden event post custom fields (i.e. not starting with _) * @var array */ var $event_attributes = array(); /* Recurring Specific Values */ var $recurrence; var $recurrence_interval; var $recurrence_freq; var $recurrence_byday; var $recurrence_days = 0; var $recurrence_byweekno; /* anonymous submission information */ var $event_owner_anonymous; var $event_owner_name; var $event_owner_email; /** * Previously used to give this object shorter property names for db values (each key has a name) but this is now depreciated, use the db field names as properties. This propertey provides extra info about the db fields. * @var array */ var $fields = array( 'event_id' => array( 'name'=>'id', 'type'=>'%d' ), 'post_id' => array( 'name'=>'post_id', 'type'=>'%d' ), 'event_slug' => array( 'name'=>'slug', 'type'=>'%s', 'null'=>true ), 'event_owner' => array( 'name'=>'owner', 'type'=>'%d', 'null'=>true ), 'event_name' => array( 'name'=>'name', 'type'=>'%s', 'null'=>true ), 'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s', 'null'=>true ), 'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s', 'null'=>true ), 'event_all_day' => array( 'name'=>'all_day', 'type'=>'%d', 'null'=>true ), 'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s', 'null'=>true ), 'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s', 'null'=>true ), 'post_content' => array( 'name'=>'notes', 'type'=>'%s', 'null'=>true ), 'event_rsvp' => array( 'name'=>'rsvp', 'type'=>'%d', 'null'=>true ), //has a default, so can be null/excluded 'event_rsvp_date' => array( 'name'=>'rsvp_date', 'type'=>'%s', 'null'=>true ), 'event_rsvp_time' => array( 'name'=>'rsvp_time', 'type'=>'%s', 'null'=>true ), 'event_spaces' => array( 'name'=>'spaces', 'type'=>'%d', 'null'=>true), 'location_id' => array( 'name'=>'location_id', 'type'=>'%d', 'null'=>true ), 'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d', 'null'=>true ), 'event_status' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ), 'event_private' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ), 'event_date_created' => array( 'name'=>'date_created', 'type'=>'%s', 'null'=>true ), 'event_date_modified' => array( 'name'=>'date_modified', 'type'=>'%s', 'null'=>true ), 'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s', 'null'=>true ), 'blog_id' => array( 'name'=>'blog_id', 'type'=>'%d', 'null'=>true ), 'group_id' => array( 'name'=>'group_id', 'type'=>'%d', 'null'=>true ), 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s) 'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s) 'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s', 'null'=>true ), //daily,weekly,monthly? 'recurrence_days' => array( 'name'=>'days', 'type'=>'%d', 'null'=>true ), //daily,weekly,monthly? 'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s', 'null'=>true ), //if weekly or monthly, what days of the week? 'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d', 'null'=>true ), //if monthly which week (-1 is last) ); var $post_fields = array('event_slug','event_owner','event_name','event_attributes','post_id','post_content'); //fields that won't be taken from the em_events table anymore var $recurrence_fields = array('recurrence_interval', 'recurrence_freq', 'recurrence_days', 'recurrence_byday', 'recurrence_byweekno'); var $image_url = ''; /** * Timestamp of start date/time * @var int */ var $start; /** * Timestamp of end date/time * @var int */ var $end; /** * Timestamp for booking cut-off date/time * @var int */ var $rsvp_end; /** * Created on timestamp, taken from DB, converted to TS * @var int */ var $created; /** * Created on timestamp, taken from DB, converted to TS * @var int */ var $modified; /** * @var EM_Location */ var $location; /** * @var EM_Bookings */ var $bookings; /** * The contact person for this event * @var WP_User */ var $contact; /** * The category object * @var EM_Category */ var $category; /** * If there are any errors, they will be added here. * @var array */ var $errors = array(); /** * If something was successful, a feedback message might be supplied here. * @var string */ var $feedback_message; /** * Any warnings about an event (e.g. bad data, recurrence, etc.) * @var string */ var $warnings; /** * Array of dbem_event field names required to create an event * @var array */ var $required_fields = array('event_name', 'event_start_date'); var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png'); /** * previous status of event when instantiated * @access protected * @var mixed */ var $previous_status = 0; /* Post Variables - copied out of post object for easy IDE reference */ var $ID; var $post_author; var $post_date; var $post_date_gmt; var $post_title; var $post_excerpt; var $post_status; var $comment_status; var $ping_status; var $post_password; var $post_name; var $to_ping; var $pinged; var $post_modified; var $post_modified_gmt; var $post_content_filtered; var $post_parent; var $guid; var $menu_order; var $post_type; var $post_mime_type; var $comment_count; var $ancestors; var $filter; /** * 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. * @param mixed $event_data * @param mixed $search_by default is post_id, otherwise it can be by event_id as well. * @return null */ function __construct($id = false, $search_by = 'event_id') { global $wpdb; if( is_array($id) ){ //deal with the old array style, but we can't supply arrays anymore $id = (!empty($id['event_id'])) ? $id['event_id'] : $id['post_id']; $search_by = (!empty($id['event_id'])) ? 'event_id':'post_id'; } $is_post = !empty($id->ID) && ($id->post_type == EM_POST_TYPE_EVENT || $id->post_type == 'event-recurring'); if( is_numeric($id) || $is_post ){ //only load info if $id is a number if($search_by == 'event_id' && !$is_post ){ //search by event_id, get post_id and blog_id (if in ms mode) and load the post $results = $wpdb->get_row($wpdb->prepare("SELECT post_id, blog_id FROM ".EM_EVENTS_TABLE." WHERE event_id=%d",$id), ARRAY_A); if( is_multisite() && (is_numeric($results['blog_id']) || $results['blog_id']=='' ) ){ if( $results['blog_id']=='' ) $results['blog_id'] = get_current_site()->blog_id; $event_post = get_blog_post($results['blog_id'], $results['post_id']); $search_by = $results['blog_id']; }else{ $event_post = get_post($results['post_id']); } }else{ if(!$is_post){ if( is_multisite() && (is_numeric($search_by) || $search_by == '') ){ if( $search_by == '' ) $search_by = get_current_site()->blog_id; //we've been given a blog_id, so we're searching for a post id $event_post = get_blog_post($search_by, $id); }else{ //search for the post id only $event_post = get_post($id); } }else{ $event_post = $id; } } $this->load_postdata($event_post, $search_by); } $this->recurrence = $this->is_recurring() ? 1:0; //if(defined('trashtest')){ print_r($this); die("got here");} //Do it here so things appear in the po file. $this->status_array = array( 0 => __('Pending','dbem'), 1 => __('Approved','dbem') ); do_action('em_event', $this, $id, $search_by); } function load_postdata($event_post, $search_by = false){ if( is_object($event_post) ){ //load post data - regardless $this->post_id = $event_post->ID; $this->event_name = $event_post->post_title; $this->event_owner = $event_post->post_author; $this->post_content = $event_post->post_content; $this->event_slug = $event_post->post_name; $this->event_modified = $event_post->post_modified; foreach( $event_post as $key => $value ){ //merge post object into this object $this->$key = $value; } $this->previous_status = $this->event_status; //so we know about updates $this->recurrence = $this->is_recurring() ? 1:0; //load meta data and other related information if( $event_post->post_status != 'auto-draft' ){ $event_meta = $this->get_event_meta($search_by); //Get custom fields and post meta foreach($event_meta as $event_meta_key => $event_meta_val){ $field_name = substr($event_meta_key, 1); if($event_meta_key[0] != '_'){ $this->event_attributes[$event_meta_key] = ( count($event_meta_val) > 1 ) ? $event_meta_val:$event_meta_val[0]; }elseif( is_string($field_name) && !in_array($field_name, $this->post_fields) ){ if( array_key_exists($field_name, $this->fields) ){ $this->$field_name = $event_meta_val[0]; }elseif( in_array($field_name, array('event_owner_name','event_owner_anonymous','event_owner_email')) ){ $this->$field_name = $event_meta_val[0]; } } } //Start/End times should be available as timestamp $this->start = strtotime($this->event_start_date." ".$this->event_start_time); $this->end = strtotime($this->event_end_date." ".$this->event_end_time); if( !empty($this->event_rsvp_date ) ){ $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time); } //quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta if( empty($this->event_id) && !$this->is_recurring() ){ global $wpdb; $event_array = $wpdb->get_row('SELECT * FROM '.EM_EVENTS_TABLE. ' WHERE post_id='.$event_post->ID, ARRAY_A); if( !empty($event_array['event_id']) ){ foreach($event_array as $key => $value){ if( !empty($value) && empty($this->$key) ){ update_post_meta($event_post->ID, '_'.$key, $value); $this->$key = $value; } } } } } $this->get_status(); $this->compat_keys(); } } function get_event_meta($blog_id = false){ if( is_numeric($blog_id) && $blog_id > 0 && is_multisite() ){ // if in multisite mode, switch blogs quickly to get the right post meta. switch_to_blog($blog_id); $event_meta = get_post_meta($this->post_id); restore_current_blog(); $this->blog_id = $blog_id; }else{ $event_meta = get_post_meta($this->post_id); } return $event_meta; } /** * Retrieve event information via POST (only used in situations where posts aren't submitted via WP) * @return boolean */ function get_post($validate = true){ global $allowedposttags; //we need to get the post/event name and content.... that's it. $this->post_content = isset($_POST['content']) ? wp_kses( stripslashes($_POST['content']), $allowedposttags):''; $this->event_name = !empty($_POST['event_name']) ? htmlspecialchars_decode(wp_kses_data(htmlspecialchars_decode(stripslashes($_POST['event_name'])))):''; $this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT; //don't forget categories! $this->get_categories()->get_post(); //anonymous submissions and guest basic info if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){ $this->event_owner_anonymous = 1; $this->event_owner_name = !empty($_POST['event_owner_name']) ? wp_kses_data(stripslashes($_POST['event_owner_name'])):''; $this->event_owner_email = !empty($_POST['event_owner_email']) ? wp_kses_data($_POST['event_owner_email']):''; } //get the rest and validate (optional) $this->get_post_meta(false); $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true return apply_filters('em_event_get_post', $result, $this); } /** * Retrieve event post meta information via POST, which should be always be called when saving the event custom post via WP. * @param boolean $validate whether or not to run validation, default is true * @return boolean */ function get_post_meta($validate = true){ //Grab POST data $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : ''; $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date; //check if this is recurring or not if( !empty($_POST['recurring']) ){ $this->recurrence = 1; $this->post_type = 'event-recurring'; } //Get Location info if( !get_option('dbem_locations_enabled') || (!empty($_POST['no_location']) && !get_option('dbem_require_location',true)) || (empty($_POST['location_id']) && !get_option('dbem_require_location',true) && get_option('dbem_use_select_for_locations')) ){ $this->location_id = 0; }elseif( !empty($_POST['location_id']) && is_numeric($_POST['location_id']) ){ $this->location_id = $_POST['location_id']; }else{ //we're adding a new location, so create an empty location and populate $this->location_id = null; $this->get_location()->get_post(false); $this->get_location()->post_content = ''; //reset post content, as it'll grab the event description otherwise } //Sort out time $this->event_all_day = ( !empty($_POST['event_all_day']) ) ? 1 : 0; if( !$this->event_all_day ){ $match = array(); foreach( array('event_start_time','event_end_time', 'event_rsvp_time') as $timeName ){ if( !empty($_POST[$timeName]) && preg_match ( '/^([01]\d|2[0-3]):([0-5]\d) ?(AM|PM)?$/', $_POST[$timeName], $match ) ){ if( !empty($match[3]) && $match[3] == 'PM' && $match[1] != 12 ){ $match[1] = 12+$match[1]; }elseif( !empty($match[3]) && $match[3] == 'AM' && $match[1] == 12 ){ $match[1] = '00'; } $this->$timeName = $match[1].":".$match[2].":00"; }else{ $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time; } } }else{ $this->event_start_time = $this->event_end_time = '00:00:00'; } //Start/End times should be available as timestamp $this->start = strtotime($this->event_start_date." ".$this->event_start_time); $this->end = strtotime($this->event_end_date." ".$this->event_end_time); //Bookings if( !empty($_POST['event_rsvp']) && $_POST['event_rsvp'] ){ $this->get_bookings()->get_tickets()->get_post(); $this->event_rsvp = 1; //RSVP cuttoff TIME is set up above where start/end times are as well if( !$this->is_recurring() ){ $this->event_rsvp_date = ( isset($_POST['event_rsvp_date']) ) ? wp_kses_data($_POST['event_rsvp_date']) : $this->event_start_date; if( empty($this->event_rsvp_date) ){ $this->event_rsvp_time = '00:00:00'; } } $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0; }else{ $this->event_rsvp = 0; $this->event_rsvp_time = '00:00:00'; } //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes) if(get_option('dbem_attributes_enabled')){ global $allowedtags; if( !is_array($this->event_attributes) ){ $this->event_attributes = array(); } $event_available_attributes = em_get_attributes(); if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){ foreach($_POST['em_attributes'] as $att_key => $att_value ){ if( (in_array($att_key, $event_available_attributes['names']) || array_key_exists($att_key, $this->event_attributes) ) ){ $this->event_attributes[$att_key] = ''; $att_vals = count($event_available_attributes['values'][$att_key]); if( !empty($att_value) ){ if( $att_vals <= 1 || ($att_vals > 1 && in_array($att_value, $event_available_attributes['values'][$att_key])) ){ $this->event_attributes[$att_key] = stripslashes($att_value); } } if( empty($att_value) && $att_vals > 1){ $this->event_attributes[$att_key] = stripslashes(wp_kses($event_available_attributes['values'][$att_key][0], $allowedtags)); } } } } } //Set Blog ID if( is_multisite() ){ $this->blog_id = get_current_blog_id(); } //group id $this->group_id = (!empty($_POST['group_id']) && is_numeric($_POST['group_id'])) ? $_POST['group_id']:0; //Recurrence data if( $this->is_recurring() ){ $this->recurrence = 1; //just in case $this->recurrence_freq = ( !empty($_POST['recurrence_freq']) && in_array($_POST['recurrence_freq'], array('daily','weekly','monthly','yearly')) ) ? $_POST['recurrence_freq']:'daily'; if( !empty($_POST['recurrence_bydays']) && $this->recurrence_freq == 'weekly' && self::array_is_numeric($_POST['recurrence_bydays']) ){ $this->recurrence_byday = implode( ",", $_POST['recurrence_bydays'] ); }elseif( !empty($_POST['recurrence_byday']) && $this->recurrence_freq == 'monthly' ){ $this->recurrence_byday = wp_kses_data($_POST['recurrence_byday']); } $this->recurrence_interval = ( !empty($_POST['recurrence_interval']) && is_numeric($_POST['recurrence_interval']) ) ? $_POST['recurrence_interval']:1; $this->recurrence_byweekno = ( !empty($_POST['recurrence_byweekno']) ) ? wp_kses_data($_POST['recurrence_byweekno']):''; $this->recurrence_days = ( !empty($_POST['recurrence_days']) && is_numeric($_POST['recurrence_days']) ) ? (int) $_POST['recurrence_days']:0; } //categories in MS GLobal if(EM_MS_GLOBAL && !is_main_site()){ $this->get_categories()->get_post(); //it'll know what to do } //validate (optional) and return result $this->compat_keys(); //compatability return apply_filters('em_event_get_post', count($this->errors) == 0, $this); } function validate(){ $validate_post = true; if( empty($this->event_name) ){ $validate_post = false; $this->add_error( sprintf(__("%s is required.", "dbem"), __('Event name','dbem')) ); } //anonymous submissions and guest basic info if( !empty($this->event_owner_anonymous) ){ if( !is_email($this->event_owner_email) ){ $this->add_error( sprintf(__("%s is required.", "dbem"), __('A valid email','dbem')) ); } if( empty($this->event_owner_name) ){ $this->add_error( sprintf(__("%s is required.", "dbem"), __('Your name','dbem')) ); } } $validate_tickets = $this->get_bookings()->get_tickets()->validate(); $validate_image = $this->image_validate(); $validate_meta = $this->validate_meta(); return apply_filters('em_event_validate', $validate_post && $validate_image && $validate_meta && $validate_tickets, $this ); } function validate_meta(){ $missing_fields = Array (); foreach ( array('event_start_date') as $field ) { if ( $this->$field == "") { $missing_fields[$field] = $field; } } 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) ){ if( strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_end_date . $this->event_end_time) ){ $this->add_error(__('Events cannot start after they end.','dbem')); }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) ){ $this->add_error(__('Events cannot start after they end.','dbem').' '.__('For recurring events that end the following day, ensure you make your event last 1 or more days.')); } }else{ if( !empty($missing_fields['event_start_date']) ) { unset($missing_fields['event_start_date']); } if( !empty($missing_fields['event_end_date']) ) { unset($missing_fields['event_end_date']); } $this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','dbem')); } if( $this->event_rsvp ){ if( !$this->get_bookings()->get_tickets()->validate() ){ $this->add_error($this->get_bookings()->get_tickets()->get_errors()); } if( !empty($this->event_rsvp_date) && !preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_rsvp_date) ){ $this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','dbem')); } } if( get_option('dbem_locations_enabled') && empty($this->location_id) ){ //location ids don't need validating as we're not saving a location if( get_option('dbem_require_location',true) || $this->location_id !== 0 ){ if( !$this->get_location()->validate() ){ $this->add_error($this->get_location()->get_errors()); } } } if ( count($missing_fields) > 0){ // TODO Create friendly equivelant names for missing fields notice in validation $this->add_error( __( 'Missing fields: ', 'dbem') . implode ( ", ", $missing_fields ) . ". " ); } if ( $this->is_recurring() && ($this->event_end_date == "" || $this->event_end_date == $this->event_start_date) ){ $this->add_error( __( 'Since the event is repeated, you must specify an event end date greater than the start date.', 'dbem' )); } return apply_filters('em_event_validate_meta', count($this->errors) == 0, $this ); } /** * Will save the current instance into the database, along with location information if a new one was created and return true if successful, false if not. * Will automatically detect whether it's a new or existing event. * @return boolean */ function save(){ global $wpdb, $current_user, $blog_id; if( !$this->can_manage('edit_events', 'edit_others_events') && !( get_option('dbem_events_anonymous_submissions') && empty($this->event_id)) ){ //unless events can be submitted by an anonymous user (and this is a new event), user must have permissions. return apply_filters('em_event_save', false, $this); } remove_action('save_post',array('EM_Event_Post_Admin','save_post'),10,1); //disable the default save post action, we'll do it manually this way do_action('em_event_save_pre', $this); $post_array = array(); //Deal with updates to an event if( !empty($this->post_id) ){ //get the full array of post data so we don't overwrite anything. if( !empty($this->blog_id) && is_multisite() ){ $post_array = (array) get_blog_post($this->blog_id, $this->post_id); }else{ $post_array = (array) get_post($this->post_id); } } //Overwrite new post info $post_array['post_type'] = ($this->recurrence && get_option('dbem_recurrence_enabled')) ? 'event-recurring':EM_POST_TYPE_EVENT; $post_array['post_title'] = $this->event_name; $post_array['post_content'] = $this->post_content; //decide on post status if( empty($this->force_status) ){ if( count($this->errors) == 0 ){ $post_array['post_status'] = ( $this->can_manage('publish_events','publish_events') ) ? 'publish':'pending'; }else{ $post_array['post_status'] = 'draft'; } }else{ $post_array['post_status'] = $this->force_status; } //anonymous submission only if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){ $post_array['post_author'] = get_option('dbem_events_anonymous_user'); if( !is_numeric($post_array['post_author']) ) $post_array['post_author'] = 0; } //Save post and continue with meta $post_id = wp_insert_post($post_array); $post_save = false; $meta_save = false; if( !is_wp_error($post_id) && !empty($post_id) ){ $post_save = true; //refresh this event with wp post info we'll put into the db $post_data = get_post($post_id); $this->post_id = $post_id; $this->event_slug = $post_data->post_name; $this->event_owner = $post_data->post_author; $this->post_status = $post_data->post_status; $this->get_status(); //Categories? note that categories will soft-fail, so no errors $this->get_categories()->event_id = $this->event_id; $this->categories->post_id = $this->post_id; $this->categories->save(); //anonymous submissions should save this information if( !empty($this->event_owner_anonymous) ){ update_post_meta($this->post_id, '_event_owner_anonymous', 1); update_post_meta($this->post_id, '_event_owner_name', $this->event_owner_name); update_post_meta($this->post_id, '_event_owner_email', $this->event_owner_email); } //save the image $this->image_upload(); //now save the meta $meta_save = $this->save_meta(); $image_save = (count($this->errors) == 0); //whilst it might not be an image save that fails, we can know something went wrong } $result = $meta_save && $post_save && $image_save; $previous_status = $this->previous_status; if($result) $this->load_postdata($post_data, $blog_id); //reload post info $this->previous_status = $previous_status; //do a dirty update for location too if it's not published if( $this->is_published() && !empty($this->location_id) ){ $EM_Location = $this->get_location(); if( $EM_Location->location_status !== 1 ){ //let's also publish the location $EM_Location->set_status(1, true); } } return apply_filters('em_event_save', $result, $this); } function save_meta(){ global $wpdb; if( ( get_option('dbem_events_anonymous_submissions') && empty($this->event_id)) || $this->can_manage('edit_events', 'edit_others_events') ){ do_action('em_event_save_meta_pre', $this); //first save location if( empty($this->location_id) && !($this->location_id === 0 && !get_option('dbem_require_location',true)) ){ if( !$this->get_location()->save() ){ //soft fail global $EM_Notices; if( !empty($this->get_location()->location_id) ){ $EM_Notices->add_error( __('There were some errors saving your location.','dbem').' '.sprintf(__('It will not be displayed on the website listings, to correct this you must edit your location directly.'),$this->get_location()->output('#_LOCATIONEDITURL')), true); }else{ $this->get_location()->set_status(null); $EM_Notices->add_error( __('There were some errors saving your location.'), true); } } if( !empty($this->location->location_id) ){ //only case we don't use get_location(), since it will fail as location has an id, whereas location_id isn't set in this object $this->location_id = $this->location->location_id; } } //Update Post Meta foreach($this->fields as $key => $field_info){ if( !in_array($key, $this->post_fields) && $key != 'event_attributes' ){ update_post_meta($this->post_id, '_'.$key, $this->$key); }elseif($key == 'event_attributes'){ //attributes get saved as individual keys foreach($this->event_attributes as $event_attribute_key => $event_attribute){ if( !empty($event_attribute) ){ update_post_meta($this->post_id, $event_attribute_key, $event_attribute); }else{ delete_post_meta($this->post_id, $event_attribute_key); } } } } //update timestampes update_post_meta($this->post_id, '_start_ts', str_pad($this->start, 10, 0, STR_PAD_LEFT)); update_post_meta($this->post_id, '_end_ts', str_pad($this->end, 10, 0, STR_PAD_LEFT)); //sort out event status $result = count($this->errors) == 0; $this->get_status(); $this->event_status = ($result) ? $this->event_status:null; //set status at this point, it's either the current status, or if validation fails, null //Save to em_event table $event_array = $this->to_array(true); unset($event_array['event_id']); //decide whether or not event is private at this point $event_array['event_private'] = ( $this->post_status == 'private' ) ? 1:0; //save event_attributes just in case $event_array['event_attributes'] = serialize($this->event_attributes); //check if event truly exists, meaning the event_id is actually a valid event id if( !empty($this->event_id) ){ $blog_condition = ''; if( EM_MS_GLOBAL ){ if( is_main_site() ){ $blog_condition = " AND (blog_id='".get_current_blog_id()."' OR blog_id IS NULL)"; }else{ $blog_condition = " AND blog_id='".get_current_blog_id()."' "; } } $event_truly_exists = $wpdb->get_var('SELECT post_id FROM '.EM_EVENTS_TABLE." WHERE event_id={$this->event_id}".$blog_condition) == $this->post_id; }else{ $event_truly_exists = false; } //save all the meta if( empty($this->event_id) || !$event_truly_exists ){ $this->previous_status = 0; //for sure this was previously status 0 $this->event_date_created = current_time('mysql'); if ( !$wpdb->insert(EM_EVENTS_TABLE, $event_array) ){ $this->add_error( sprintf(__('Something went wrong saving your %s to the index table. Please inform a site administrator about this.','dbem'),__('event','dbem'))); }else{ //success, so link the event with the post via an event id meta value for easy retrieval $this->event_id = $wpdb->insert_id; update_post_meta($this->post_id, '_event_id', $this->event_id); $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Event','dbem')); $just_added_event = true; //make an easy hook do_action('em_event_save_new', $this); } }else{ $event_array['post_content'] = $this->post_content; //in case the content was removed, which is acceptable $this->previous_status = $this->get_previous_status(); $this->event_date_modified = $event_array['event_date_modified'] = current_time('mysql'); if ( $wpdb->update(EM_EVENTS_TABLE, $event_array, array('event_id'=>$this->event_id) ) === false ){ $this->add_error( sprintf(__('Something went wrong updating your %s to the index table. Please inform a site administrator about this.','dbem'),__('event','dbem'))); }else{ //Also set the status here if status != previous status if( $this->previous_status != $this->get_status()){ $status_value = $this->get_status(true); $wpdb->query('UPDATE '.EM_EVENTS_TABLE." SET event_status=$status_value WHERE event_id=".$this->event_id); } $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Event','dbem')); } } //Add/Delete Tickets if($this->event_rsvp == 0){ $this->get_bookings()->delete(); }else{ if( !$this->get_bookings()->get_tickets()->save() ){ $this->add_error( $this->get_bookings()->get_tickets()->get_errors() ); } } $result = count($this->errors) == 0; //If we're saving event categories in MS Global mode, we'll add them here, saving by term id (cat ids are gone now) if( EM_MS_GLOBAL && !is_main_site() ){ $this->get_categories()->save(); //it'll know what to do }elseif( EM_MS_GLOBAL ){ $this->get_categories()->save_index(); //just save to index, we assume cats are saved in $this->save(); } //build recurrences if needed if( $this->is_recurring() && $result && $this->is_published() ){ //only save events if recurring event validates and is published if( !$this->save_events() ){ //only save if post is 'published' $this->add_error(__ ( 'Something went wrong with the recurrence update...', 'dbem' ). __ ( 'There was a problem saving the recurring events.', 'dbem' )); } } if( !empty($just_added_event) ){ do_action('em_event_added', $this); } } $this->compat_keys(); return apply_filters('em_event_save_meta', count($this->errors) == 0, $this); } /** * Duplicates this event and returns the duplicated event. Will return false if there is a problem with duplication. * @return EM_Event */ function duplicate(){ global $wpdb, $EZSQL_ERROR; //First, duplicate. if( $this->can_manage('edit_events','edit_others_events') ){ $EM_Event = clone $this; $EM_Event->get_categories(); //before we remove event/post ids $EM_Event->get_bookings()->get_tickets(); //in case this wasn't loaded and before we reset ids $EM_Event->event_id = null; $EM_Event->post_id = null; $EM_Event->ID = null; $EM_Event->post_name = ''; $EM_Event->location_id = (empty($EM_Event->location_id) && !get_option('dbem_require_location')) ? 0:$EM_Event->location_id; $EM_Event->get_bookings()->event_id = null; $EM_Event->get_bookings()->get_tickets()->event_id = null; //if bookings reset ticket ids and duplicate tickets foreach($EM_Event->get_bookings()->get_tickets()->tickets as $EM_Ticket){ $EM_Ticket->ticket_id = null; $EM_Ticket->event_id = null; } do_action('em_event_duplicate_pre', $EM_Event); $EM_Event->duplicated = true; $EM_Event->force_status = 'draft'; if( $EM_Event->save() ){ $EM_Event->feedback_message = sprintf(__("%s successfully duplicated.", 'dbem'), __('Event','dbem')); //other non-EM post meta inc. featured image $event_meta = $this->get_event_meta($this->blog_id); $event_meta['_event_approvals_count'] = 0; //reset this counter for new event $event_meta_inserts = array(); //Get custom fields and post meta - adapted from $this->load_post_meta() foreach($event_meta as $event_meta_key => $event_meta_vals){ if($event_meta_key[0] == '_' && is_array($event_meta_vals)){ $field_name = substr($event_meta_key, 1); if($field_name != 'event_attributes' && !array_key_exists($field_name, $this->fields) && !in_array($field_name, array('edit_last', 'edit_lock', 'event_owner_name','event_owner_anonymous','event_owner_email')) ){ foreach($event_meta_vals as $event_meta_val){ $event_meta_inserts[] = "({$EM_Event->post_id}, '{$event_meta_key}', '{$event_meta_val}')"; } } } } //save in one SQL statement if( !empty($event_meta_inserts) ){ $wpdb->query('INSERT INTO '.$wpdb->postmeta." (post_id, meta_key, meta_value) VALUES ".implode(', ', $event_meta_inserts)); } //set event to draft status return apply_filters('em_event_duplicate', $EM_Event, $this); } } //TODO add error notifications for duplication failures. return apply_filters('em_event_duplicate', false, $this);; } /** * Delete whole event, including bookings, tickets, etc. * @return boolean */ function delete($force_delete = false){ //atm wp seems to force cp deletions anyway global $wpdb; if( $this->can_manage('delete_events', 'delete_others_events') ){ if( !is_admin() ){ include_once('em-event-post-admin.php'); if( !defined('EM_EVENT_DELETE_INCLUDE') ){ EM_Event_Post_Admin::init(); EM_Event_Recurring_Post_Admin::init(); define('EM_EVENT_DELETE_INCLUDE',true); } } do_action('em_event_delete_pre', $this); if( $force_delete ){ $result = wp_delete_post($this->post_id,$force_delete); }else{ $result = wp_trash_post($this->post_id); } }else{ $result = false; } //print_r($result); echo "|"; print_r($result_meta); die('DELETING'); return apply_filters('em_event_delete', $result !== false, $this); } function delete_meta(){ global $wpdb; $result = false; if( $this->can_manage('delete_events', 'delete_others_events') ){ do_action('em_event_delete_meta_event_pre', $this); $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=%d", $this->event_id) ); if( $result !== false ){ $this->delete_bookings(); $this->delete_tickets(); //Delete the recurrences then this recurrence event if( $this->is_recurring() ){ $result = $this->delete_events(); //was true at this point, so false if fails } //Delete categories from meta if in MS global mode if( EM_MS_GLOBAL ){ $wpdb->query('DELETE FROM '.EM_META_TABLE.' WHERE object_id='.$this->event_id." AND meta_key='event-category'"); } } } return apply_filters('em_event_delete_meta', $result !== false, $this); } /** * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary. */ function delete_bookings(){ global $wpdb; do_action('em_event_delete_bookings_pre', $this); $result = false; if( $this->can_manage('manage_bookings','manage_others_bookings') ){ $result_bt = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE booking_id IN (SELECT booking_id FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d)", $this->event_id) ); $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d", $this->event_id) ); } return apply_filters('em_event_delete_bookings', $result !== false && $result_bt !== false, $this); } /** * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary. */ function delete_tickets(){ global $wpdb; do_action('em_event_delete_tickets_pre', $this); $result = false; if( $this->can_manage('manage_bookings','manage_others_bookings') ){ $result_bt = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE ticket_id IN (SELECT ticket_id FROM ".EM_TICKETS_TABLE." WHERE event_id=%d)", $this->event_id) ); $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_TABLE." WHERE event_id=%d", $this->event_id) ); } return apply_filters('em_event_delete_tickets', $result, $this); } /** * Change the status of the event. This will save to the Database too. * @param int $status * @param boolean $set_post_status * @return string */ function set_status($status, $set_post_status = false){ global $wpdb; if($status === null){ $set_status='NULL'; if($set_post_status){ //if the post is trash, don't untrash it! $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) ); $this->post_status = 'draft'; } }else{ $set_status = $status ? 1:0; if($set_post_status){ if($this->post_status == 'pending'){ $this->post_name = sanitize_title($this->post_title); } $this->post_status = $set_status ? 'publish':'pending'; $wpdb->update( $wpdb->posts, array( 'post_status' => $this->post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) ); } } $this->previous_status = $this->get_previous_status(); $result = $wpdb->query("UPDATE ".EM_EVENTS_TABLE." SET event_status=$set_status, event_slug='{$this->post_name}' WHERE event_id=".$this->event_id); $this->get_status(); //reload status return apply_filters('em_event_set_status', $result !== false, $status, $this); } function is_published(){ return apply_filters('em_event_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this); } function get_status($db = false){ switch( $this->post_status ){ case 'private': $this->event_private = 1; $this->event_status = $status = 1; break; case 'publish': $this->event_private = 0; $this->event_status = $status = 1; break; case 'pending': $this->event_private = 0; $this->event_status = $status = 0; break; default: //draft or unknown $this->event_private = 0; $status = $db ? 'NULL':null; $this->event_status = null; break; } return $status; } function get_previous_status(){ global $wpdb; return $wpdb->get_var('SELECT event_status FROM '.EM_EVENTS_TABLE.' WHERE event_id='.$this->event_id); //get status from db, not post_status, as posts get saved quickly } /** * Returns an EM_Categories object of the EM_Event instance. * @return EM_Categories */ function get_categories() { if( empty($this->categories) ){ $this->categories = new EM_Categories($this); }elseif(empty($this->categories->event_id)){ $this->categories->event_id = $this->event_id; $this->categories->post_id = $this->post_id; } return apply_filters('em_event_get_categories', $this->categories, $this); } /** * Returns the location object this event belongs to. * @return EM_Location */ function get_location() { global $EM_Location; if( is_object($EM_Location) && $EM_Location->location_id == $this->location_id ){ $this->location = $EM_Location; }else{ if( !is_object($this->location) || $this->location->location_id != $this->location_id ){ $this->location = em_get_location($this->location_id); } } return $this->location; } /** * Returns the location object this event belongs to. * @return EM_Person */ function get_contact(){ if( !is_object($this->contact) ){ $this->contact = new EM_Person($this->event_owner); //if this is anonymous submission, change contact email and name if( $this->event_owner_anonymous ){ $this->contact->user_email = $this->event_owner_email; $name = explode(' ',$this->event_owner_name); $first_name = array_shift($name); $last_name = (count($name) > 0) ? implode(' ',$name):''; $this->contact->user_firstname = $this->contact->first_name = $first_name; $this->contact->user_lastname = $this->contact->last_name = $last_name; } } return $this->contact; } /** * Retrieve and save the bookings belonging to instance. If called again will return cached version, set $force_reload to true to create a new EM_Bookings object. * @param boolean $force_reload * @return EM_Bookings */ function get_bookings( $force_reload = false ){ if( get_option('dbem_rsvp_enabled') ){ if( (!$this->bookings || $force_reload) ){ $this->bookings = new EM_Bookings($this); } $this->bookings->event_id = $this->event_id; //always refresh event_id }else{ return new EM_Bookings(); } //TODO for some reason this returned instance doesn't modify the original, e.g. try $this->get_bookings()->add($EM_Booking) and see how $this->bookings->feedback_message doesn't change return apply_filters('em_event_get_bookings', $this->bookings, $this); } /** * Get the tickets related to this event. * @param boolean $force_reload * @return EM_Tickets */ function get_tickets( $force_reload = false ){ return $this->get_bookings($force_reload)->get_tickets(); } /** * Gets number of spaces in this event, dependent on ticket spaces or hard limit, whichever is smaller. * @param boolean $force_refresh * @return int */ function get_spaces($force_refresh=false){ return $this->get_bookings()->get_spaces($force_refresh); } /* * Extends the default EM_Object function by switching blogs as needed if in MS Global mode * @param string $size * @return string * @see EM_Object::get_image_url() */ function get_image_url($size = 'full'){ if( EM_MS_GLOBAL && get_current_blog_id() != $this->blog_id ){ switch_to_blog($this->blog_id); $switch_back = true; } $return = parent::get_image_url($size); if( !empty($switch_back) ){ restore_current_blog(); } return $return; } function get_edit_reschedule_url(){ if( $this->is_recurrence() ){ $EM_Event = em_get_event($this->recurrence_id); return $EM_Event->get_edit_url(); } } function get_edit_url(){ if( $this->can_manage('edit_events','edit_others_events') ){ if( EM_MS_GLOBAL && get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){ if( get_blog_option($this->blog_id, 'dbem_edit_events_page') ){ $link = em_add_get_params(get_permalink(get_blog_option($this->blog_id, 'dbem_edit_events_page')), array('action'=>'edit','event_id'=>$this->event_id), false); } if( empty($link)) $link = get_admin_url($this->blog_id, "post.php?post={$this->post_id}&action=edit"); }else{ if( get_option('dbem_edit_events_page') && !is_admin() ){ $link = em_add_get_params(get_permalink(get_option('dbem_edit_events_page')), array('action'=>'edit','event_id'=>$this->event_id), false); } if( empty($link)) $link = admin_url()."post.php?post={$this->post_id}&action=edit"; } return apply_filters('em_event_get_edit_url', $link, $this); } } function get_bookings_url(){ if( get_option('dbem_edit_bookings_page') && (!is_admin() || !empty($_REQUEST['is_public'])) ){ $my_bookings_page = get_permalink(get_option('dbem_edit_bookings_page')); $bookings_link = em_add_get_params($my_bookings_page, array('event_id'=>$this->event_id), false); }else{ if( is_multisite() && $this->blog_id != get_current_blog_id() ){ $bookings_link = get_admin_url($this->blog_id, 'edit.php?post_type='.EM_POST_TYPE_EVENT."&page=events-manager-bookings&event_id=".$this->event_id); }else{ $bookings_link = EM_ADMIN_URL. "&page=events-manager-bookings&event_id=".$this->event_id; } } return apply_filters('em_event_get_bookings_url', $bookings_link, $this); } function get_permalink(){ if( EM_MS_GLOBAL ){ if( get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && $this->blog_id != get_current_blog_id() ){ //linking directly to the blog $event_link = get_blog_permalink( $this->blog_id, $this->post_id); }elseif( !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){ if( get_option('dbem_events_page') ){ $event_link = trailingslashit(get_permalink(get_option('dbem_events_page')).get_site_option('dbem_ms_events_slug',EM_EVENT_SLUG).'/'.$this->event_slug.'-'.$this->event_id); }else{ $event_link = trailingslashit(home_url()).EM_POST_TYPE_EVENT_SLUG.'/'.get_site_option('dbem_ms_events_slug',EM_EVENT_SLUG).'/'.$this->event_slug.'-'.$this->event_id; } } } if( empty($event_link) ){ $event_link = get_post_permalink($this->post_id); } return apply_filters('em_event_get_permalink', $event_link, $this); } function get_ical_url(){ global $wp_rewrite; if( !empty($wp_rewrite) && $wp_rewrite->using_permalinks() ){ return trailingslashit($this->get_permalink()).'ical/'; }else{ return em_add_get_params($this->get_permalink(), array('ical'=>1)); } } function is_free( $now = false ){ $free = true; foreach($this->get_tickets() as $EM_Ticket){ /* @var $EM_Ticket EM_Ticket */ if( $EM_Ticket->get_price() > 0 ){ if( !$now || $EM_Ticket->is_available() ){ $free = false; } } } return apply_filters('em_event_is_free',$free,$this); } /** * Will output a single event format of this event. * Equivalent of calling EM_Event::output( get_option ( 'dbem_single_event_format' ) ) * @param string $target * @return string */ function output_single($target='html'){ $format = get_option ( 'dbem_single_event_format' ); return apply_filters('em_event_output_single', $this->output($format, $target), $this, $target); } /** * Will output a event in the format passed in $format by replacing placeholders within the format. * @param string $format * @param string $target * @return string */ function output($format, $target="html") { $event_string = $format; //Time place holder that doesn't show if empty. //TODO add filter here too preg_match_all('/#@?_\{[^}]+\}/', $format, $results); foreach($results[0] as $result) { if(substr($result, 0, 3 ) == "#@_"){ $date = 'end_date'; $offset = 4; }else{ $date = 'start_date'; $offset = 3; } if( $date == 'end_date' && $this->event_end_date == $this->event_start_date ){ $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) ); }else{ $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) ); } $event_string = str_replace($result,$replace,$event_string ); } //This is for the custom attributes preg_match_all('/#_ATT\{([^}]+)\}(\{([^}]+)\})?/', $format, $results); $attributes = em_get_attributes(); foreach($results[0] as $resultKey => $result) { //Strip string of placeholder and just leave the reference $attRef = substr( substr($result, 0, strpos($result, '}')), 6 ); $attString = ''; if( is_array($this->event_attributes) && array_key_exists($attRef, $this->event_attributes) ){ $attString = $this->event_attributes[$attRef]; }elseif( !empty($results[3][$resultKey]) ){ //Check to see if we have a second set of braces; $attString = $results[3][$resultKey]; }elseif( !empty($attributes['values'][$attRef][0]) ){ $attString = $attributes['values'][$attRef][0]; } $attString = apply_filters('em_event_output_placeholder', $attString, $this, $result, $target); $event_string = str_replace($result, $attString ,$event_string ); } //First let's do some conditional placeholder removals for ($i = 0 ; $i < EM_CONDITIONAL_RECURSIONS; $i++){ //you can add nested recursions by modifying this setting in your wp_options table preg_match_all('/\{([a-zA-Z0-9_]+)\}(.+?)\{\/\1\}/s', $event_string, $conditionals); if( count($conditionals[0]) > 0 ){ //Check if the language we want exists, if not we take the first language there foreach($conditionals[1] as $key => $condition){ $show_condition = false; if ($condition == 'has_bookings') { //check if there's a booking, if not, remove this section of code. $show_condition = ($this->event_rsvp && get_option('dbem_rsvp_enabled')); }elseif ($condition == 'no_bookings') { //check if there's a booking, if not, remove this section of code. $show_condition = (!$this->event_rsvp && get_option('dbem_rsvp_enabled')); }elseif ($condition == 'no_location'){ //does this event have a valid location? $show_condition = ( empty($this->location_id) || !$this->get_location()->location_status ); }elseif ($condition == 'has_location'){ //does this event have a valid location? $show_condition = ( !empty($this->location_id) && $this->get_location()->location_status ); }elseif ($condition == 'has_image'){ //does this event have an image? $show_condition = ( $this->get_image_url() != '' ); }elseif ($condition == 'no_image'){ //does this event have an image? $show_condition = ( $this->get_image_url() == '' ); }elseif ($condition == 'has_time'){ //are the booking times different and not an all-day event $show_condition = ( $this->event_start_time != $this->event_end_time && !$this->event_all_day ); }elseif ($condition == 'no_time'){ //are the booking times exactly the same and it's not an all-day event. $show_condition = ( $this->event_start_time == $this->event_end_time && !$this->event_all_day ); }elseif ($condition == 'all_day'){ //is it an all day event $show_condition = !empty($this->event_all_day); }elseif ($condition == 'logged_in'){ //user is logged in $show_condition = is_user_logged_in(); }elseif ($condition == 'not_logged_in'){ //not logged in $show_condition = !is_user_logged_in(); }elseif ($condition == 'has_spaces'){ //is it an all day event $show_condition = $this->event_rsvp && $this->get_bookings()->get_available_spaces() > 0; }elseif ($condition == 'fully_booked'){ //is it an all day event $show_condition = $this->event_rsvp && $this->get_bookings()->get_available_spaces() <= 0; }elseif ($condition == 'is_free' || $condition == 'is_free_now'){ //is it a free day event, if _now then free right now $show_condition = !$this->event_rsvp || $this->is_free( $condition == 'is_free_now' ); }elseif ($condition == 'not_free' || $condition == 'not_free_now'){ //is it a paid event, if _now then paid right now $show_condition = $this->event_rsvp && !$this->is_free( $condition == 'not_free_now' ); }elseif ($condition == 'is_long'){ //is it an all day event $show_condition = $this->event_start_date != $this->event_end_date; }elseif ($condition == 'not_long'){ //is it an all day event $show_condition = $this->event_start_date == $this->event_end_date; }elseif ($condition == 'is_past'){ //if event is past $show_condition = $this->start <= current_time('timestamp'); }elseif ($condition == 'is_future'){ //if event is upcoming $show_condition = $this->start > current_time('timestamp'); }elseif ($condition == 'is_recurrence'){ //if event is a recurrence $show_condition = $this->is_recurrence(); }elseif ($condition == 'not_recurrence'){ //if event is not a recurrence $show_condition = !$this->is_recurrence(); }elseif ($condition == 'is_private'){ //if event is a recurrence $show_condition = $this->event_private == 1; }elseif ($condition == 'not_private'){ //if event is not a recurrence $show_condition = $this->event_private == 0; }elseif ( preg_match('/^has_category_([a-zA-Z0-9_\-]+)$/', $condition, $category_match)){ //event is in this category $show_condition = has_term($category_match[1], EM_TAXONOMY_CATEGORY, $this->post_id); }elseif ( preg_match('/^no_category_([a-zA-Z0-9_\-]+)$/', $condition, $category_match)){ //event is NOT in this category $show_condition = !has_term($category_match[1], EM_TAXONOMY_CATEGORY, $this->post_id); }elseif ( preg_match('/^has_tag_([a-zA-Z0-9_\-]+)$/', $condition, $tag_match)){ //event has this tag $show_condition = has_term($tag_match[1], EM_TAXONOMY_TAG, $this->post_id); }elseif ( preg_match('/^no_tag_([a-zA-Z0-9_\-]+)$/', $condition, $tag_match)){ //event doesn't have this tag $show_condition = !has_term($tag_match[1], EM_TAXONOMY_TAG, $this->post_id); } //other potential ones - has_attribute_... no_attribute_... has_categories_... $show_condition = apply_filters('em_event_output_show_condition', $show_condition, $condition, $conditionals[0][$key], $this); if($show_condition){ //calculate lengths to delete placeholders $placeholder_length = strlen($condition)+2; $replacement = substr($conditionals[0][$key], $placeholder_length, strlen($conditionals[0][$key])-($placeholder_length *2 +1)); }else{ $replacement = ''; } $event_string = str_replace($conditionals[0][$key], apply_filters('em_event_output_condition', $replacement, $condition, $conditionals[0][$key], $this), $event_string); } } } //Now let's check out the placeholders. preg_match_all("/(#@?_?[A-Za-z0-9]+)({([a-zA-Z0-9_,]+)})?/", $format, $placeholders); $replaces = array(); foreach($placeholders[1] as $key => $result) { $match = true; $replace = ''; $full_result = $placeholders[0][$key]; switch( $result ){ //Event Details case '#_EVENTID': $replace = $this->event_id; break; case '#_EVENTPOSTID': $replace = $this->post_id; break; case '#_NAME': //depreciated case '#_EVENTNAME': $replace = $this->event_name; break; case '#_NOTES': //depreciated case '#_EXCERPT': //depreciated case '#_EVENTNOTES': case '#_EVENTEXCERPT': $replace = $this->post_content; if($result == "#_EXCERPT" || $result == "#_EVENTEXCERPT"){ if( !empty($this->post_excerpt) ){ $replace = $this->post_excerpt; }else{ $matches = explode('