/**
  * @group 8861
  */
 public function test_sum_tickets_currently_available_at_datetime()
 {
     //echo "\n\n test_sum_tickets_currently_available_at_datetime: ";
     $scenarios = $this->scenarios->get_scenarios_by_type('datetime');
     foreach ($scenarios as $scenario) {
         //echo "\n\nTesting" . $scenario->name;
         if ($scenario->get_expected('sum_tickets_currently_available_at_datetime') !== false) {
             //echo "\n scenario->get_scenario_object()->ID(): " . $scenario->get_scenario_object()->ID();
             $actual = EEM_Ticket::instance()->sum_tickets_currently_available_at_datetime($scenario->get_scenario_object()->ID());
             $this->assertEquals($scenario->get_expected('sum_tickets_currently_available_at_datetime'), $actual);
         }
     }
 }
예제 #2
0
 /**
  *		This function is a singleton method used to instantiate the Espresso_model object
  *
  *		@access public
  *		@param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
  *		@return EEM_Ticket instance
  */
 public static function instance($timezone = NULL)
 {
     // check if instance of Espresso_model already exists
     if (self::$_instance === NULL) {
         // instantiate Espresso_model
         self::$_instance = new self($timezone);
     }
     //set timezone if we have in incoming string
     if (!empty($timezone)) {
         self::$_instance->set_timezone($timezone);
     }
     // Espresso_model object
     return self::$_instance;
 }
 /**
  * This generates the dummy relation objects for use in a new registration.
  *
  * @since 4.3.0
  *
  * @param array $args
  */
 private function _set_new_relations($args)
 {
     //transaction
     $this->_transaction = empty($args['TXN_ID']) ? $this->factory->transaction->create() : EEM_Transaction::instance()->get_one_by_ID($args['TXN_ID']);
     $this->_transaction = empty($this->_transaction) ? $this->factory->transaction->create() : $this->_transaction;
     //ticket
     $this->_ticket = empty($args['TKT_ID']) ? $this->factory->ticket_chained->create() : EEM_Ticket::instance()->get_one_by_ID($args['TKT_ID']);
     $this->_ticket = empty($this->_ticket) ? $this->factory->ticket_chained->create() : $this->_ticket;
     //attendee
     $this->_attendee = empty($args['ATT_ID']) ? $this->factory->attendee->create() : EEM_Attendee::instance()->get_one_by_ID($args['ATT_ID']);
     $this->_attendee = empty($this->_attendee) ? $this->factory->attendee->create() : $this->_attendee;
     //status
     $this->_status = empty($arg['STS_ID']) ? $this->factory->status->create(array('STS_ID' => EEM_Registration::status_id_pending_payment, 'STS_type' => 'registration', 'STS_code' => 'PENDING_PAYMENT')) : EEM_Status::instance()->get_one_by_ID($args['STS_ID']);
     $this->_status = empty($this->_status) ? $this->factory->status->create(array('STS_ID' => EEM_Registration::status_id_pending_payment, 'STS_type' => 'registration', 'STS_code' => 'PENDING_PAYMENT')) : $this->_status;
 }
 /**
  * Gets all the ticket types currently available for purchase
  * @param array $query_params like EEM_Base::get_all's
  * @return EE_Ticket[]
  */
 public function ticket_types_available_for_purchase($query_params = array())
 {
     // first check if datetime is valid
     if (!($this->is_upcoming() || $this->is_active()) || $this->sold_out()) {
         return array();
     }
     if (empty($query_params)) {
         $query_params = array(array('TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')), 'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')), 'TKT_deleted' => FALSE));
     }
     return $this->tickets($query_params);
 }
 /**
  *	Given an array of data (usually from a CSV import) attempts to save that data to the db.
  *	If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
  *	next level being numeric indexes adn each value representing a model object, and the last layer down
  *	being keys of model fields and their proposed values.
  *	If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
  *	If the CSV data says (in the metadata row) that it's from the SAME database,
  *	we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
  *	IDs DON'T exist in the database, they're treated as temporary IDs,
  *	which can used elsewhere to refer to the same object. Once an item
  *	with a temporary ID gets inserted, we record its mapping from temporary
  *	ID to real ID, and use the real ID in place of the temporary ID
  *	when that temporary ID was used as a foreign key.
  *	If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
  *	we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
  *	ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
  *	and insert a new event, and map it's temporary ID of 1 over to its new real ID.
  *	An important exception are non-auto-increment primary keys. If one entry in the
  *	CSV file has the same ID as one in the DB, we assume they are meant to be
  *	the same item, and instead update the item in the DB with that same ID.
  *	Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
  *	time you import a CSV from a different site, we remember their mappings, and
  * will try to update the item in the DB instead of inserting another item (eg
  * if we previously imported an event with temporary ID 1, and then it got a
  * real ID of 123, we remember that. So the next time we import an event with
  * temporary ID, from the same site, we know that it's real ID is 123, and will
  * update that event, instead of adding a new event).
  *		  @access public
  *			@param array $csv_data_array - the array containing the csv data produced from EE_CSV::import_csv_to_model_data_array()
  *			@param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table fields they will be saved to
  *			@return TRUE on success, FALSE on fail
  */
 public function save_csv_data_array_to_db($csv_data_array, $model_name = FALSE)
 {
     $success = FALSE;
     $error = FALSE;
     //whther to treat this import as if it's data froma different database or not
     //ie, if it IS from a different database, ignore foreign keys whihf
     $export_from_site_a_to_b = true;
     // first level of array is not table information but a table name was passed to the function
     // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
     if ($model_name) {
         $csv_data_array = array($csv_data_array);
     }
     // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
     $old_site_url = 'none-specified';
     //hanlde metadata
     if (isset($csv_data_array[EE_CSV::metadata_header])) {
         $csv_metadata = array_shift($csv_data_array[EE_CSV::metadata_header]);
         //ok so its metadata, dont try to save it to ehte db obviously...
         if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
             EE_Error::add_attention(sprintf(__("CSV Data appears to be from the same database, so attempting to update data", "event_espresso")));
             $export_from_site_a_to_b = false;
         } else {
             $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
             EE_Error::add_attention(sprintf(__("CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database", "event_espresso"), $old_site_url, site_url()));
         }
         unset($csv_data_array[EE_CSV::metadata_header]);
     }
     /**
      * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
      * the value will be the newly-inserted ID.
      * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
      */
     $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
     if ($old_db_to_new_db_mapping) {
         EE_Error::add_attention(sprintf(__("We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s", "event_espresso"), $old_site_url, site_url()));
     }
     $old_db_to_new_db_mapping = $this->save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping);
     //save the mapping from old db to new db in case they try re-importing the same data from the same website again
     update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping);
     if ($this->_total_updates > 0) {
         EE_Error::add_success(sprintf(__("%s existing records in the database were updated.", "event_espresso"), $this->_total_updates));
         $success = true;
     }
     if ($this->_total_inserts > 0) {
         EE_Error::add_success(sprintf(__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts));
         $success = true;
     }
     if ($this->_total_update_errors > 0) {
         EE_Error::add_error(sprintf(__("'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", "event_espresso"), $this->_total_update_errors), __FILE__, __FUNCTION__, __LINE__);
         $error = true;
     }
     if ($this->_total_insert_errors > 0) {
         EE_Error::add_error(sprintf(__("One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", "event_espresso"), $this->_total_insert_errors), __FILE__, __FUNCTION__, __LINE__);
         $error = true;
     }
     //lastly, we need to update the datetime and ticket sold amounts
     //as those may ahve been affected by this
     EEM_Datetime::instance()->update_sold(EEM_Datetime::instance()->get_all());
     EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
     // if there was at least one success and absolutely no errors
     if ($success && !$error) {
         return TRUE;
     } else {
         return FALSE;
     }
 }
 /**
  * 	process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
  *
  *
  *
  * 	[ESPRESSO_EVENT_ATTENDEES] - defaults to attendees for earliest active event, or earliest upcoming event.
  * 	[ESPRESSO_EVENT_ATTENDEES event_id=123] - attendees for specific event.
  * 	[ESPRESSO_EVENT_ATTENDEES datetime_id=245] - attendees for a specific datetime.
  * 	[ESPRESSO_EVENT_ATTENDEES ticket_id=123] - attendees for a specific ticket.
  * 	[ESPRESSO_EVENT_ATTENDEES status=all] - specific registration status (use status id) or all for all attendees
  *                                          regardless of status.  Note default is to only return approved attendees
  * 	[ESPRESSO_EVENT_ATTENDEES show_gravatar=true] - default is to not return gravatar.  Otherwise if this is set
  *                                                  then return gravatar for email address given.
  *
  *  Note: because of the relationship between event_id, ticket_id, and datetime_id. If more than one of those params
  *  is included then preference is given to the following:
  *  - event_id is used whenever its present and any others are ignored.
  *  - if no event_id then datetime is used whenever its present and any others are ignored.
  *  - otherwise ticket_id is used if present.
  *
  *  @access 	public
  *  @param 	    array 	$attributes
  *  @return 	string
  */
 public function process_shortcode($attributes = array())
 {
     //load helpers
     EE_Registry::instance()->load_helper('Event_View');
     EE_Registry::instance()->load_helper('Template');
     // merge in any attributes passed via fallback shortcode processor
     $attributes = array_merge((array) $attributes, (array) $this->_attributes);
     //set default attributes
     $default_shortcode_attributes = array('event_id' => null, 'datetime_id' => null, 'ticket_id' => null, 'status' => EEM_Registration::status_id_approved, 'show_gravatar' => false);
     // allow the defaults to be filtered
     $default_shortcode_attributes = apply_filters('EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts', $default_shortcode_attributes);
     // grab attributes and merge with defaults, then extract
     $attributes = array_merge($default_shortcode_attributes, $attributes);
     $template_args = array('contacts' => array(), 'event' => null, 'datetime' => null, 'ticket' => null, 'show_gravatar' => $attributes['show_gravatar']);
     //start setting up the query for the contacts
     $query = array();
     $error = false;
     //what event?
     if (empty($attributes['event_id']) && empty($attributes['datetime_id']) && empty($attributes['ticket_id'])) {
         //seems like is_espresso_event_single() isn't working as expected. So using alternate method.
         if (is_single() && is_espresso_event()) {
             $event = EEH_Event_View::get_event();
             if ($event instanceof EE_Event) {
                 $template_args['event'] = $event;
                 $query[0]['Registration.EVT_ID'] = $event->ID();
             }
         } else {
             //try getting the earliest active event if none then get the
             $events = EEM_Event::instance()->get_active_events(array('limit' => 1, 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC')));
             $events = empty($events) ? EEM_Event::instance()->get_upcoming_events(array('limit' => 1, 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'))) : $events;
             $event = reset($events);
             if ($event instanceof EE_Event) {
                 $query[0]['Registration.EVT_ID'] = $event->ID();
                 $template_args['event'] = $event;
             }
         }
     } elseif (!empty($attributes['event_id'])) {
         $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
         if ($event instanceof EE_Event) {
             $query[0]['Registration.EVT_ID'] = $attributes['event_id'];
             $template_args['event'] = $event;
         } else {
             $error = true;
         }
     }
     //datetime?
     if (!empty($attributes['datetime_id']) && empty($attributes['event_id'])) {
         $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
         if ($datetime instanceof EE_Datetime) {
             $query[0]['Registration.Ticket.Datetime.DTT_ID'] = $attributes['datetime_id'];
             $query['default_where_conditions'] = 'this_model_only';
             $template_args['datetime'] = $datetime;
             $template_args['event'] = $datetime->event();
         } else {
             $error = true;
         }
     }
     //ticket?just
     if (!empty($attributes['ticket_id']) && empty($attributes['event_id']) && empty($attributes['datetime_id'])) {
         $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
         if ($ticket instanceof EE_Ticket) {
             $query[0]['Registration.TKT_ID'] = $attributes['ticket_id'];
             $template_args['ticket'] = $ticket;
             $template_args['event'] = $ticket->first_datetime() instanceof EE_Datetime ? $ticket->first_datetime()->event() : null;
         } else {
             $error = true;
         }
     }
     //status
     $reg_status_array = EEM_Registration::reg_status_array();
     if ($attributes['status'] != 'all' && isset($reg_status_array[$attributes['status']])) {
         $query[0]['Registration.STS_ID'] = $attributes['status'];
     }
     $query['group_by'] = array('ATT_ID');
     $query['order_by'] = apply_filters('FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by', array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC'));
     //if we have NO query where conditions, then there was an invalid parameter or the shortcode was used incorrectly
     //so when WP_DEBUG is set and true, we'll show a message, otherwise we'll just return an empty string.
     if (!isset($query[0]) || !is_array($query[0]) || $error) {
         if (WP_DEBUG) {
             return '<div class="important-notice ee-attention">' . __('The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly.  Please double check the arguments you used for any typos.  In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.', 'event_espresso') . '</div>';
         } else {
             return '';
         }
     }
     //get contacts!
     $template_args['contacts'] = EEM_Attendee::instance()->get_all($query);
     //all set let's load up the template and return.
     return EEH_Template::locate_template('loop-espresso_event_attendees.php', $template_args, true, true);
 }
 /**
  * trash or restore registrations
  * @param  boolean $trash whether to archive or restore
  * @access protected
  * @return void
  */
 protected function _trash_or_restore_registrations($trash = TRUE)
 {
     $REGM = EEM_Registration::instance();
     $success = 1;
     $error = 0;
     $tickets = array();
     $dtts = array();
     //if empty _REG_ID then get out because there's nothing to do
     if (empty($this->_req_data['_REG_ID'])) {
         $msg = $trash ? __('In order to trash registrations you must select which ones you wish to trash by clicking the checkboxes.', 'event_espresso') : __('In order to restore registrations you must select which ones you wish to restore by clicking the checkboxes.', 'event_espresso');
         EE_Error::add_error($msg, __FILE__, __LINE__, __FUNCTION__);
         $this->_redirect_after_action(FALSE, '', '', array(), TRUE);
     }
     //Checkboxes
     if (!empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
         // if array has more than one element than success message should be plural
         $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
         // cycle thru checkboxes
         while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
             $REG = $REGM->get_one_by_ID($REG_ID);
             $payment_count = $REG->get_first_related('Transaction')->count_related('Payment');
             if ($payment_count > 0) {
                 $name = $REG->attendee() instanceof EE_Attendee ? $REG->attendee()->full_name() : __('Unknown Attendee', 'event_espresso');
                 $error = 1;
                 $success = 0;
                 EE_Error::add_error(sprintf(__('The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.', 'event_espresso'), $name), __FILE__, __FUNCTION__, __LINE__);
                 continue;
                 //can't trash this registration because it has payments.
             }
             $ticket = $REG->get_first_related('Ticket');
             $tickets[$ticket->ID()] = $ticket;
             $dtt = $ticket->get_many_related('Datetime');
             $dtts = array_merge($dtts, $dtt);
             $updated = $trash ? $REG->delete() : $REG->restore();
             if (!$updated) {
                 $success = 0;
             } else {
                 $success = 2;
             }
             /**/
         }
     } else {
         // grab single id and delete
         $REG_ID = absint($this->_req_data['_REG_ID']);
         $REG = $REGM->get_one_by_ID($REG_ID);
         $ticket = $REG->get_first_related('Ticket');
         $tickets[$ticket->ID()] = $ticket;
         $dtts = $ticket->get_many_related('Datetime');
         $updated = $trash ? $REG->delete() : $REG->restore();
         if (!$updated) {
             $success = 0;
         }
     }
     //now let's update counts
     EEM_Ticket::instance()->update_tickets_sold($tickets);
     EEM_Datetime::instance()->update_sold($dtts);
     $what = $success > 1 ? __('Registrations', 'event_espresso') : __('Registration', 'event_espresso');
     $action_desc = $trash ? __('moved to the trash', 'event_espresso') : __('restored', 'event_espresso');
     $overwrite_msgs = $error ? TRUE : FALSE;
     $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'default'), $overwrite_msgs);
 }
예제 #8
0
 /**
  *	Given an array of data (usually from a CSV import) attempts to save that data to the db.
  *	If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
  *	next level being numeric indexes adn each value representing a model object, and the last layer down
  *	being keys of model fields and their proposed values.
  *	If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
  *	If the CSV data says (in the metadata row) that it's from the SAME database,
  *	we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
  *	IDs DON'T exist in the database, they're treated as temporary IDs,
  *	which can used elsewhere to refer to the same object. Once an item
  *	with a temporary ID gets inserted, we record its mapping from temporary
  *	ID to real ID, and use the real ID in place of the temporary ID
  *	when that temporary ID was used as a foreign key.
  *	If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
  *	we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
  *	ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
  *	and insert a new event, and map it's temporary ID of 1 over to its new real ID.
  *	An important exception are non-auto-increment primary keys. If one entry in the
  *	CSV file has the same ID as one in the DB, we assume they are meant to be
  *	the same item, and instead update the item in the DB with that same ID.
  *	Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
  *	time you import a CSV from a different site, we remember their mappings, and
  * will try to update the item in the DB instead of inserting another item (eg
  * if we previously imported an event with temporary ID 1, and then it got a
  * real ID of 123, we remember that. So the next time we import an event with
  * temporary ID, from the same site, we know that it's real ID is 123, and will
  * update that event, instead of adding a new event).
  *		  @access public
  *			@param array $csv_data_array - the array containing the csv data produced from EE_CSV::import_csv_to_model_data_array()
  *			@param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table fields they will be saved to
  *			@return TRUE on success, FALSE on fail
  */
 public function save_csv_to_db($csv_data_array, $model_name = FALSE)
 {
     $total_inserts = 0;
     $total_updates = 0;
     $total_insert_errors = 0;
     $total_update_errors = 0;
     $success = FALSE;
     $error = FALSE;
     //whther to treat this import as if it's data froma different database or not
     //ie, if it IS from a different database, ignore foreign keys whihf
     $export_from_site_a_to_b = true;
     // first level of array is not table information but a table name was passed to the function
     // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
     if ($model_name) {
         $csv_data_array = array($csv_data_array);
     }
     // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
     $old_site_url = 'none-specified';
     //hanlde metadata
     if (isset($csv_data_array[EE_CSV::metadata_header])) {
         $csv_metadata = array_shift($csv_data_array[EE_CSV::metadata_header]);
         //ok so its metadata, dont try to save it to ehte db obviously...
         if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
             EE_Error::add_attention(sprintf(__("CSV Data appears to be from the same database, so attempting to update data", "event_espresso")));
             $export_from_site_a_to_b = false;
         } else {
             $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
             EE_Error::add_attention(sprintf(__("CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database", "event_espresso"), $old_site_url, site_url()));
         }
         unset($csv_data_array[EE_CSV::metadata_header]);
     }
     /**
      * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
      * the value will be the newly-inserted ID.
      * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
      */
     $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
     if ($old_db_to_new_db_mapping) {
         EE_Error::add_attention(sprintf(__("We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s", "event_espresso"), $old_site_url, site_url()));
     }
     foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) {
         //now check that assumption was correct. If
         if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) {
             $model_name = $model_name_in_csv_data;
         } else {
             // no table info in the array and no table name passed to the function?? FAIL
             EE_Error::add_error(__('No table information was specified and/or found, therefore the import could not be completed', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
             return FALSE;
         }
         /* @var $model EEM_Base */
         $model = EE_Registry::instance()->load_model($model_name);
         //so without further ado, scanning all the data provided for primary keys and their inital values
         foreach ($model_data_from_import as $model_object_data) {
             //before we do ANYTHING, make sure the csv row wasn't just completely blank
             $row_is_completely_empty = true;
             foreach ($model_object_data as $field) {
                 if ($field) {
                     $row_is_completely_empty = false;
                 }
             }
             if ($row_is_completely_empty) {
                 continue;
             }
             //find the PK in the row of data (or a combined key if
             //there is no primary key)
             if ($model->has_primary_key_field()) {
                 $id_in_csv = $model_object_data[$model->primary_key_name()];
             } else {
                 $id_in_csv = $model->get_index_primary_key_string($model_object_data);
             }
             //now we need to decide if we're going to add a new model object given the $model_object_data,
             //or just update.
             if ($export_from_site_a_to_b) {
                 //if it's a site-to-site export-and-import, see if this modelobject's id
                 //in the old data that we know of
                 if (isset($old_db_to_new_db_mapping[$model_name][$id_in_csv])) {
                     $do_insert = false;
                     //and from now on, pretend the mapped ID of this thing is what we've mapped
                     if ($model->has_primary_key_field()) {
                         $model_object_data[$model->primary_key_name()] = $old_db_to_new_db_mapping[$model_name][$id_in_csv];
                     }
                 } else {
                     //check if this new DB has an exact copy of this model object (eg, a country or state that we don't want to duplicate)
                     $copy_in_db = $model->get_one_copy($model_object_data);
                     if ($copy_in_db) {
                         //so basically this already exists in the DB...
                         //remember the mapping
                         $old_db_to_new_db_mapping[$model_name][$id_in_csv] = $copy_in_db->ID();
                         //and don't bother trying to update or insert, beceause
                         //we JUST asserted that it's the exact same as what's in the DB
                         continue;
                     } else {
                         $do_insert = true;
                     }
                 }
                 //loop through all its related models, and see if we can swap their OLD foreign keys
                 //(ie, idsin the OLD db) for  new foreign key (ie ids in the NEW db)
                 foreach ($model->field_settings() as $field_name => $fk_field) {
                     if ($fk_field instanceof EE_Foreign_Key_Field_Base) {
                         $fk_value = $model_object_data[$fk_field->get_name()];
                         //if the foreign key is 0 or blank, just ignore it and leave it as-is
                         if ($fk_value == '0' || $fk_value == '') {
                             continue;
                         }
                         //now, is that value in the list of PKs that have been inserted?
                         if (is_array($fk_field->get_model_name_pointed_to())) {
                             //it points to a bunch of different models. We want to try each
                             $model_names_pointed_to = $fk_field->get_model_name_pointed_to();
                         } else {
                             $model_names_pointed_to = array($fk_field->get_model_name_pointed_to());
                         }
                         $found_new_id = false;
                         foreach ($model_names_pointed_to as $model_pointed_to_by_fk) {
                             if (isset($old_db_to_new_db_mapping[$model_pointed_to_by_fk][$fk_value])) {
                                 //and don't forget to replace the temporary id used in the csv with Id of the newly-added thing
                                 $model_object_data[$fk_field->get_name()] = $old_db_to_new_db_mapping[$model_pointed_to_by_fk][$fk_value];
                                 $found_new_id = true;
                             }
                         }
                         if (!$found_new_id) {
                             EE_Error::add_error(sprintf(__("Could not find %s with ID %s in old/csv for model %s and row %s.<br>", "event_espresso"), implode(",", $model_names_pointed_to), $fk_value, $model_name, http_build_query($model_object_data)), __FILE__, __FUNCTION__, __LINE__);
                         }
                     }
                 }
             } else {
                 //this is just a re-import
                 //in this case, check if this thing ACTUALLY exists in the database
                 if ($model->has_primary_key_field() && $model->get_one_by_ID($id_in_csv) || !$model->has_primary_key_field() && $model->get_one(array($model_object_data))) {
                     $do_insert = false;
                 } else {
                     $do_insert = true;
                 }
             }
             //double-check we actually want to insert, if that's what we're planning
             //based on whether this item would be unique in the DB or not
             if ($do_insert) {
                 //we're supposed to be inserting. But wait, will this thing
                 //be acceptable if inserted?
                 $conflicting = $model->get_one_conflicting($model_object_data);
                 if ($conflicting) {
                     //ok, this item would conflict if inserted. Just update the item that it conflicts with.
                     $do_insert = false;
                     //and if this model has a primary key, remember its mapping
                     if ($model->has_primary_key_field()) {
                         $old_db_to_new_db_mapping[$model_name][$id_in_csv] = $conflicting->ID();
                         $model_object_data[$model->primary_key_name()] = $conflicting->ID();
                     } else {
                         //we want to update this conflicting item, instead of inserting a conflicting item
                         //so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields
                         //for the WHERE conditions in the update). At the time of this comment, there were no models like this
                         foreach ($model->get_combined_primary_key_fields() as $key_field) {
                             $model_object_data[$key_field->get_name()] = $conflicting->get($key_field->get_name());
                         }
                     }
                 }
             }
             if ($do_insert) {
                 //remove the primary key, if there is one (we don't want it for inserts OR updates)
                 //we'll put it back in if we need it
                 if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) {
                     $effective_id = $model_object_data[$model->primary_key_name()];
                     unset($model_object_data[$model->primary_key_name()]);
                 }
                 //the model takes care of validating the CSV's input
                 try {
                     $new_id = $model->insert($model_object_data);
                     if ($new_id) {
                         $old_db_to_new_db_mapping[$model_name][$id_in_csv] = $new_id;
                         $total_inserts++;
                         EE_Error::add_success(sprintf(__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"), $model_name, $new_id, implode(",", $model_object_data)));
                     } else {
                         $total_insert_errors++;
                         $model_object_data[$model->primary_key_name()] = $effective_id;
                         EE_Error::add_error(sprintf(__("Could not insert new %s with the csv data: %s", "event_espresso"), $model_name, http_build_query($model_object_data)), __FILE__, __FUNCTION__, __LINE__);
                     }
                 } catch (EE_Error $e) {
                     $total_insert_errors++;
                     if ($model->has_primary_key_field()) {
                         $model_object_data[$model->primary_key_name()] = $effective_id;
                     }
                     EE_Error::add_error(sprintf(__("Could not insert new %s with the csv data: %s because %s", "event_espresso"), $model_name, implode(",", $model_object_data), $e->getMessage()), __FILE__, __FUNCTION__, __LINE__);
                 }
             } else {
                 //UPDATING
                 try {
                     if ($model->has_primary_key_field()) {
                         $conditions = array($model->primary_key_name() => $model_object_data[$model->primary_key_name()]);
                         unset($model_object_data[$model->primary_key_name()]);
                     } elseif ($model->get_combined_primary_key_fields() > 1) {
                         $conditions = array();
                         foreach ($model->get_combined_primary_key_fields() as $key_field) {
                             $conditions[$key_field->get_name()] = $model_object_data[$key_field->get_name()];
                         }
                     } else {
                         $model->primary_key_name();
                         //this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
                     }
                     $success = $model->update($model_object_data, array($conditions));
                     if ($success) {
                         $total_updates++;
                         EE_Error::add_success(sprintf(__("Successfully updated %s with csv data %s", "event_espresso"), $model_name, implode(",", $model_object_data)));
                     } else {
                         $matched_items = $model->get_all(array($conditions));
                         if (!$matched_items) {
                             //no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck?
                             $total_update_errors++;
                             EE_Error::add_error(sprintf(__("Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)", "event_espresso"), $model_name, http_build_query($model_object_data), http_build_query($conditions)), __FILE__, __FUNCTION__, __LINE__);
                         } else {
                             $total_updates++;
                             EE_Error::add_success(sprintf(__("%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.", "event_espresso"), $model_name, implode(",", $model_object_data)));
                         }
                     }
                 } catch (EE_Error $e) {
                     $total_update_errors++;
                     EE_Error::add_error(sprintf(__("Could not update %s with the csv data: %s because %s", "event_espresso"), $model_name, implode(",", $model_object_data), $e->getMessage()), __FILE__, __FUNCTION__, __LINE__);
                 }
             }
         }
     }
     //save the mapping from old db to new db in case they try re-importing the same data from the same website again
     update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping);
     if ($total_updates > 0) {
         EE_Error::add_success(sprintf(__("%s existing records in the database were updated.", "event_espresso"), $total_updates));
         $success = true;
     }
     if ($total_inserts > 0) {
         EE_Error::add_success(sprintf(__("%s new records were added to the database.", "event_espresso"), $total_inserts));
         $success = true;
     }
     if ($total_update_errors > 0) {
         EE_Error::add_error(sprintf(__("'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", "event_espresso"), $total_update_errors), __FILE__, __FUNCTION__, __LINE__);
         $error = true;
     }
     if ($total_insert_errors > 0) {
         EE_Error::add_error(sprintf(__("One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", "event_espresso"), $total_insert_errors), __FILE__, __FUNCTION__, __LINE__);
         $error = true;
     }
     //lastly, we need to update the datetime and ticket sold amounts
     //as those may ahve been affected by this
     EEM_Datetime::instance()->update_sold(EEM_Datetime::instance()->get_all());
     EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
     // if there was at least one success and absolutely no errors
     if ($success && !$error) {
         return TRUE;
     } else {
         return FALSE;
     }
 }
 /**
  * Gets all the tickets available for purchase of this event
  * @param array $query_params like EEM_Base::get_all
  * @return EE_Ticket[]
  */
 public function tickets($query_params = array())
 {
     //first get all datetimes
     $datetimes = $this->datetimes_ordered();
     if (!$datetimes) {
         return array();
     }
     $datetime_ids = array();
     foreach ($datetimes as $datetime) {
         $datetime_ids[] = $datetime->ID();
     }
     $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
     //if incoming $query_params has where conditions let's merge but not override existing.
     if (is_array($query_params) && isset($query_params[0])) {
         $where_params = array_merge($query_params[0], $where_params);
         unset($query_params[0]);
     }
     //now add $where_params to $query_params
     $query_params[0] = $where_params;
     return EEM_Ticket::instance()->get_all($query_params);
 }
 /**
  *    creates buttons for selecting number of attendees for an event
  *
  * @access 	public
  * @param 	object $event
  * @param 	bool 	$view_details
  * @return 	string
  */
 public static function display_ticket_selector($event = NULL, $view_details = FALSE)
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     //		d( $event );
     if ($event instanceof EE_Event) {
         self::$_event = $event;
     } else {
         if ($event instanceof WP_Post && isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) {
             self::$_event = $event->EE_Event;
         } else {
             if ($event instanceof WP_Post && (!isset($event->EE_Event) || !$event->EE_Event instanceof EE_Event)) {
                 $event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event);
                 self::$_event = $event->EE_Event;
             } else {
                 $user_msg = __('No Event object or an invalid Event object was supplied.', 'event_espresso');
                 $dev_msg = $user_msg . __('In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.', 'event_espresso');
                 EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
                 return FALSE;
             }
         }
     }
     if ((!self::$_event->display_ticket_selector() || $view_details) && !is_admin()) {
         return !is_single() ? EED_Ticket_Selector::display_view_details_btn(self::$_event) : '';
     }
     $template_args = array();
     $template_args['date_format'] = apply_filters('FHEE__EED_Ticket_Selector__display_ticket_selector__date_format', 'l F jS, Y');
     $template_args['time_format'] = apply_filters('FHEE__EED_Ticket_Selector__display_ticket_selector__time_format', 'g:i a');
     $template_args['EVT_ID'] = self::$_event->ID();
     $template_args['event'] = self::$_event;
     // is the event expired ?
     $template_args['event_is_expired'] = self::$_event->is_expired();
     if ($template_args['event_is_expired']) {
         return '<p><span class="important-notice">' . __('We\'re sorry, but all tickets sales have ended because the event is expired.', 'event_espresso') . '</span></p>';
     }
     // filter the maximum qty that can appear in the Ticket Selector qty dropdowns
     $template_args['max_atndz'] = apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets', self::$_event->additional_limit());
     if ($template_args['max_atndz'] < 1) {
         $sales_closed_msg = __('We\'re sorry, but ticket sales have been closed at this time. Please check back again later.', 'event_espresso');
         if (current_user_can('edit_post', self::$_event->ID())) {
             $sales_closed_msg .= sprintf(__('%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s', 'event_espresso'), '<div class="ee-attention" style="text-align: left;"><b>', '</b><br />', $link = '<span class="edit-link"><a class="post-edit-link" href="' . get_edit_post_link(self::$_event->ID()) . '">', '</a></span></div>');
         }
         return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
     }
     // get all tickets for this event ordered by the datetime
     $template_args['tickets'] = EEM_Ticket::instance()->get_all(array(array('Datetime.EVT_ID' => self::$_event->ID()), 'order_by' => array('TKT_required' => 'DESC', 'TKT_order' => 'ASC', 'TKT_start_date' => 'ASC', 'TKT_end_date' => 'ASC', 'Datetime.DTT_EVT_start' => 'DESC')));
     $templates['ticket_selector'] = TICKET_SELECTOR_TEMPLATES_PATH . 'ticket_selector_chart.template.php';
     $templates['ticket_selector'] = apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector__template_path', $templates['ticket_selector'], self::$_event);
     // redirecting to another site for registration ??
     $external_url = self::$_event->external_url() !== NULL || self::$_event->external_url() !== '' ? self::$_event->external_url() : FALSE;
     // set up the form (but not for the admin)
     $ticket_selector = !is_admin() ? EED_Ticket_Selector::ticket_selector_form_open(self::$_event->ID(), $external_url) : '';
     // if not redirecting to another site for registration
     if (!$external_url) {
         // then display the ticket selector
         $ticket_selector .= EEH_Template::locate_template($templates['ticket_selector'], $template_args);
     } else {
         // if not we still need to trigger the display of the submit button
         add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
         //display notice to admin that registration is external
         $ticket_selector .= !is_admin() ? '' : __('Registration is at an external URL for this event.', 'event_espresso');
     }
     // submit button and form close tag
     $ticket_selector .= !is_admin() ? EED_Ticket_Selector::display_ticket_selector_submit(self::$_event->ID()) : '';
     $ticket_selector .= !is_admin() ? EED_Ticket_Selector::ticket_selector_form_close() : '';
     return $ticket_selector;
 }
 /**
  * return the ticket object for a given ticket ID
  *
  * @since 4.3.0
  *
  * @param int $TKT_ID the ticket id for the ticket to attempt to retrieve
  *
  * @return mixed null|EE_Ticket
  */
 public function get_object_by_id($TKT_ID)
 {
     return EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
 }
 function test_wp_user_field_name()
 {
     $this->assertEquals('EVT_wp_user', EEM_Event::instance()->wp_user_field_name());
     $this->assertEquals('Registration.Event.EVT_wp_user', EEM_Transaction::instance()->wp_user_field_name());
     $this->assertEquals('TKT_wp_user', EEM_Ticket::instance()->wp_user_field_name());
 }
 /**
  * If a user can read private events, they should be able to read others private events' tickets
  */
 public function test_get_all__caps__read_admin__logged_in_with_read_private_events()
 {
     global $current_user;
     $current_user = $this->user;
     $current_user->add_cap('ee_read_events');
     $current_user->add_cap('ee_read_others_events');
     $current_user->add_cap('ee_read_private_events');
     $results = EEM_Ticket::instance()->get_all(array('caps' => EEM_Base::caps_read_admin, 'order_by' => array('TKT_ID' => 'ASC')));
     //I should be able to read tickets for my own events, and for others' that aren't private
     $this->assertEEModelObjectsEquals($this->t_mine, reset($results));
     $this->assertEEModelObjectsEquals($this->t_others, next($results));
     $this->assertEEModelObjectsEquals($this->t_private, next($results));
     $this->assertEquals(3, count($results));
 }
 /**
  * 	_ticket_row
  *
  * @param EE_Line_Item $line_item
  * @return mixed
  */
 private function _ticket_row(EE_Line_Item $line_item)
 {
     $ticket = EEM_Ticket::instance()->get_one_by_ID($line_item->OBJ_ID());
     if ($ticket instanceof EE_Ticket) {
         // start of row
         $content = $line_item->name();
         $content .= '<div style="margin:0 0 0 2em; text-align: right;">';
         $content .= ' ' . $line_item->quantity();
         $content .= _x(' x ', 'short form for times, for example: 2 x 4 = 8.', 'event_espresso');
         $content .= $line_item->unit_price_no_code() . ' = ';
         $content .= $line_item->is_taxable() ? $line_item->total_no_code() . '*' : $line_item->total_no_code();
         $content .= '</div>';
         // track taxes
         $this->_show_taxes = $line_item->is_taxable() ? true : $this->_show_taxes;
         return EEH_HTML::li($content, 'event-cart-ticket-list-' . $line_item->code());
     }
     return null;
 }
 protected function _delete_the_ticket($TKT_ID)
 {
     $tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
     $tkt->_remove_relations('Datetime');
     //delete all related prices first
     $tkt->delete_related_permanently('Price');
     return $tkt->delete_permanently();
 }
 /**
  *    _event_tickets
  * generates a multidimensional array of tickets grouped by event
  * where the event ids are the keys for the outer array
  *
  * @access    protected
  * @return array
  */
 protected function _event_tickets($TKT_ID = 0)
 {
     $event_tickets = array();
     $ticket_line_items = EE_Registry::instance()->CART->get_tickets();
     foreach ($ticket_line_items as $ticket_line_item) {
         if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() == 'Ticket') {
             $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
             if ($ticket instanceof EE_Ticket && $ticket->ID() != $TKT_ID) {
                 $event = $ticket->first_datetime()->event();
                 for ($x = 1; $x <= $ticket_line_item->quantity(); $x++) {
                     $event_tickets[$event->ID()][] = $ticket->ID();
                 }
             }
         }
     }
     return $event_tickets;
 }
 /**
  * 	posts_orderby_sql
  *
  * 	possible parameters:
  * 	ID
  * 	start_date
  * 	end_date
  * 	event_name
  * 	category_slug
  * 	ticket_start
  * 	ticket_end
  * 	venue_title
  * 	city
  * 	state
  *
  * 	**IMPORTANT**
  * 	make sure to also send the $orderby_params array to the posts_join_for_orderby() method
  * 	or else some of the table references below will result in MySQL errors
  *
  *  @access 	public
  *  @param	boolean	$orderby_params
  *  @return 	string
  */
 public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC')
 {
     global $wpdb;
     $SQL = '';
     $cntr = 1;
     $orderby_params = is_array($orderby_params) ? $orderby_params : array($orderby_params);
     foreach ($orderby_params as $orderby) {
         $glue = $cntr == 1 || $cntr == count($orderby_params) ? ' ' : ', ';
         switch ($orderby) {
             case 'id':
             case 'ID':
                 $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
                 break;
             case 'start_date':
                 $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_start ' . $sort;
                 break;
             case 'end_date':
                 $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
                 break;
             case 'event_name':
                 $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
                 break;
             case 'category_slug':
                 $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
                 break;
             case 'ticket_start':
                 $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
                 break;
             case 'ticket_end':
                 $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
                 break;
             case 'venue_title':
                 $SQL .= $glue . 'venue_title ' . $sort;
                 break;
             case 'city':
                 $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
                 break;
             case 'state':
                 $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
                 break;
         }
         $cntr++;
     }
     //echo '<h4>$SQL : ' . $SQL . '  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h4>';
     return $SQL;
 }
 /**
  * 		_trash_or_restore_price
  *		@param boolean 		$trash - whether to move item to trash (TRUE) or restore it (FALSE)
  *		@access protected
  *		@return void
  */
 protected function _trash_or_restore_price($trash = TRUE)
 {
     //echo '<h3>'. __CLASS__ . '->' . __FUNCTION__ . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h3>';
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     require_once EE_MODELS . 'EEM_Price.model.php';
     $PRC = EEM_Price::instance();
     $success = 1;
     $PRC_deleted = $trash ? TRUE : FALSE;
     //get base ticket for updating
     $ticket = EEM_Ticket::instance()->get_one_by_ID(1);
     //Checkboxes
     if (!empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
         // if array has more than one element than success message should be plural
         $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
         // cycle thru checkboxes
         while (list($PRC_ID, $value) = each($this->_req_data['checkbox'])) {
             if (!$PRC->update_by_ID(array('PRC_deleted' => $PRC_deleted), absint($PRC_ID))) {
                 $success = 0;
             } else {
                 $PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
                 if ($PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
                     //if trashing then remove relations to base default ticket.  If restoring then add back to base default ticket
                     if ($PRC_deleted) {
                         $ticket->_remove_relation_to($PRC_ID, 'Price');
                     } else {
                         $ticket->_add_relation_to($PRC_ID, 'Price');
                     }
                     $ticket->save();
                 }
             }
         }
     } else {
         // grab single id and delete
         $PRC_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
         if (empty($PRC_ID) || !$PRC->update_by_ID(array('PRC_deleted' => $PRC_deleted), $PRC_ID)) {
             $success = 0;
         } else {
             $PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
             if ($PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
                 //if trashing then remove relations to base default ticket.  If restoring then add back to base default ticket
                 if ($PRC_deleted) {
                     $ticket->_remove_relation_to($PRC_ID, 'Price');
                 } else {
                     $ticket->_add_relation_to($PRC_ID, 'Price');
                 }
                 $ticket->save();
             }
         }
     }
     $query_args = array('action' => 'default');
     if ($success) {
         if ($trash) {
             $msg = $success == 2 ? __('The Prices have been trashed.', 'event_espresso') : __('The Price has been trashed.', 'event_espresso');
         } else {
             $msg = $success == 2 ? __('The Prices have been restored.', 'event_espresso') : __('The Price has been restored.', 'event_espresso');
         }
         EE_Error::add_success($msg);
     }
     $this->_redirect_after_action(FALSE, '', '', $query_args, TRUE);
 }
 /**
  * test verifies that if importing from site A to B, is the exported data from A
  * coincidentally has the same IDs as data in site B, that it DOES NOT overwrite it
  */
 public function test_save_data_array_to_db__from_other_site__data_with_same_ids()
 {
     //add some stuff to the db, but just keep references to their clones (which won't be affected by the entity mapper)
     $original_event1 = clone $this->new_model_obj_with_dependencies('Event');
     $original_datetime1 = clone $this->new_model_obj_with_dependencies('Datetime', array('EVT_ID' => $original_event1->ID()));
     $original_ticket1 = clone $this->new_model_obj_with_dependencies('Ticket');
     $original_datetime_ticket = clone $this->new_model_obj_with_dependencies('Datetime_Ticket', array('DTT_ID' => $original_datetime1->ID(), 'TKT_ID' => $original_ticket1->ID()));
     //now let's make some model objects that AREN'T in this database
     //that could confuse the importer
     $other_db_event = $this->new_model_obj_with_dependencies('Event', array(), false);
     $other_db_event_props = $other_db_event->model_field_array();
     $other_db_event_props['EVT_ID'] = $original_event1->ID();
     $other_db_event2 = $this->new_model_obj_with_dependencies('Event', array(), false);
     $other_db_event2_props = $other_db_event2->model_field_array();
     $other_db_event2_props['EVT_ID'] = 1000;
     $other_db_datetime = $this->new_model_obj_with_dependencies('Datetime', array('EVT_ID' => $original_event1->ID()), false);
     $other_db_datetime_props = $other_db_datetime->model_field_array();
     $other_db_datetime_props['DTT_ID'] = $original_datetime1->ID();
     $other_db_ticket = $this->new_model_obj_with_dependencies('Ticket', array('TKT_ID' => $original_ticket1->ID()), false);
     $other_db_ticket_props = $other_db_ticket->model_field_array();
     $other_db_ticket_props['TKT_ID'] = $original_ticket1->ID();
     $other_db_datetime_ticket = EE_Datetime_Ticket::new_instance(array('DTT_ID' => $original_datetime1->ID(), 'TKT_ID' => $original_ticket1->ID()), false);
     $other_db_datetime_ticket_props = $other_db_datetime_ticket->model_field_array();
     $other_db_datetime_ticket_props['DTK_ID'] = $original_datetime_ticket->ID();
     $event_count = EEM_Event::instance()->count();
     $datetime_count = EEM_Datetime::instance()->count();
     $ticket_count = EEM_Ticket::instance()->count();
     $datetime_ticket_count = EEM_Datetime_Ticket::instance()->count();
     $csv_data_rows = array('Event' => array($other_db_event_props, $other_db_event2_props), 'Datetime' => array($other_db_datetime_props), 'Ticket' => array($other_db_ticket_props), 'Datetime_Ticket' => array($other_db_datetime_ticket_props));
     //ok give it a whirl...
     $new_mappings = EE_Import::instance()->save_data_rows_to_db($csv_data_rows, true, array());
     //what should have happened:
     //we should have a mapping for each newly-inserted
     //events...
     $this->assertNotEmpty($new_mappings);
     $this->assertArrayHasKey('Event', $new_mappings);
     $event1_mapping = $new_mappings['Event'][$original_event1->ID()];
     $this->assertNotEmpty($event1_mapping);
     $this->assertNotEquals($original_event1->ID(), $event1_mapping);
     $event2_mapping = $new_mappings['Event'][1000];
     $this->assertNotEmpty($event2_mapping);
     $this->assertNotEquals(1000, $event1_mapping);
     //newly inerted datetime...
     $this->assertNotEmpty($new_mappings);
     $this->assertArrayHasKey('Datetime', $new_mappings);
     $datetime1_mapping = $new_mappings['Datetime'][$original_datetime1->ID()];
     $this->assertNotEmpty($datetime1_mapping);
     $this->assertNotEquals($original_datetime1->ID(), $datetime1_mapping);
     //newly inserted ticket
     $this->assertNotEmpty($new_mappings);
     $this->assertArrayHasKey('Ticket', $new_mappings);
     $ticket1_mapping = $new_mappings['Ticket'][$original_ticket1->ID()];
     $this->assertNotEmpty($ticket1_mapping);
     $this->assertNotEquals($original_ticket1->ID(), $ticket1_mapping);
     //and newly inserted datetime-ticke...
     $this->assertNotEmpty($new_mappings);
     $this->assertArrayHasKey('Datetime_Ticket', $new_mappings);
     $datetime_ticket_mapping = $new_mappings['Datetime_Ticket'][$original_datetime_ticket->ID()];
     $this->assertNotEmpty($datetime_ticket_mapping);
     $this->assertNotEquals($original_datetime_ticket->ID(), $datetime_ticket_mapping);
     //we should have inserted 2 new events, 1 new datetime, 1 new ticket and 1 new relation
     $this->assertEquals($event_count + 2, EEM_Event::instance()->count());
     $this->assertEquals($datetime_count + 1, EEM_Datetime::instance()->count());
     $this->assertEquals($ticket_count + 1, EEM_Ticket::instance()->count());
     $this->assertEquals($datetime_ticket_count + 1, EEM_Datetime_Ticket::instance()->count());
     //the newly inserted datetime shoudl have bene associated to the new event for $other_db_event_props
     $inserted_datetime_from_other_db = EEM_Datetime::instance()->get_one_by_ID($datetime1_mapping);
     $this->assertEquals($event1_mapping, $inserted_datetime_from_other_db->get('EVT_ID'));
     //there shoudl be a newly inserted ticket
     $inserted_ticket_from_other_db = EEM_Ticket::instance()->get_one_by_ID($ticket1_mapping);
     $this->assertNotNull($inserted_ticket_from_other_db);
     //the newly inserted datetime-ticket should hae been associated with the newly inserted datetime and ticket
     $inserted_datetime_ticket_from_other_db = EEM_Datetime_Ticket::instance()->get_one_by_ID($datetime_ticket_mapping);
     $this->assertEquals($ticket1_mapping, $inserted_datetime_ticket_from_other_db->get('TKT_ID'));
     $this->assertEquals($datetime1_mapping, $inserted_datetime_ticket_from_other_db->get('DTT_ID'));
     //the original event shouldn't be affected, nor should it have more than the original datetime on it
     $updated_event1 = EEM_Event::instance()->refresh_entity_map_from_db($original_event1->ID());
     $this->assertEEModelObjectsEquals($original_event1, $updated_event1);
     //the original datetime shoudln't be affected, nor shoudl it have more than the original ticket associagted with it
     $updated_datetime1 = EEM_Datetime::instance()->refresh_entity_map_from_db($original_datetime1->ID());
     $this->assertEEModelObjectsEquals($original_datetime1, $updated_datetime1);
 }
 public function column_tkts_sold($item)
 {
     return EEM_Ticket::instance()->sum(array(array('Datetime.EVT_ID' => $item->ID())), 'TKT_sold');
 }
 /**
  * 	_ticket_row
  *
  * @param EE_Line_Item $line_item
  * @param array        $options
  * @return mixed
  */
 private function _ticket_row(EE_Line_Item $line_item, $options = array())
 {
     $ticket = EEM_Ticket::instance()->get_one_by_ID($line_item->OBJ_ID());
     if ($ticket instanceof EE_Ticket) {
         // start of row
         $html = EEH_HTML::tr('', 'event-cart-ticket-row-' . $line_item->ID(), 'event-cart-ticket-row item');
         // name && desc
         $name_and_desc = $line_item->name();
         $name_and_desc .= $options['show_desc'] ? '<span class="line-item-desc-spn smaller-text"> : ' . $line_item->desc() . '</span>' : '';
         $name_and_desc = $line_item->is_taxable() ? $name_and_desc . ' * ' : $name_and_desc;
         // name td
         $html .= EEH_HTML::td($name_and_desc, '', 'ticket info');
         // price td
         $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
         // quantity td
         $html .= EEH_HTML::td($this->_ticket_qty_input($line_item, $ticket), '', 'jst-rght');
         // total td
         $html .= EEH_HTML::td($line_item->total_no_code(), '', 'jst-rght');
         // end of row
         $html .= EEH_HTML::trx();
         return $html;
     }
     return null;
 }
 /**
  *    creates buttons for selecting number of attendees for an event
  *
  * @access 	public
  * @param 	object $event
  * @param 	bool 	$view_details
  * @return 	string
  */
 public static function display_ticket_selector($event = NULL, $view_details = FALSE)
 {
     // reset filter for displaying submit button
     remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
     // poke and prod incoming event till it tells us what it is
     if (!EED_Ticket_Selector::set_event($event)) {
         return false;
     }
     $event_post = self::$_event instanceof EE_Event ? self::$_event->ID() : $event;
     // grab event status
     $_event_active_status = self::$_event->get_active_status();
     if (!is_admin() && (!self::$_event->display_ticket_selector() || $view_details || post_password_required($event_post) || $_event_active_status != EE_Datetime::active && $_event_active_status != EE_Datetime::upcoming && $_event_active_status != EE_Datetime::sold_out && !($_event_active_status == EE_Datetime::inactive && is_user_logged_in()))) {
         return !is_single() ? EED_Ticket_Selector::display_view_details_btn() : '';
     }
     $template_args = array();
     $template_args['event_status'] = $_event_active_status;
     $template_args['date_format'] = apply_filters('FHEE__EED_Ticket_Selector__display_ticket_selector__date_format', get_option('date_format'));
     $template_args['time_format'] = apply_filters('FHEE__EED_Ticket_Selector__display_ticket_selector__time_format', get_option('time_format'));
     $template_args['EVT_ID'] = self::$_event->ID();
     $template_args['event'] = self::$_event;
     // is the event expired ?
     $template_args['event_is_expired'] = self::$_event->is_expired();
     if ($template_args['event_is_expired']) {
         return '<div class="ee-event-expired-notice"><span class="important-notice">' . __('We\'re sorry, but all tickets sales have ended because the event is expired.', 'event_espresso') . '</span></div>';
     }
     $ticket_query_args = array(array('Datetime.EVT_ID' => self::$_event->ID()), 'order_by' => array('TKT_order' => 'ASC', 'TKT_required' => 'DESC', 'TKT_start_date' => 'ASC', 'TKT_end_date' => 'ASC', 'Datetime.DTT_EVT_start' => 'DESC'));
     if (!EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector->show_expired_tickets) {
         //use the correct applicable time query depending on what version of core is being run.
         $current_time = method_exists('EEM_Datetime', 'current_time_for_query') ? time() : current_time('timestamp');
         $ticket_query_args[0]['TKT_end_date'] = array('>', $current_time);
     }
     // get all tickets for this event ordered by the datetime
     $template_args['tickets'] = EEM_Ticket::instance()->get_all($ticket_query_args);
     if (count($template_args['tickets']) < 1) {
         return '<div class="ee-event-expired-notice"><span class="important-notice">' . __('We\'re sorry, but all ticket sales have ended.', 'event_espresso') . '</span></div>';
     }
     // filter the maximum qty that can appear in the Ticket Selector qty dropdowns
     $template_args['max_atndz'] = apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets', self::$_event->additional_limit());
     if ($template_args['max_atndz'] < 1) {
         $sales_closed_msg = __('We\'re sorry, but ticket sales have been closed at this time. Please check back again later.', 'event_espresso');
         if (current_user_can('edit_post', self::$_event->ID())) {
             $sales_closed_msg .= sprintf(__('%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s', 'event_espresso'), '<div class="ee-attention" style="text-align: left;"><b>', '</b><br />', $link = '<span class="edit-link"><a class="post-edit-link" href="' . get_edit_post_link(self::$_event->ID()) . '">', '</a></span></div>');
         }
         return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
     }
     $templates['ticket_selector'] = TICKET_SELECTOR_TEMPLATES_PATH . 'ticket_selector_chart.template.php';
     $templates['ticket_selector'] = apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector__template_path', $templates['ticket_selector'], self::$_event);
     // redirecting to another site for registration ??
     $external_url = self::$_event->external_url() !== NULL || self::$_event->external_url() !== '' ? self::$_event->external_url() : FALSE;
     // set up the form (but not for the admin)
     $ticket_selector = !is_admin() ? EED_Ticket_Selector::ticket_selector_form_open(self::$_event->ID(), $external_url) : '';
     // if not redirecting to another site for registration
     if (!$external_url) {
         // then display the ticket selector
         $ticket_selector .= EEH_Template::locate_template($templates['ticket_selector'], $template_args);
     } else {
         // if not we still need to trigger the display of the submit button
         add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
         //display notice to admin that registration is external
         $ticket_selector .= !is_admin() ? '' : __('Registration is at an external URL for this event.', 'event_espresso');
     }
     // submit button and form close tag
     $ticket_selector .= !is_admin() ? EED_Ticket_Selector::display_ticket_selector_submit() : '';
     // set no cache headers and constants
     EE_System::do_not_cache();
     return $ticket_selector;
 }
 /**
  * 	_ticket_row
  *
  * @param EE_Line_Item $line_item
  * @return mixed
  */
 private function _ticket_row(EE_Line_Item $line_item)
 {
     $ticket = EEM_Ticket::instance()->get_one_by_ID($line_item->OBJ_ID());
     if ($ticket instanceof EE_Ticket) {
         // start of row
         $html = '';
         $html .= EEH_HTML::tr('', 'event-cart-item-row-' . $line_item->code());
         $this->_show_taxes = $line_item->is_taxable() ? true : $this->_show_taxes;
         $line_item_name = $line_item->is_taxable() ? $line_item->name() . ' * ' : $line_item->name();
         // name td
         $html .= EEH_HTML::td($line_item_name, '', 'ticket info');
         // price td
         $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
         // quantity td
         $html .= EEH_HTML::td($line_item->quantity(), '', 'mini-cart-tbl-qty-td jst-cntr');
         // total td
         $html .= EEH_HTML::td($line_item->total_no_code(), '', 'jst-rght');
         // end of row
         $html .= EEH_HTML::trx();
         return $html;
     }
     return null;
 }
 /**
  *    perform_sold_out_status_check
  *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
  *    if NOT, then the event status will get toggled to 'sold_out'
  *
  * @access public
  * @return bool    return the ACTUAL sold out state.
  */
 public function perform_sold_out_status_check()
 {
     // get all unexpired untrashed tickets
     $tickets = $this->tickets(array(array('TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')), 'TKT_deleted' => false)));
     // if all the tickets are just expired, then don't update the event status to sold out
     if (empty($tickets)) {
         return true;
     }
     // set initial value
     $spaces_remaining = 0;
     foreach ($tickets as $ticket) {
         if ($ticket instanceof EE_Ticket) {
             $spaces_remaining += $ticket->qty('saleable');
         }
     }
     if ($spaces_remaining === 0) {
         $this->set_status(EEM_Event::sold_out);
         if (!is_admin() || is_admin() && defined('DOING_AJAX')) {
             $this->save();
         }
         $sold_out = TRUE;
     } else {
         $sold_out = FALSE;
         // was event previously marked as sold out ?
         if ($this->status() == EEM_Event::sold_out) {
             // revert status to previous value, if it was set
             $previous_event_status = $this->get_post_meta('_previous_event_status', true);
             if ($previous_event_status) {
                 $this->set_status($previous_event_status);
             }
         }
     }
     //note: I considered changing the EEM_Event status away from sold_out if this status check reveals that it's no longer sold out (yet the status is still set as sold out) but the problem is... what do we change the status BACK to?  We can't always assume that the previous event status was 'published' because this status check is always done in the admin and its entirely possible the event admin manually changes to sold_out status from some other status.  We also don't want a draft event to become a "publish event" because the sold out check reveals its NOT sold out.
     // So I'll forgo the automatic switch away from sold out status for now and instead just return the $sold out status... so this check can be used to validate the TRUE sold out status regardless of what the Event status is set to.
     return $sold_out;
 }
 /**
  *    posts_orderby_sql
  *
  *    possible parameters:
  *    ID
  *    start_date
  *    end_date
  *    event_name
  *    category_slug
  *    ticket_start
  *    ticket_end
  *    venue_title
  *    city
  *    state
  *
  *    **IMPORTANT**
  *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
  *    or else some of the table references below will result in MySQL errors
  *
  * @access    public
  * @param array|bool $orderby_params
  * @param string     $sort
  * @return    string
  */
 public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC')
 {
     global $wpdb;
     $SQL = '';
     $counter = 0;
     //make sure 'orderby' is set in query params
     if (!isset(self::$_query_params['orderby'])) {
         self::$_query_params['orderby'] = array();
     }
     // loop thru $orderby_params (type cast as array)
     foreach ((array) $orderby_params as $orderby) {
         // check if we have already added this param
         if (isset(self::$_query_params['orderby'][$orderby])) {
             // if so then remove from the $orderby_params so that the count() method below is accurate
             unset($orderby_params[$orderby]);
             // then bump ahead to the next param
             continue;
         }
         // this will ad a comma depending on whether this is the first or last param
         $glue = $counter == 0 || $counter == count($orderby_params) ? ' ' : ', ';
         // ok what's we dealing with?
         switch ($orderby) {
             case 'id':
             case 'ID':
                 $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
                 break;
             case 'end_date':
                 $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
                 break;
             case 'event_name':
                 $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
                 break;
             case 'category_slug':
                 $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
                 break;
             case 'ticket_start':
                 $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
                 break;
             case 'ticket_end':
                 $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
                 break;
             case 'venue_title':
                 $SQL .= $glue . 'venue_title ' . $sort;
                 break;
             case 'city':
                 $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
                 break;
             case 'state':
                 $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
                 break;
             case 'start_date':
             default:
                 $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_start ' . $sort;
                 break;
         }
         // add to array of orderby params that have been added
         self::$_query_params['orderby'][$orderby] = TRUE;
         $counter++;
     }
     return $SQL;
 }
 /**
  * Counts the total tickets available (from all the different types of tickets which are available for
  * this datetime).
  * @param array $query_params like EEM_Base::get_all's
  * @return int
  */
 public function tickets_remaining($query_params = array())
 {
     return EEM_Ticket::instance()->sum_tickets_currently_available_at_datetime($this->ID(), $query_params);
 }
 public function test_delete_all()
 {
     $ticket_1 = $this->new_model_obj_with_dependencies('Ticket', array('TKT_price' => '5'), false);
     $ticket_2 = $this->new_model_obj_with_dependencies('Ticket', array('TKT_price' => '6'), false);
     $this->repository->add($ticket_1);
     $this->repository->add($ticket_2);
     $this->assertTrue($this->repository->has($ticket_1));
     $this->assertTrue($this->repository->has($ticket_2));
     $this->assertEquals(count($this->repository), 2);
     $this->assertEquals($ticket_1->ID(), 0);
     $this->assertEquals($ticket_2->ID(), 0);
     $saved = $this->repository->save_all();
     $this->assertEquals($saved, true);
     $ticket_1_ID = $ticket_1->ID();
     $ticket_2_ID = $ticket_2->ID();
     $this->assertNotEquals($ticket_1_ID, 0);
     $this->assertNotEquals($ticket_2_ID, 0);
     // now test that we can delete the tickets and remove them from the repo
     $deleted = $this->repository->delete_all();
     $this->assertTrue($deleted);
     $this->assertFalse($this->repository->has($ticket_1));
     $this->assertFalse($this->repository->has($ticket_2));
     // and the total count
     $this->assertEquals(count($this->repository), 0);
     // because tickets are soft deletable
     $ticket1_from_db = EEM_Ticket::instance()->get_one_by_ID($ticket_1_ID);
     $this->assertTrue($ticket1_from_db->deleted());
     $ticket2_from_db = EEM_Ticket::instance()->get_one_by_ID($ticket_2_ID);
     $this->assertTrue($ticket2_from_db->deleted());
 }