protected function _parser($shortcode)
 {
     EE_Registry::instance()->load_helper('Formatter');
     $this->_event = $this->_data instanceof EE_Event ? $this->_data : null;
     //if no event, then let's see if there is a reg_obj.  If there IS, then we'll try and grab the event from the reg_obj instead.
     if (empty($this->_event)) {
         $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : NULL;
         $aee = $this->_extra_data instanceof EE_Messages_Addressee ? $this->_extra_data : $aee;
         $this->_event = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration ? $aee->reg_obj->event() : NULL;
     }
     //If there is no event objecdt by now then get out.
     if (!$this->_event instanceof EE_Event) {
         return '';
     }
     switch ($shortcode) {
         case '[EVENT_ID]':
             return $this->_event->ID();
             break;
         case '[EVENT_IDENTIFIER]':
             return isset($this->_data['line_ref']) ? $this->_data['line_ref'] : '';
             break;
         case '[EVENT]':
         case '[EVENT_NAME]':
             return $this->_event->get('EVT_name');
             break;
         case '[EVENT_PHONE]':
             return $this->_event->get('EVT_phone');
             break;
         case '[EVENT_DESCRIPTION]':
             return $this->_event->get('EVT_desc');
             break;
         case '[EVENT_EXCERPT]':
             return $this->_event->get('EVT_short_desc');
             break;
         case '[EVENT_LINK]':
             return $this->_get_event_link($this->_event);
             break;
         case '[EVENT_URL]':
             return $this->_get_event_link($this->_event, FALSE);
             break;
         case '[VIRTUAL_URL]':
             $venue = $this->_event->get_first_related('Venue');
             if (empty($venue)) {
                 return '';
             }
             return $venue->get('VNU_virtual_url');
         case '[VIRTUAL_PHONE]':
             $venue = $this->_event->get_first_related('Venue');
             if (empty($venue)) {
                 return '';
             }
             return $venue->get('VNU_virtual_phone');
             break;
         case '[EVENT_IMAGE]':
             $image = $this->_event->feature_image_url(array(600, 300));
             // @todo: eventually we should make this an attribute shortcode so that em can send along what size they want returned.
             return !empty($image) ? '<img src="' . $image . '" alt="' . sprintf(esc_attr__('%s Feature Image', 'event_espresso'), $this->_event->get('EVT_name')) . '" />' : '';
             break;
         case '[EVENT_FACEBOOK_URL]':
             $facebook_url = $this->_event->get_post_meta('event_facebook', true);
             return empty($facebook_url) ? EE_Registry::instance()->CFG->organization->get_pretty('facebook') : $facebook_url;
             break;
         case '[EVENT_TWITTER_URL]':
             $twitter_url = $this->_event->get_post_meta('event_twitter', true);
             return empty($twitter_url) ? EE_Registry::instance()->CFG->organization->get_pretty('twitter') : $twitter_url;
             break;
         case '[EVENT_AUTHOR_EMAIL]':
             $author_id = $this->_event->get('EVT_wp_user');
             $user_data = get_userdata((int) $author_id);
             return $user_data->user_email;
             break;
         case '[EVENT_TOTAL_SPOTS_TAKEN]':
             return EEM_Registration::instance()->count(array(array('EVT_ID' => $this->_event->ID(), 'STS_ID' => EEM_Registration::status_id_approved)), 'REG_ID', true);
             break;
         case '[REGISTRATION_LIST_TABLE_FOR_EVENT_URL]':
             EE_Registry::instance()->load_helper('URL');
             return EEH_URL::add_query_args_and_nonce(array('event_id' => $this->_event->ID(), 'page' => 'espresso_registrations', 'action' => 'default'), admin_url('admin.php'), true);
             break;
     }
     if (strpos($shortcode, '[EVENT_META_*') !== false) {
         $shortcode = str_replace('[EVENT_META_*', '', $shortcode);
         $shortcode = trim(str_replace(']', '', $shortcode));
         //pull the meta value from the event post
         $event_meta = $this->_event->get_post_meta($shortcode, true);
         return !empty($event_meta) ? $this->_event->get_post_meta($shortcode, true) : '';
     }
     if (strpos($shortcode, '[EVENT_TOTAL_AVAILABLE_SPACES_*') !== false) {
         $attrs = $this->_get_shortcode_attrs($shortcode);
         $method = empty($attrs['method']) ? 'current' : $attrs['method'];
         $method = $method === 'current';
         $available = $this->_event->total_available_spaces($method);
         return $available === INF ? '&infin;' : $available;
     }
     return '';
 }
 /**
  * @param EE_Event $item
  *
  * @return string
  */
 public function column_venue(EE_Event $item)
 {
     $venue = $item->get_first_related('Venue');
     return !empty($venue) ? $venue->name() : '';
 }
 /**
  * Handles saving everything related to Tickets (datetimes, tickets, prices)
  * @param  EE_Event $evtobj The Event object we're attaching data to
  * @param  array    $data   The request data from the form
  * @return bool             success or fail
  */
 protected function _default_tickets_update($evtobj, $data)
 {
     $success = TRUE;
     $incoming_date_formats = array('Y-m-d', 'h:i a');
     foreach ($data['edit_event_datetimes'] as $row => $dtt) {
         $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && !empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end'] : $dtt['DTT_EVT_start'];
         $datetime_values = array('DTT_ID' => !empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : NULL, 'DTT_EVT_start' => $dtt['DTT_EVT_start'], 'DTT_EVT_end' => $dtt['DTT_EVT_end'], 'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? INF : $dtt['DTT_reg_limit'], 'DTT_order' => $row);
         //if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
         if (!empty($dtt['DTT_ID'])) {
             $DTM = EE_Registry::instance()->load_model('Datetime', array($evtobj->get_timezone()))->get_one_by_ID($dtt['DTT_ID']);
             $DTM->set_date_format($incoming_date_formats[0]);
             $DTM->set_time_format($incoming_date_formats[1]);
             foreach ($datetime_values as $field => $value) {
                 $DTM->set($field, $value);
             }
             //make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
             $saved_dtts[$DTM->ID()] = $DTM;
         } else {
             $DTM = EE_Registry::instance()->load_class('Datetime', array($datetime_values), FALSE, FALSE);
             $DTM->set_date_format($incoming_date_formats[0]);
             $DTM->set_time_format($incoming_date_formats[1]);
             $DTM->set_timezone($evtobj->get_timezone());
             foreach ($datetime_values as $field => $value) {
                 $DTM->set($field, $value);
             }
         }
         $DTM->save();
         $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
         //load DTT helper
         EE_Registry::instance()->load_helper('DTT_Helper');
         //before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
         if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
             $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
             $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
             $DTT->save();
         }
         //now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
         $saved_dtt = $DTT;
         $success = !$success ? $success : $DTT;
         //if ANY of these updates fail then we want the appropriate global error message. //todod this is actually sucky we need a better error message but this is what it is for now.
     }
     //no dtts get deleted so we don't do any of that logic here.
     //update tickets next
     $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
     foreach ($data['edit_tickets'] as $row => $tkt) {
         $incoming_date_formats = array('Y-m-d', 'h:i a');
         $update_prices = false;
         $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount']) ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
         if (empty($tkt['TKT_start_date'])) {
             //let's use now in the set timezone.
             $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
             $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
         }
         if (empty($tkt['TKT_end_date'])) {
             //use the start date of the first datetime
             $dtt = $evtobj->get_first_related('Datetime');
             $tkt['TKT_end_date'] = $dtt->start_date_and_time($incoming_date_formats[0], $incoming_date_formats[1]);
         }
         $TKT_values = array('TKT_ID' => !empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : NULL, 'TTM_ID' => !empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0, 'TKT_name' => !empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '', 'TKT_description' => !empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '', 'TKT_start_date' => $tkt['TKT_start_date'], 'TKT_end_date' => $tkt['TKT_end_date'], 'TKT_qty' => empty($tkt['TKT_qty']) ? INF : $tkt['TKT_qty'], 'TKT_uses' => empty($tkt['TKT_uses']) ? INF : $tkt['TKT_uses'], 'TKT_min' => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'], 'TKT_max' => empty($tkt['TKT_max']) ? INF : $tkt['TKT_max'], 'TKT_row' => $row, 'TKT_order' => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row, 'TKT_price' => $ticket_price);
         //if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
         if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
             $TKT_values['TKT_ID'] = 0;
             $TKT_values['TKT_is_default'] = 0;
             $TKT_values['TKT_price'] = $ticket_price;
             $update_prices = TRUE;
         }
         //if we have a TKT_ID then we need to get that existing TKT_obj and update it
         //we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
         //keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
         if (!empty($tkt['TKT_ID'])) {
             $TKT = EE_Registry::instance()->load_model('Ticket', array($evtobj->get_timezone()))->get_one_by_ID($tkt['TKT_ID']);
             $ticket_sold = $TKT->count_related('Registration', array(array('STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete))))) > 0 ? true : false;
             //let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
             $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price') && !$TKT->get('TKT_deleted') ? TRUE : FALSE;
             $TKT->set_date_format($incoming_date_formats[0]);
             $TKT->set_time_format($incoming_date_formats[1]);
             //set new values
             foreach ($TKT_values as $field => $value) {
                 $TKT->set($field, $value);
             }
             //if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
             if ($create_new_TKT) {
                 //archive the old ticket first
                 $TKT->set('TKT_deleted', 1);
                 $TKT->save();
                 //make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
                 $saved_tickets[$TKT->ID()] = $TKT;
                 //create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
                 $TKT = clone $TKT;
                 $TKT->set('TKT_ID', 0);
                 $TKT->set('TKT_deleted', 0);
                 $TKT->set('TKT_price', $ticket_price);
                 $TKT->set('TKT_sold', 0);
                 //now we need to make sure that $new prices are created as well and attached to new ticket.
                 $update_prices = TRUE;
             }
             //make sure price is set if it hasn't been already
             $TKT->set('TKT_price', $ticket_price);
         } else {
             //no TKT_id so a new TKT
             $TKT_values['TKT_price'] = $ticket_price;
             $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), FALSE, FALSE);
             //need to reset values to properly account for the date formats
             $TKT->set_date_format($incoming_date_formats[0]);
             $TKT->set_time_format($incoming_date_formats[1]);
             $TKT->set_timezone($evtobj->get_timezone());
             //set new values
             foreach ($TKT_values as $field => $value) {
                 $TKT->set($field, $value);
             }
             $update_prices = TRUE;
         }
         //update ticket.
         $TKT->save();
         //before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
         if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
             $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
             EE_Registry::instance()->load_helper('DTT_Helper');
             $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
             $TKT->save();
         }
         //initially let's add the ticket to the dtt
         $saved_dtt->_add_relation_to($TKT, 'Ticket');
         $saved_tickets[$TKT->ID()] = $TKT;
         //add prices to ticket
         $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
     }
     //however now we need to handle permanantly deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanantely because there is no need to save in db.
     $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
     $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
     foreach ($tickets_removed as $id) {
         $id = absint($id);
         //get the ticket for this id
         $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
         //need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
         $dtts = $tkt_to_remove->get_many_related('Datetime');
         foreach ($dtts as $dtt) {
             $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
         }
         //need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
         $tkt_to_remove->delete_related_permanently('Price');
         //finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
         $tkt_to_remove->delete_permanently();
     }
     /**/
     return array($saved_dtt, $saved_tickets);
 }
 /**
  * This retrieves the specified venue information
  * @param  string $what What to retrieve from database
  * @return string       What was retrieved!
  */
 private function _venue($db_ref)
 {
     //we need the EE_Event object to get the venue.
     $this->_event = $this->_data instanceof EE_Event ? $this->_data : null;
     //if no event, then let's see if there is a reg_obj.  If there IS, then we'll try and grab the event from the reg_obj instead.
     if (empty($this->_event)) {
         $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : NULL;
         $aee = $this->_extra_data instanceof EE_Messages_Addressee ? $this->_extra_data : $aee;
         $this->_event = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration ? $aee->reg_obj->event() : NULL;
         //if still empty do we have a ticket data item?
         $this->_event = empty($this->_event) && $this->_data instanceof EE_Ticket && $this->_extra_data['data'] instanceof EE_Messages_Addressee ? $this->_extra_data['data']->tickets[$this->_data->ID()]['EE_Event'] : $this->_event;
         //if STILL empty event, let's try to get the first event in the list of events via EE_Messages_Addressee and use that.
         $event = $aee instanceof EE_Messages_Addressee ? reset($aee->events) : array();
         $this->_event = empty($this->_event) && !empty($events) ? $event : $this->_event;
     }
     //If there is no event objecdt by now then get out.
     if (!$this->_event instanceof EE_Event) {
         return '';
     }
     $venue = $this->_event->get_first_related('Venue');
     if (empty($venue)) {
         return '';
     }
     //no venue so get out.
     switch ($db_ref) {
         case 'title':
             return $venue->get('VNU_name');
             break;
         case 'description':
             return $venue->get('VNU_desc');
             break;
         case 'url':
             $url = $venue->get('VNU_url');
             return empty($url) ? $venue->get_permalink() : $url;
             break;
         case 'image':
             return '<img src="' . $venue->feature_image_url(array(200, 200)) . '" alt="' . sprintf(esc_attr__('%s Feature Image', 'event_espresso'), $venue->get('VNU_name')) . '" />';
             break;
         case 'phone':
             return $venue->get('VNU_phone');
             break;
         case 'address':
             return $venue->get('VNU_address');
             break;
         case 'address2':
             return $venue->get('VNU_address2');
             break;
         case 'city':
             return $venue->get('VNU_city');
             break;
         case 'state':
             $state = $venue->state_obj();
             return is_object($state) ? $state->get('STA_name') : '';
             break;
         case 'country':
             $country = $venue->country_obj();
             return is_object($country) ? $country->get('CNT_name') : '';
             break;
         case 'zip':
             return $venue->get('VNU_zip');
             break;
         case 'formatted_address':
             return EEH_Address::format($venue);
             break;
         case 'gmap_link':
         case 'gmap_link_img':
             $state = $venue->state_obj();
             $country = $venue->country_obj();
             $atts = array('id' => $venue->ID(), 'address' => $venue->get('VNU_address'), 'city' => $venue->get('VNU_city'), 'state' => is_object($state) ? $state->get('STA_name') : '', 'zip' => $venue->get('VNU_zip'), 'country' => is_object($country) ? $country->get('CNT_name') : '', 'type' => $db_ref == 'gmap_link' ? 'url' : 'map', 'map_w' => 200, 'map_h' => 200);
             return EEH_Maps::google_map_link($atts);
             break;
     }
 }
 protected function _parser($shortcode)
 {
     EE_Registry::instance()->load_helper('Formatter');
     $this->_event = $this->_data instanceof EE_Event ? $this->_data : null;
     //if no event, then let's see if there is a reg_obj.  If there IS, then we'll try and grab the event from the reg_obj instead.
     if (empty($this->_event)) {
         $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : NULL;
         $aee = $this->_extra_data instanceof EE_Messages_Addressee ? $this->_extra_data : $aee;
         $this->_event = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration ? $aee->reg_obj->event() : NULL;
     }
     //If there is no event objecdt by now then get out.
     if (!$this->_event instanceof EE_Event) {
         return '';
     }
     switch ($shortcode) {
         case '[EVENT_ID]':
             return $this->_event->ID();
             break;
         case '[EVENT_IDENTIFIER]':
             return isset($this->_data['line_ref']) ? $this->_data['line_ref'] : '';
             break;
         case '[EVENT]':
         case '[EVENT_NAME]':
             return $this->_event->get('EVT_name');
             break;
         case '[EVENT_PHONE]':
             return $this->_event->get('EVT_phone');
             break;
         case '[EVENT_DESCRIPTION]':
             return $this->_event->get('EVT_desc');
             break;
         case '[EVENT_EXCERPT]':
             return $this->_event->get('EVT_short_desc');
             break;
         case '[EVENT_LINK]':
             return $this->_get_event_link($this->_event);
             break;
         case '[EVENT_URL]':
             return $this->_get_event_link($this->_event, FALSE);
             break;
         case '[VIRTUAL_URL]':
             $venue = $this->_event->get_first_related('Venue');
             if (empty($venue)) {
                 return '';
             }
             return $venue->get('VNU_virtual_url');
         case '[VIRTUAL_PHONE]':
             $venue = $this->_event->get_first_related('Venue');
             if (empty($venue)) {
                 return '';
             }
             return $venue->get('VNU_virtual_phone');
             break;
         case '[EVENT_IMAGE]':
             $image = $this->_event->feature_image_url(array(600, 300));
             // @todo: eventually we should make this an attribute shortcode so that em can send along what size they want returned.
             return !empty($image) ? '<img src="' . $image . '" alt="' . sprintf(esc_attr__('%s Feature Image', 'event_espresso'), $this->_event->get('EVT_name')) . '" />' : '';
             break;
         case '[EVENT_FACEBOOK_URL]':
             $facebook_url = $this->_event->get_post_meta('event_facebook', true);
             return empty($facebook_url) ? EE_Registry::instance()->CFG->organization->get_pretty('facebook') : $facebook_url;
             break;
         case '[EVENT_TWITTER_URL]':
             $twitter_url = $this->_event->get_post_meta('event_twitter', true);
             return empty($twitter_url) ? EE_Registry::instance()->CFG->organization->get_pretty('twitter') : $twitter_url;
             break;
         case '[EVENT_AUTHOR_EMAIL]':
             $author_id = $this->_event->get('EVT_wp_user');
             $user_data = get_userdata((int) $author_id);
             return $user_data->user_email;
             break;
     }
     return '';
 }