/**
  * Calculates the checkin status for each datetime this registration has access to
  *
  * @param array            $wpdb_row
  * @param \WP_REST_Request $request
  * @param Base             $controller
  * @return int
  * @throws \EE_Error
  */
 public static function datetime_checkin_stati($wpdb_row, $request, $controller)
 {
     if (is_array($wpdb_row) && isset($wpdb_row['Registration.REG_ID'])) {
         $reg = \EEM_Registration::instance()->get_one_by_ID($wpdb_row['Registration.REG_ID']);
     } else {
         $reg = null;
     }
     if (!$reg instanceof \EE_Registration) {
         throw new \EE_Error(sprintf(__('Cannot calculate datetime_checkin_stati because the registration with ID %1$s (from database row %2$s) was not found', 'event_espresso'), $wpdb_row['Registration.REG_ID'], print_r($wpdb_row, true)));
     }
     $datetime_ids = \EEM_Datetime::instance()->get_col(array(array('Ticket.TKT_ID' => $reg->ticket_ID())));
     $checkin_stati = array();
     foreach ($datetime_ids as $datetime_id) {
         $status = $reg->check_in_status_for_datetime($datetime_id);
         switch ($status) {
             case \EE_Registration::checkin_status_out:
                 $status_pretty = 'OUT';
                 break;
             case \EE_Registration::checkin_status_in:
                 $status_pretty = 'IN';
                 break;
             case \EE_Registration::checkin_status_never:
             default:
                 $status_pretty = 'NEVER';
                 break;
         }
         $checkin_stati[$datetime_id] = $status_pretty;
     }
     return $checkin_stati;
 }
 /**
  * This allows setting the $_datetime property to a new ticket object if the incoming args for the
  * new ticket have a dtt_id (or set to default if no dtt_id)
  *
  * @since 4.3.0
  * @param int $DTT_ID EE_Datetime ID
  */
 private function _set_new_datetime($DTT_ID = 0)
 {
     $this->_datetime = empty($DTT_ID) ? EEM_Datetime::instance()->get_one_by_ID($DTT_ID) : $this->factory->datetime_chained->create();
     //fail safe just in case (so we can be sure to have an datetime).
     if (empty($this->_datetime)) {
         $this->_datetime = $this->factory->datetime_chained->create();
     }
 }
 /**
  *		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_Datetime 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);
     }
     //we might have a timezone set, let set_timezone decide what to do with it
     self::$_instance->set_timezone($timezone);
     // Espresso_model object
     return self::$_instance;
 }
示例#4
0
 /**
  * Calculates the total spaces available on the datetime, taking into account
  * ticket limits too.
  *
  * @see EE_Datetime::spaces_remaining( true )
  * @param array            $wpdb_row
  * @param \WP_REST_Request $request
  * @param Controller_Base  $controller
  * @return int
  * @throws \EE_Error
  */
 public static function spaces_remaining_considering_tickets($wpdb_row, $request, $controller)
 {
     if (is_array($wpdb_row) && isset($wpdb_row['Datetime.DTT_ID'])) {
         $dtt_obj = \EEM_Datetime::instance()->get_one_by_ID($wpdb_row['Datetime.DTT_ID']);
     } else {
         $dtt_obj = null;
     }
     if ($dtt_obj instanceof \EE_Datetime) {
         return $dtt_obj->spaces_remaining(true);
     } else {
         throw new \EE_Error(sprintf(__('Cannot calculate spaces_remaining_considering_tickets because the datetime with ID %1$s (from database row %2$s) was not found', 'event_espresso'), $wpdb_row['Datetime.DTT_ID'], print_r($wpdb_row, true)));
     }
 }
 /**
  * Gets all events happening at this venue. Query parameters can be added to
  * fetch a subset of those events.
  * @param array $query_params like EEM_Base::get_all's $query_params
  * @param bool  $upcoming
  * @return EE_Event[]
  */
 function events($query_params = array(), $upcoming = FALSE)
 {
     if ($upcoming) {
         $query_params = array(array('status' => 'publish', 'Datetime.DTT_EVT_start' => array('>', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'))));
     }
     return $this->get_many_related('Event', $query_params);
 }
 /**
  * Gets all the datetimes from the db ordered by DTT_order
  * @param boolean $show_expired
  * @param boolean $show_deleted
  * @return EE_Datetime[]
  */
 public function datetimes_ordered($show_expired = TRUE, $show_deleted = FALSE)
 {
     return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order($this->ID(), $show_expired, $show_deleted);
 }
示例#7
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;
     }
 }
 /**
  * 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);
 }
 /**
  * Returns the 'primary' datetime for the event
  * @param bool $try_to_exclude_expired
  * @param bool $try_to_exclude_deleted
  * @return EE_Datetime
  */
 public function primary_datetime($try_to_exclude_expired = TRUE, $try_to_exclude_deleted = TRUE)
 {
     if (!empty($this->_Primary_Datetime)) {
         return $this->_Primary_Datetime;
     }
     $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event($this->ID(), $try_to_exclude_expired, $try_to_exclude_deleted);
     return $this->_Primary_Datetime;
 }
 /**
  * Front-end display of widget.
  *
  * @see WP_Widget::widget()
  *
  * @param array $args     Widget arguments.
  * @param array $instance Saved values from database.
  */
 public function widget($args, $instance)
 {
     global $post;
     // make sure there is some kinda post object
     if ($post instanceof WP_Post) {
         $before_widget = '';
         $before_title = '';
         $after_title = '';
         $after_widget = '';
         // but NOT an events archives page, cuz that would be like two event lists on the same page
         $show_everywhere = isset($instance['show_everywhere']) ? (bool) absint($instance['show_everywhere']) : TRUE;
         if ($show_everywhere || !($post->post_type == 'espresso_events' && is_archive())) {
             // let's use some of the event helper functions'
             // make separate vars out of attributes
             extract($args);
             // add function to make the title a link
             add_filter('widget_title', array($this, 'make_the_title_a_link'), 15);
             // filter the title
             $title = apply_filters('widget_title', $instance['title']);
             // remove the function from the filter, so it does not affect other widgets
             remove_filter('widget_title', array($this, 'make_the_title_a_link'), 15);
             // Before widget (defined by themes).
             echo $before_widget;
             // Display the widget title if one was input (before and after defined by themes).
             if (!empty($title)) {
                 echo $before_title . $title . $after_title;
             }
             // grab widget settings
             $category = isset($instance['category_name']) && !empty($instance['category_name']) ? $instance['category_name'] : FALSE;
             $show_expired = isset($instance['show_expired']) ? (bool) absint($instance['show_expired']) : FALSE;
             $image_size = isset($instance['image_size']) && !empty($instance['image_size']) ? $instance['image_size'] : 'medium';
             $show_desc = isset($instance['show_desc']) ? (bool) absint($instance['show_desc']) : TRUE;
             $show_dates = isset($instance['show_dates']) ? (bool) absint($instance['show_dates']) : TRUE;
             $date_limit = isset($instance['date_limit']) && !empty($instance['date_limit']) ? $instance['date_limit'] : NULL;
             $date_range = isset($instance['date_range']) && !empty($instance['date_range']) ? $instance['date_range'] : FALSE;
             // start to build our where clause
             $where = array('status' => 'publish');
             // add category
             if ($category) {
                 $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
                 $where['Term_Taxonomy.Term.slug'] = $category;
             }
             // if NOT expired then we want events that start today or in the future
             if (!$show_expired) {
                 $where['Datetime.DTT_EVT_end'] = array('>=', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'));
             }
             // run the query
             $events = EE_Registry::instance()->load_model('Event')->get_all(array($where, 'limit' => $instance['limit'] > 0 ? '0,' . $instance['limit'] : '0,10', 'order_by' => 'Datetime.DTT_EVT_start', 'order' => 'ASC', 'group_by' => 'EVT_ID'));
             if (!empty($events)) {
                 echo '<ul class="ee-upcoming-events-widget-ul">';
                 foreach ($events as $event) {
                     if ($event instanceof EE_Event && (!is_single() || $post->ID != $event->ID())) {
                         //printr( $event, '$event  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
                         echo '<li id="ee-upcoming-events-widget-li-' . $event->ID() . '" class="ee-upcoming-events-widget-li">';
                         // how big is the event name ?
                         $name_length = strlen($event->name());
                         switch ($name_length) {
                             case $name_length > 70:
                                 $len_class = ' three-line';
                                 break;
                             case $name_length > 35:
                                 $len_class = ' two-line';
                                 break;
                             default:
                                 $len_class = ' one-line';
                         }
                         $event_url = apply_filters('FHEE_EEW_Upcoming_Events__widget__event_url', $event->get_permalink(), $event);
                         echo '<h5 class="ee-upcoming-events-widget-title-h5"><a class="ee-widget-event-name-a' . $len_class . '" href="' . $event_url . '">' . $event->name() . '</a></h5>';
                         if (has_post_thumbnail($event->ID()) && $image_size != 'none') {
                             echo '<div class="ee-upcoming-events-widget-img-dv"><a class="ee-upcoming-events-widget-img" href="' . $event_url . '">' . get_the_post_thumbnail($event->ID(), $image_size) . '</a></div>';
                         }
                         $desc = $event->short_description(25);
                         if ($show_dates) {
                             $date_format = apply_filters('FHEE__espresso_event_date_range__date_format', get_option('date_format'));
                             $time_format = apply_filters('FHEE__espresso_event_date_range__time_format', get_option('time_format'));
                             $single_date_format = apply_filters('FHEE__espresso_event_date_range__single_date_format', get_option('date_format'));
                             $single_time_format = apply_filters('FHEE__espresso_event_date_range__single_time_format', get_option('time_format'));
                             if ($date_range == TRUE) {
                                 echo espresso_event_date_range($date_format, $time_format, $single_date_format, $single_time_format, $event->ID());
                             } else {
                                 echo espresso_list_of_event_dates($event->ID(), $date_format, $time_format, FALSE, NULL, TRUE, TRUE, $date_limit);
                             }
                         }
                         if ($show_desc && $desc) {
                             echo '<p style="margin-top: .5em">' . $desc . '</p>';
                         }
                         echo '</li>';
                     }
                 }
                 echo '</ul>';
             }
             // After widget (defined by themes).
             echo $after_widget;
         }
     }
 }
 /**
  * This only returns events that are expired.  They may still be published but all their datetimes have expired.
  *
  * @access public
  * @param  array  $query_params An array of query params to further filter on (note that status and DTT_EVT_end will be overridden)
  * @param bool    $count whether to return the count or not (default FALSE)
  * @return array 	EE_Event objects
  */
 public function get_expired_events($query_params, $count = FALSE)
 {
     $where_params = isset($query_params[0]) ? $query_params[0] : array();
     //if we have count make sure we don't include group by
     if ($count && isset($query_params['group_by'])) {
         unset($query_params['group_by']);
     }
     //let's add specific query_params for active_events - keep in mind this will override any sent status in the query AND any date queries.
     if (isset($where_params['status'])) {
         unset($where_params['status']);
     }
     $exclude_query = $query_params;
     if (isset($exclude_query[0])) {
         unset($exclude_query[0]);
     }
     $exclude_query[0] = array('Datetime.DTT_EVT_end' => array('>', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')));
     //first get all events that have datetimes where its not expired.
     $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
     $event_ids = array_keys($event_ids);
     //if we have any additional query_params, let's add them to the 'AND' condition
     $and_condition = array('Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')), 'EVT_ID' => array('NOT IN', $event_ids));
     if (isset($where_params['OR'])) {
         $and_condition['OR'] = $where_params['OR'];
         unset($where_params['OR']);
     }
     if (isset($where_params['Datetime.DTT_EVT_end'])) {
         $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
         unset($where_params['Datetime.DTT_EVT_end']);
     }
     if (isset($where_params['Datetime.DTT_EVT_start'])) {
         $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
         unset($where_params['Datetime.DTT_EVT_start']);
     }
     //merge remaining $where params with the and conditions.
     $and_condtion = array_merge($and_condition, $where_params);
     $where_params['AND'] = $and_condition;
     $query_params[0] = $where_params;
     // don't use $query_params with count() because we don't want to include additional query clauses like "GROUP BY"
     return $count ? $this->count(array($where_params), 'EVT_ID', true) : $this->get_all($query_params);
 }
 /**
  * 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);
 }
 /**
  * return the datetime object for a given datetime ID
  *
  * @since 4.3.0
  *
  * @param int $DTT_ID the datetime id for the datetime to attempt to retrieve
  *
  * @return mixed null|EE_Datetime
  */
 public function get_object_by_id($DTT_ID)
 {
     return EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
 }
        global $post;
        //Debug
        //d( $post );
        //Create the event link
        $button_text = !isset($button_text) ? __('Register Now!', 'event_espresso') : $button_text;
        $alt_button_text = !isset($alt_button_text) ? __('View Details', 'event_espresso') : $alt_button_text;
        //For alternate registration pages
        $external_url = $post->EE_Event->external_url();
        $button_text = !empty($external_url) ? $alt_button_text : $button_text;
        $registration_url = !empty($external_url) ? $post->EE_Event->external_url() : $post->EE_Event->get_permalink();
        $feature_image_url = $post->EE_Event->feature_image_url();
        if (!isset($default_image) || $default_image == '') {
            $default_image = EE_GRID_TEMPLATE_URL . '/images/default.jpg';
        }
        $image = !empty($feature_image_url) ? $feature_image_url : $default_image;
        $datetimes = EEM_Datetime::instance()->get_datetimes_for_event_ordered_by_start_time($post->ID, $show_expired, false, 1);
        $datetime = end($datetimes);
        $startdate = date_i18n($date_format . ' ' . $time_format, strtotime($datetime->start_date_and_time('Y-m-d', 'H:i:s')));
        ?>


		<div class="ee_grid_box item">
                <a id="a_register_link-<?php 
        echo $post->ID;
        ?>
" href="<?php 
        echo $registration_url;
        ?>
" class="darken">
                    <img src="<?php 
        echo $image;
 /**
  * This method verifies whether the user can checkin for the given datetime considering the max uses value set on the ticket.
  *
  * To do this,  a query is done to get the count of the datetime records already checked into.  If the datetime given does
  * not have a check-in record and checking in for that datetime will exceed the allowed uses, then return false.  Otherwise return true.
  *
  * @param int | EE_Datetime  $DTT_OR_ID  The datetime the registration is being checked against
  * @return bool   true means can checkin.  false means cannot checkin.
  */
 public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
 {
     $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
     if (!$DTT_ID) {
         return false;
     }
     $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
     // if max uses is not set or equals infinity then return true cause its not a factor for whether user can check-in
     // or not.
     if (!$max_uses || $max_uses === EE_INF) {
         return true;
     }
     //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
     //go ahead and toggle.
     if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
         return true;
     }
     //made it here so the last check is whether the number of checkins per unique datetime on this registration
     //disallows further check-ins.
     $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(array('REG_ID' => $this->ID(), 'CHK_in' => true)), 'DTT_ID', true);
     // checkins have already reached their max number of uses
     // so registrant can NOT checkin
     if ($count_unique_dtt_checkins >= $max_uses) {
         EE_Error::add_error(__('Check-in denied because number of datetime uses for the ticket has been reached or exceeded.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     return true;
 }
 /**
  * 	posts_orderby
  *
  * @access 	public
  * @param 	string $SQL
  * @param 	WP_Query $wp_query
  * @return 	string
  */
 public function posts_orderby($SQL, WP_Query $wp_query)
 {
     if ($wp_query instanceof WP_Query && ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy)) {
         $SQL = EEM_Datetime::instance()->table() . '.DTT_EVT_start ASC';
     }
     return $SQL;
 }
 /**
  * get total number of events this month
  *
  * @access public
  * @return int
  */
 public function total_events_this_month()
 {
     //Dates
     $this_year_r = date('Y');
     $this_month_r = date('m');
     $days_this_month = date('t');
     $start = EEM_Datetime::instance()->convert_datetime_for_query('DTT_EVT_start', $this_year_r . '-' . $this_month_r . '-01 00:00:00', 'Y-m-d H:i:s', 'UTC');
     $end = EEM_Datetime::instance()->convert_datetime_for_query('DTT_EVT_start', $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59', 'Y-m-d H:i:s', 'UTC');
     $where = array('Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)));
     $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
     return $count;
 }
 /**
  *    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;
 }
 public function test_get_dtt_months_and_years()
 {
     //setup some dates we'll use for testing with.
     $timezone = new DateTimeZone('America/Toronto');
     $upcoming_start_date = new DateTime("now +2hours", $timezone);
     $past_start_date = new DateTime("now -2days", $timezone);
     $current_end_date = new DateTime("now +2days", $timezone);
     $current = new DateTime("now", $timezone);
     $formats = array('Y-d-m', 'h:i a');
     $full_format = implode(' ', $formats);
     //setup some datetimes to attach to events.
     $datetimes = array('expired_datetime' => $this->factory->datetime->create(array('DTT_EVT_start' => $past_start_date->format($full_format), 'DTT_EVT_end' => $past_start_date->format($full_format), 'timezone' => 'America/Toronto', 'formats' => $formats)), 'upcoming_datetime' => $this->factory->datetime->create(array('DTT_EVT_start' => $upcoming_start_date->format($full_format), 'DTT_EVT_end' => $upcoming_start_date->format($full_format), 'timezone' => 'America/Toronto', 'formats' => $formats)), 'active_datetime' => $this->factory->datetime->create(array('DTT_EVT_start' => $current->sub(new DateInterval("PT2H"))->format($full_format), 'DTT_EVT_end' => $current_end_date->add(new DateInterval("PT2H"))->format($full_format), 'timezone' => 'America/Toronto', 'formats' => $formats)), 'sold_out_datetime' => $this->factory->datetime->create(array('DTT_EVT_start' => $upcoming_start_date->format($full_format), 'DTT_EVT_end' => $upcoming_start_date->format($full_format), 'DTT_reg_limit' => 10, 'DTT_sold' => 10, 'timezone' => 'America/Toronto', 'formats' => $formats)), 'inactive_datetime' => $this->factory->datetime->create(array('DTT_EVT_start' => $current->format($full_format), 'DTT_EVT_end' => $current_end_date->format($full_format), 'timezone' => 'America/Toronto', 'formats' => $formats)));
     $events = $this->factory->event->create_many(5);
     //add datetimes to the events.
     $events[0]->_add_relation_to($datetimes['expired_datetime'], 'Datetime');
     $events[0]->save();
     $events[1]->_add_relation_to($datetimes['upcoming_datetime'], 'Datetime');
     $events[1]->save();
     $events[2]->_add_relation_to($datetimes['active_datetime'], 'Datetime');
     $events[2]->save();
     $events[3]->_add_relation_to($datetimes['sold_out_datetime'], 'Datetime');
     $events[3]->save();
     $events[4]->_add_relation_to($datetimes['inactive_datetime'], 'Datetime');
     $events[4]->save();
     foreach ($events as $index => $event) {
         if ($index !== 4) {
             $event->set('status', 'publish');
             $event->save();
         }
     }
     //run tests for various scenarios.
     foreach ($datetimes as $type => $datetime) {
         switch ($type) {
             case 'expired_datetime':
                 $dtts = EEM_Datetime::instance()->get_dtt_months_and_years(array(), 'expired');
                 $dtt = reset($dtts);
                 $this->assertEquals(1, count($dtts));
                 $this->assertEquals($past_start_date->format('Y'), $dtt->dtt_year);
                 $this->assertEquals($past_start_date->format('F'), $dtt->dtt_month);
                 break;
             case 'upcoming_datetime':
                 $dtts = EEM_Datetime::instance()->get_dtt_months_and_years(array(), 'upcoming');
                 $dtt = reset($dtts);
                 $this->assertEquals(1, count($dtts));
                 $this->assertEquals($upcoming_start_date->format('Y'), $dtt->dtt_year);
                 $this->assertEquals($upcoming_start_date->format('F'), $dtt->dtt_month);
                 break;
             case 'active_datetime':
                 $dtts = EEM_Datetime::instance()->get_dtt_months_and_years(array(), 'active');
                 $dtt = reset($dtts);
                 $this->assertEquals(1, count($dtts));
                 $this->assertEquals($current->format('Y'), $dtt->dtt_year);
                 $this->assertEquals($current->format('F'), $dtt->dtt_month);
                 break;
             case 'sold_out_datetime':
                 $dtts = EEM_Datetime::instance()->get_dtt_months_and_years(array(), 'upcoming');
                 $dtt = reset($dtts);
                 $this->assertEquals(1, count($dtts));
                 $this->assertEquals($upcoming_start_date->format('Y'), $dtt->dtt_year);
                 $this->assertEquals($upcoming_start_date->format('F'), $dtt->dtt_month);
                 break;
             case 'inactive_datetime':
                 $dtts = EEM_Datetime::instance()->get_dtt_months_and_years(array(), 'inactive');
                 $dtt = reset($dtts);
                 $this->assertEquals(1, count($dtts));
                 $this->assertEquals($current->format('Y'), $dtt->dtt_year);
                 $this->assertEquals($current->format('F'), $dtt->dtt_month);
                 break;
         }
     }
 }
 /**
  * This returns a wpdb->results 		Array of all DTT month and years matching the incoming query params and grouped by month and year.
  * @param  array $where_params 		Array of query_params as described in the comments for EEM_Base::get_all()
  * @param  string $evt_active_status 		A string representing the evt active status to filter the months by.
  * 		Can be:
  * 			- '' = no filter
  * 			- upcoming = Published events with at least one upcoming datetime.
  * 			- expired = Events with all datetimes expired.
  * 			- active = Events that are published and have at least one datetime that starts before now and ends after now.
  * 			- inactive = Events that are either not published.
  * @return wpdb results array
  */
 public function get_dtt_months_and_years($where_params, $evt_active_status = '')
 {
     switch ($evt_active_status) {
         case 'upcoming':
             $where_params['Event.status'] = 'publish';
             //if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
             if (isset($where_params['DTT_EVT_start'])) {
                 $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
             }
             $where_params['DTT_EVT_start'] = array('>', $this->current_time_for_query('DTT_EVT_start'));
             break;
         case 'expired':
             if (isset($where_params['Event.status'])) {
                 unset($where_params['Event.status']);
             }
             //get events to exclude
             $exclude_query[0] = array_merge($where_params, array('DTT_EVT_end' => array('>', $this->current_time_for_query('DTT_EVT_end'))));
             //first get all events that have datetimes where its not expired.
             $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Datetime.EVT_ID');
             $event_ids = array_keys($event_ids);
             if (isset($where_params['DTT_EVT_end'])) {
                 $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
             }
             $where_params['DTT_EVT_end'] = array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'));
             $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
             break;
         case 'active':
             $where_params['Event.status'] = 'publish';
             if (isset($where_params['DTT_EVT_start'])) {
                 $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
             }
             if (isset($where_params['Datetime.DTT_EVT_end'])) {
                 $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
             }
             $where_params['DTT_EVT_start'] = array('<', $this->current_time_for_query('DTT_EVT_start'));
             $where_params['DTT_EVT_end'] = array('>', $this->current_time_for_query('DTT_EVT_end'));
             break;
         case 'inactive':
             if (isset($where_params['Event.status'])) {
                 unset($where_params['Event.status']);
             }
             if (isset($where_params['OR'])) {
                 $where_params['AND']['OR'] = $where_params['OR'];
             }
             if (isset($where_params['DTT_EVT_end'])) {
                 $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
                 unset($where_params['DTT_EVT_end']);
             }
             if (isset($where_params['DTT_EVT_start'])) {
                 $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
                 unset($where_params['DTT_EVT_start']);
             }
             $where_params['AND']['Event.status'] = array('!=', 'publish');
             break;
     }
     $query_params[0] = $where_params;
     $query_params['group_by'] = array('dtt_year', 'dtt_month');
     $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
     $columns_to_select = array('dtt_year' => array('YEAR(DTT_EVT_start)', '%s'), 'dtt_month' => array('MONTHNAME(DTT_EVT_start)', '%s'));
     return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
 }
 /**
  *    _set_initial_ticket_datetime_availability
  *
  * @access 	private
  * @param 	EE_Ticket $ticket
  * @return 	int
  */
 private static function _set_initial_ticket_datetime_availability(EE_Ticket $ticket)
 {
     // first, get all of the datetimes that are available to this ticket
     $datetimes = $ticket->get_many_related('Datetime', array(array('DTT_EVT_end' => array('>=', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'))), 'order_by' => array('DTT_EVT_start' => 'ASC')));
     if (!empty($datetimes)) {
         // now loop thru all of the datetimes
         foreach ($datetimes as $datetime) {
             if ($datetime instanceof EE_Datetime) {
                 // the number of spaces available for the datetime without considering individual ticket quantities
                 $spaces_remaining = $datetime->spaces_remaining();
                 // save the total available spaces ( the lesser of the ticket qty minus the number of tickets sold or the datetime spaces remaining) to this ticket using the datetime ID as the key
                 self::$_available_spaces['tickets'][$ticket->ID()][$datetime->ID()] = min($ticket->qty() - $ticket->sold(), $spaces_remaining);
                 // if the remaining spaces for this datetime is already set, then compare that against the datetime spaces remaining, and take the lowest number,
                 // else just take the datetime spaces remaining, and assign to the datetimes array
                 self::$_available_spaces['datetimes'][$datetime->ID()] = isset(self::$_available_spaces['datetimes'][$datetime->ID()]) ? min(self::$_available_spaces['datetimes'][$datetime->ID()], $spaces_remaining) : $spaces_remaining;
             }
         }
     }
 }
 /**
  * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
  * @access protected
  * @return void
  */
 protected function _registration_checkin_list_table()
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     $reg_id = isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : null;
     $reg = EEM_Registration::instance()->get_one_by_ID($reg_id);
     $this->_admin_page_title .= $this->get_action_link_or_button('new_registration', 'add-registrant', array('event_id' => $reg->event_ID()), 'add-new-h2');
     $legend_items = array('checkin' => array('class' => 'ee-icon ee-icon-check-in', 'desc' => __('This indicates the attendee has been checked in', 'event_espresso')), 'checkout' => array('class' => 'ee-icon ee-icon-check-out', 'desc' => __('This indicates the attendee has been checked out', 'event_espresso')));
     $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
     $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : NULL;
     $go_back_url = !empty($reg_id) ? EE_Admin_Page::add_query_args_and_nonce(array('action' => 'event_registrations', 'event_id' => EEM_Registration::instance()->get_one_by_ID($reg_id)->get_first_related('Event')->ID(), 'DTT_ID' => $dtt_id), $this->_admin_base_url) : '';
     $this->_template_args['before_list_table'] = !empty($reg_id) && !empty($dtt_id) ? '<h2>' . sprintf(__("%s's check in records for %s at the event, %s", 'event_espresso'), '<span id="checkin-attendee-name">' . EEM_Registration::instance()->get_one_by_ID($reg_id)->get_first_related('Attendee')->full_name() . '</span>', '<span id="checkin-dtt"><a href="' . $go_back_url . '">' . EEM_Datetime::instance()->get_one_by_ID($dtt_id)->start_date_and_time() . ' - ' . EEM_Datetime::instance()->get_one_by_ID($dtt_id)->end_date_and_time() . '</a></span>', '<span id="checkin-event-name">' . EEM_Datetime::instance()->get_one_by_ID($dtt_id)->get_first_related('Event')->get('EVT_name') . '</span>') . '</h2>' : '';
     $this->_template_args['list_table_hidden_fields'] = !empty($reg_id) ? '<input type="hidden" name="_REGID" value="' . $reg_id . '">' : '';
     $this->_template_args['list_table_hidden_fields'] .= !empty($dtt_id) ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
     $this->display_admin_list_table_page_with_no_sidebar();
 }
 /**
  * Get the logical active status in a hierarchical order for all the datetimes.  Note
  *
  * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
  * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
  * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
  * the event is considered expired.
  *
  * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
  * set on the EVENT when it is not published and thus is done
  *
  * @param bool $reset
  *
  * @return bool | string - based on EE_Datetime active constants or FALSE if error.
  */
 public function get_active_status($reset = false)
 {
     // if the active status has already been set, then just use that value (unless we are resetting it)
     if (!empty($this->_active_status) && !$reset) {
         return $this->_active_status;
     }
     //first check if event id is present on this object
     if (!$this->ID()) {
         return false;
     }
     $where_params_for_event = array(array('EVT_ID' => $this->ID()));
     //if event is published:
     if ($this->status() === 'publish') {
         //active?
         if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
             $this->_active_status = EE_Datetime::active;
         } else {
             //upcoming?
             if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
                 $this->_active_status = EE_Datetime::upcoming;
             } else {
                 //expired?
                 if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0) {
                     $this->_active_status = EE_Datetime::expired;
                 } else {
                     //it would be odd if things make it this far because it basically means there are no datetime's
                     //attached to the event.  So in this case it will just be considered inactive.
                     $this->_active_status = EE_Datetime::inactive;
                 }
             }
         }
     } else {
         //the event is not published, so let's just set it's active status according to its' post status
         switch ($this->status()) {
             case EEM_Event::sold_out:
                 $this->_active_status = EE_Datetime::sold_out;
                 break;
             case EEM_Event::cancelled:
                 $this->_active_status = EE_Datetime::cancelled;
                 break;
             case EEM_Event::postponed:
                 $this->_active_status = EE_Datetime::postponed;
                 break;
             default:
                 $this->_active_status = EE_Datetime::inactive;
         }
     }
     return $this->_active_status;
 }
 /**
  * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
  *
  * @param  array $stati_to_include        If included you can restrict the statuses we return counts for by including the stati
  *                               you want counts for as values in the array.  An empty array returns counts for all valid
  *                               stati.
  * @param  array  $query_params  If included can be used to refine the conditions for returning the count (i.e. only for
  *                               Datetimes connected to a specific event, or specific ticket.
  *
  * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The stati used as index keys are:
  *                EE_Datetime::active
  *                EE_Datetime::upcoming
  *                EE_Datetime::expired
  */
 public function get_datetime_counts_by_status($stati_to_include = array(), $query_params = array())
 {
     //only accept where conditions for this query.
     $_where = isset($query_params[0]) ? $query_params[0] : array();
     $status_query_args = array(EE_Datetime::active => array_merge($_where, array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))), EE_Datetime::upcoming => array_merge($_where, array('DTT_EVT_start' => array('>', time()))), EE_Datetime::expired => array_merge($_where, array('DTT_EVT_end' => array('<', time()))));
     if (!empty($stati_to_include)) {
         foreach (array_keys($status_query_args) as $status) {
             if (!in_array($status, $stati_to_include)) {
                 unset($status_query_args[$status]);
             }
         }
     }
     //loop through and query counts for each stati.
     $status_query_results = array();
     foreach ($status_query_args as $status => $status_where_conditions) {
         $status_query_results[$status] = EEM_Datetime::count(array($status_where_conditions), 'DTT_ID', true);
     }
     return $status_query_results;
 }
 /**
  * 	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);
 }
 /**
  * Gets the total number of tickets available at a particular datetime (does
  * NOT take int account the datetime's spaces available)
  * @param int $DTT_ID
  * @param array $query_params
  * @return int
  */
 public function sum_tickets_currently_available_at_datetime($DTT_ID, $query_params = array())
 {
     return EEM_Datetime::instance()->sum_tickets_currently_available_at_datetime($DTT_ID, $query_params);
 }
 /**
  * Export a custom CSV of registration info including: A bunch of the reg fields, the time of the event, the price name,
  * and the questions associated with the registrations
  * @param int $event_id
  */
 function report_registrations_for_event($event_id = NULL)
 {
     $reg_fields_to_include = array('TXN_ID', 'ATT_ID', 'REG_ID', 'REG_date', 'REG_code', 'REG_count', 'REG_final_price');
     $att_fields_to_include = array('ATT_fname', 'ATT_lname', 'ATT_email', 'ATT_address', 'ATT_address2', 'ATT_city', 'STA_ID', 'CNT_ISO', 'ATT_zip', 'ATT_phone');
     $registrations_csv_ready_array = array();
     $reg_model = EE_Registry::instance()->load_model('Registration');
     $query_params = apply_filters('FHEE__EE_Export__report_registration_for_event', array(array('OR' => array('Transaction.STS_ID' => array('NOT IN', array(EEM_Transaction::failed_status_code, EEM_Transaction::abandoned_status_code)), 'STS_ID' => EEM_Registration::status_id_approved), 'Ticket.TKT_deleted' => array('IN', array(true, false))), 'order_by' => array('Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'), 'force_join' => array('Transaction', 'Ticket', 'Attendee'), 'caps' => EEM_Base::caps_read_admin), $event_id);
     if ($event_id) {
         $query_params[0]['EVT_ID'] = $event_id;
     } else {
         $query_params['force_join'][] = 'Event';
     }
     $registration_rows = $reg_model->get_all_wpdb_results($query_params);
     //get all questions which relate to someone in this group
     $registration_ids = array();
     foreach ($registration_rows as $reg_row) {
         $registration_ids[] = intval($reg_row['Registration.REG_ID']);
     }
     //		EEM_Question::instance()->show_next_x_db_queries();
     $questions_for_these_regs_rows = EEM_Question::instance()->get_all_wpdb_results(array(array('Answer.REG_ID' => array('IN', $registration_ids))));
     foreach ($registration_rows as $reg_row) {
         if (is_array($reg_row)) {
             $reg_csv_array = array();
             if (!$event_id) {
                 //get the event's name and Id
                 $reg_csv_array[__('Event', 'event_espresso')] = sprintf(__('%1$s (%2$s)', 'event_espresso'), $this->_prepare_value_from_db_for_display(EEM_Event::instance(), 'EVT_name', $reg_row['Event_CPT.post_title']), $reg_row['Event_CPT.ID']);
             }
             $is_primary_reg = $reg_row['Registration.REG_count'] == '1' ? true : false;
             /*@var $reg_row EE_Registration */
             foreach ($reg_fields_to_include as $field_name) {
                 $field = $reg_model->field_settings_for($field_name);
                 if ($field_name == 'REG_final_price') {
                     $value = $this->_prepare_value_from_db_for_display($reg_model, $field_name, $reg_row['Registration.REG_final_price'], 'localized_float');
                 } elseif ($field_name == 'REG_count') {
                     $value = sprintf(__('%s of %s', 'event_espresso'), $this->_prepare_value_from_db_for_display($reg_model, 'REG_count', $reg_row['Registration.REG_count']), $this->_prepare_value_from_db_for_display($reg_model, 'REG_group_size', $reg_row['Registration.REG_group_size']));
                 } elseif ($field_name == 'REG_date') {
                     $value = $this->_prepare_value_from_db_for_display($reg_model, $field_name, $reg_row['Registration.REG_date'], 'no_html');
                 } else {
                     $value = $this->_prepare_value_from_db_for_display($reg_model, $field_name, $reg_row[$field->get_qualified_column()]);
                 }
                 $reg_csv_array[$this->_get_column_name_for_field($field)] = $value;
                 if ($field_name == 'REG_final_price') {
                     //add a column named Currency after the final price
                     $reg_csv_array[__("Currency", "event_espresso")] = EE_Config::instance()->currency->code;
                 }
             }
             //get pretty status
             $stati = EEM_Status::instance()->localized_status(array($reg_row['Registration.STS_ID'] => __('unknown', 'event_espresso'), $reg_row['TransactionTable.STS_ID'] => __('unknown', 'event_espresso')), FALSE, 'sentence');
             $reg_csv_array[__("Registration Status", 'event_espresso')] = $stati[$reg_row['Registration.STS_ID']];
             //get pretty trnasaction status
             $reg_csv_array[__("Transaction Status", 'event_espresso')] = $stati[$reg_row['TransactionTable.STS_ID']];
             $reg_csv_array[__('Transaction Amount Due', 'event_espresso')] = $is_primary_reg ? $this->_prepare_value_from_db_for_display(EEM_Transaction::instance(), 'TXN_total', $reg_row['TransactionTable.TXN_total'], 'localized_float') : '0.00';
             $reg_csv_array[__('Amount Paid', 'event_espresso')] = $is_primary_reg ? $this->_prepare_value_from_db_for_display(EEM_Transaction::instance(), 'TXN_paid', $reg_row['TransactionTable.TXN_paid'], 'localized_float') : '0.00';
             $payment_methods = array();
             $gateway_txn_ids_etc = array();
             $payment_times = array();
             if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) {
                 $payments_info = EEM_Payment::instance()->get_all_wpdb_results(array(array('TXN_ID' => $reg_row['TransactionTable.TXN_ID'], 'STS_ID' => EEM_Payment::status_id_approved), 'force_join' => array('Payment_Method')), ARRAY_A, 'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time');
                 foreach ($payments_info as $payment_method_and_gateway_txn_id) {
                     $payment_methods[] = isset($payment_method_and_gateway_txn_id['name']) ? $payment_method_and_gateway_txn_id['name'] : __('Unknown', 'event_espresso');
                     $gateway_txn_ids_etc[] = isset($payment_method_and_gateway_txn_id['gateway_txn_id']) ? $payment_method_and_gateway_txn_id['gateway_txn_id'] : '';
                     $payment_times[] = isset($payment_method_and_gateway_txn_id['payment_time']) ? $payment_method_and_gateway_txn_id['payment_time'] : '';
                 }
             }
             $reg_csv_array[__('Payment Date(s)', 'event_espresso')] = implode(',', $payment_times);
             $reg_csv_array[__('Payment Method(s)', 'event_espresso')] = implode(",", $payment_methods);
             $reg_csv_array[__('Gateway Transaction ID(s)', 'event_espresso')] = implode(',', $gateway_txn_ids_etc);
             //get whether or not the user has checked in
             $reg_csv_array[__("Check-Ins", "event_espresso")] = $reg_model->count_related($reg_row['Registration.REG_ID'], 'Checkin');
             //get ticket of registration and its price
             $ticket_model = EE_Registry::instance()->load_model('Ticket');
             if ($reg_row['Ticket.TKT_ID']) {
                 $ticket_name = $this->_prepare_value_from_db_for_display($ticket_model, 'TKT_name', $reg_row['Ticket.TKT_name']);
                 $datetimes_strings = array();
                 foreach (EEM_Datetime::instance()->get_all_wpdb_results(array(array('Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']), 'order_by' => array('DTT_EVT_start' => 'ASC'), 'default_where_conditions' => 'none')) as $datetime) {
                     $datetimes_strings[] = $this->_prepare_value_from_db_for_display(EEM_Datetime::instance(), 'DTT_EVT_start', $datetime['Datetime.DTT_EVT_start']);
                 }
             } else {
                 $ticket_name = __('Unknown', 'event_espresso');
                 $datetimes_strings = array(__('Unknown', 'event_espresso'));
             }
             $reg_csv_array[$ticket_model->field_settings_for('TKT_name')->get_nicename()] = $ticket_name;
             $reg_csv_array[__("Datetimes of Ticket", "event_espresso")] = implode(", ", $datetimes_strings);
             //get datetime(s) of registration
             //add attendee columns
             foreach ($att_fields_to_include as $att_field_name) {
                 $field_obj = EEM_Attendee::instance()->field_settings_for($att_field_name);
                 if ($reg_row['Attendee_CPT.ID']) {
                     if ($att_field_name == 'STA_ID') {
                         $value = EEM_State::instance()->get_var(array(array('STA_ID' => $reg_row['Attendee_Meta.STA_ID'])), 'STA_name');
                     } elseif ($att_field_name == 'CNT_ISO') {
                         $value = EEM_Country::instance()->get_var(array(array('CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO'])), 'CNT_name');
                     } else {
                         $value = $this->_prepare_value_from_db_for_display(EEM_Attendee::instance(), $att_field_name, $reg_row[$field_obj->get_qualified_column()]);
                     }
                 } else {
                     $value = '';
                 }
                 $reg_csv_array[$this->_get_column_name_for_field($field_obj)] = $value;
             }
             //make sure each registration has the same questions in the same order
             foreach ($questions_for_these_regs_rows as $question_row) {
                 if (!isset($reg_csv_array[$question_row['Question.QST_admin_label']])) {
                     $reg_csv_array[$question_row['Question.QST_admin_label']] = null;
                 }
             }
             //now fill out the questions THEY answered
             foreach (EEM_Answer::instance()->get_all_wpdb_results(array(array('REG_ID' => $reg_row['Registration.REG_ID']), 'force_join' => array('Question'))) as $answer_row) {
                 /* @var $answer EE_Answer */
                 if ($answer_row['Question.QST_ID']) {
                     $question_label = $this->_prepare_value_from_db_for_display(EEM_Question::instance(), 'QST_admin_label', $answer_row['Question.QST_admin_label']);
                 } else {
                     $question_label = sprintf(__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']);
                 }
                 if (isset($answer_row['Question.QST_type']) && $answer_row['Question.QST_type'] == EEM_Question::QST_type_state) {
                     $reg_csv_array[$question_label] = EEM_State::instance()->get_state_name_by_ID($answer_row['Answer.ANS_value']);
                 } else {
                     $reg_csv_array[$question_label] = $this->_prepare_value_from_db_for_display(EEM_Answer::instance(), 'ANS_value', $answer_row['Answer.ANS_value']);
                 }
             }
             $registrations_csv_ready_array[] = apply_filters('FHEE__EE_Export__report_registrations__reg_csv_array', $reg_csv_array, $reg_row);
         }
     }
     //if we couldn't export anything, we want to at least show the column headers
     if (empty($registrations_csv_ready_array)) {
         $reg_csv_array = array();
         $model_and_fields_to_include = array('Registration' => $reg_fields_to_include, 'Attendee' => $att_fields_to_include);
         foreach ($model_and_fields_to_include as $model_name => $field_list) {
             $model = EE_Registry::instance()->load_model($model_name);
             foreach ($field_list as $field_name) {
                 $field = $model->field_settings_for($field_name);
                 $reg_csv_array[$this->_get_column_name_for_field($field)] = null;
                 //$registration->get($field->get_name());
             }
         }
         $registrations_csv_ready_array[] = $reg_csv_array;
     }
     if ($event_id) {
         $event_slug = EEM_Event::instance()->get_var(array(array('EVT_ID' => $event_id)), 'EVT_slug');
         if (!$event_slug) {
             $event_slug = __('unknown', 'event_espresso');
         }
     } else {
         $event_slug = __('all', 'event_espresso');
     }
     $filename = sprintf("registrations-for-%s", $event_slug);
     $handle = $this->EE_CSV->begin_sending_csv($filename);
     $this->EE_CSV->write_data_array_to_csv($handle, $registrations_csv_ready_array);
     $this->EE_CSV->end_sending_csv($handle);
 }
 /**
  * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
  *
  * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
  * @param bool   $check_approved   This is used to indicate whether the caller wants can_checkin to also consider registration status as well as datetime access.
  *
  * @return bool
  */
 public function can_checkin($DTT_OR_ID, $check_approved = TRUE)
 {
     $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
     //first check registration status
     if ($check_approved && !$this->is_approved()) {
         return false;
     }
     //is there a datetime ticket that matches this dtt_ID?
     return EEM_Datetime_Ticket::instance()->exists(array(array('TKT_ID' => $this->get('TKT_ID'), 'DTT_ID' => $DTT_ID)));
 }
 /**
  * Returns query args for use in model queries on the
  * EEM model related to scope.  Note this also should
  * consider any filters present
  *
  * @since 1.0.0
  *
  * @return array
  */
 public function get_query_args()
 {
     EE_Registry::instance()->load_helper('DTT_Helper');
     //$month_increment = apply_filters( 'FHEE__EE_Promotion_Event_Scope__get_query_args__month_increment', 1 );
     //check for any existing dtt queries
     $DTT_EVT_start = !empty($_REQUEST['EVT_start_date_filter']) ? $_REQUEST['EVT_start_date_filter'] : null;
     $DTT_EVT_end = !empty($_REQUEST['EVT_end_date_filter']) ? $_REQUEST['EVT_end_date_filter'] : null;
     $_where = array('status' => array('NOT IN', array(EEM_Event::cancelled, 'trash')));
     if (!empty($DTT_EVT_start)) {
         $_where['Datetime.DTT_EVT_start'] = array('>', EEM_datetime::instance()->convert_datetime_for_query('DTT_EVT_start', $DTT_EVT_start, 'Y-m-d g:i a'));
     }
     if (!empty($DTT_EVT_end)) {
         $_where['Datetime.DTT_EVT_end'] = array('<', EEM_Datetime::instance()->convert_datetime_for_query('DTT_EVT_end', $DTT_EVT_end, 'Y-m-d g:i a'));
     }
     //exclude expired events by default unless include_expiry is checked.
     if (!isset($_REQUEST['include_expired_events_filter'])) {
         $_where['Datetime.DTT_EVT_end**exclude_expired_events_query'] = array('>', time());
     }
     //category filters?
     if (!empty($_REQUEST['EVT_CAT_ID'])) {
         $_where['Term_Taxonomy.term_id'] = $_REQUEST['EVT_CAT_ID'];
     }
     //event title?
     if (!empty($_REQUEST['EVT_title_filter'])) {
         $_where['EVT_name'] = array('LIKE', '%' . $_REQUEST['EVT_title_filter'] . '%');
     }
     $orderby = !empty($_REQUEST['PRO_scope_sort']) ? $_REQUEST['PRO_scope_sort'] : 'DESC';
     $query_params = array('0' => $_where, 'order_by' => array('EVT_created' => $orderby), 'group_by' => 'EVT_ID');
     //apply caps
     if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events_for_promotions')) {
         $query_params = EEM_Event::instance()->alter_query_params_to_only_include_mine($query_params);
     }
     return $query_params;
 }
 public function get_events($per_page = 10, $current_page = 1, $count = FALSE)
 {
     $EEME = $this->_event_model();
     $offset = ($current_page - 1) * $per_page;
     $limit = $count ? NULL : $offset . ',' . $per_page;
     $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
     $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
     if (isset($this->_req_data['month_range'])) {
         $pieces = explode(' ', $this->_req_data['month_range'], 3);
         $month_r = !empty($pieces[0]) ? date('m', strtotime($pieces[0])) : '';
         $year_r = !empty($pieces[1]) ? $pieces[1] : '';
     }
     $where = array();
     $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : NULL;
     //determine what post_status our condition will have for the query.
     switch ($status) {
         case 'month':
         case 'today':
         case NULL:
         case 'all':
             break;
         case 'draft':
             $where['status'] = array('IN', array('draft', 'auto-draft'));
             break;
         default:
             $where['status'] = $status;
     }
     //categories?
     $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0 ? $this->_req_data['EVT_CAT'] : NULL;
     if (!empty($category)) {
         $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
         $where['Term_Taxonomy.term_id'] = $category;
     }
     //date where conditions
     $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
     if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
         $DateTime = new DateTime($year_r . '-' . $month_r . '-01 00:00:00', new DateTimeZone(EEM_Datetime::instance()->get_timezone()));
         $start = $DateTime->format(implode(' ', $start_formats));
         $end = $DateTime->setDate($year_r, $month_r, $DateTime->format('t'))->setTime(23, 59, 59)->format(implode(' ', $start_formats));
         $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
     } else {
         if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
             $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
             $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
             $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
         } else {
             if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
                 $now = date('Y-m-01');
                 $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
                 $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
                 $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))->setTime(23, 59, 59)->format(implode(' ', $start_formats));
                 $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
             }
         }
     }
     if (!EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
         $where['EVT_wp_user'] = get_current_user_id();
     } else {
         if (!isset($where['status'])) {
             if (!EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
                 $where['OR'] = array('status*restrict_private' => array('!=', 'private'), 'AND' => array('status*inclusive' => array('=', 'private'), 'EVT_wp_user' => get_current_user_id()));
             }
         }
     }
     if (isset($this->_req_data['EVT_wp_user'])) {
         if ($this->_req_data['EVT_wp_user'] != get_current_user_id() && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
             $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
         }
     }
     //search query handling
     if (isset($this->_req_data['s'])) {
         $search_string = '%' . $this->_req_data['s'] . '%';
         $where['OR'] = array('EVT_name' => array('LIKE', $search_string), 'EVT_desc' => array('LIKE', $search_string), 'EVT_short_desc' => array('LIKE', $search_string));
     }
     $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
     $query_params = apply_filters('FHEE__Events_Admin_Page__get_events__query_params', array($where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $order, 'group_by' => 'EVT_ID'), $this->_req_data);
     //let's first check if we have special requests coming in.
     if (isset($this->_req_data['active_status'])) {
         switch ($this->_req_data['active_status']) {
             case 'upcoming':
                 return $EEME->get_upcoming_events($query_params, $count);
                 break;
             case 'expired':
                 return $EEME->get_expired_events($query_params, $count);
                 break;
             case 'active':
                 return $EEME->get_active_events($query_params, $count);
                 break;
             case 'inactive':
                 return $EEME->get_inactive_events($query_params, $count);
                 break;
         }
     }
     $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
     return $events;
 }