/**
  *    update_espresso_config
  *
  * @access   public
  * @param   bool $add_success
  * @param   bool $add_error
  * @return   bool
  */
 public function update_espresso_config($add_success = false, $add_error = true)
 {
     // don't allow config updates during WP heartbeats
     if (\EE_Registry::instance()->REQ->get('action', '') === 'heartbeat') {
         return false;
     }
     // commented out the following re: https://events.codebasehq.com/projects/event-espresso/tickets/8197
     //$clone = clone( self::$_instance );
     //self::$_instance = NULL;
     do_action('AHEE__EE_Config__update_espresso_config__begin', $this);
     $this->_reset_espresso_addon_config();
     // hook into update_option because that happens AFTER the ( $value === $old_value ) conditional
     // but BEFORE the actual update occurs
     add_action('update_option', array($this, 'double_check_config_comparison'), 1, 3);
     // now update "ee_config"
     $saved = update_option(EE_Config::OPTION_NAME, $this);
     EE_Config::log(EE_Config::OPTION_NAME);
     // if not saved... check if the hook we just added still exists;
     // if it does, it means one of two things:
     // 		that update_option bailed at the ( $value === $old_value ) conditional,
     //		 or...
     // 		the db update query returned 0 rows affected
     // 		(probably because the data  value was the same from it's perspective)
     // so the existence of the hook means that a negative result from update_option is NOT an error,
     // but just means no update occurred, so don't display an error to the user.
     // BUT... if update_option returns FALSE, AND the hook is missing,
     // then it means that something truly went wrong
     $saved = !$saved ? has_action('update_option', array($this, 'double_check_config_comparison')) : $saved;
     // remove our action since we don't want it in the system anymore
     remove_action('update_option', array($this, 'double_check_config_comparison'), 1);
     do_action('AHEE__EE_Config__update_espresso_config__end', $this, $saved);
     //self::$_instance = $clone;
     //unset( $clone );
     // if config remains the same or was updated successfully
     if ($saved) {
         if ($add_success) {
             EE_Error::add_success(__('The Event Espresso Configuration Settings have been successfully updated.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         }
         return true;
     } else {
         if ($add_error) {
             EE_Error::add_error(__('The Event Espresso Configuration Settings were not updated.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         }
         return false;
     }
 }
 /**
  * @resets all non-default session vars
  * @access public
  * @param array $data_to_reset
  * @param bool  $show_all_notices
  * @return TRUE on success, FALSE on fail
  */
 public function reset_data($data_to_reset = array(), $show_all_notices = FALSE)
 {
     // if $data_to_reset is not in an array, then put it in one
     if (!is_array($data_to_reset)) {
         $data_to_reset = array($data_to_reset);
     }
     // nothing ??? go home!
     if (empty($data_to_reset)) {
         EE_Error::add_error(__('No session data could be reset, because no session var name was provided.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return FALSE;
     }
     $return_value = TRUE;
     // since $data_to_reset is an array, cycle through the values
     foreach ($data_to_reset as $reset) {
         // first check to make sure it is a valid session var
         if (isset($this->_session_data[$reset])) {
             // then check to make sure it is not a default var
             if (!array_key_exists($reset, $this->_default_session_vars)) {
                 // remove session var
                 unset($this->_session_data[$reset]);
                 if ($show_all_notices) {
                     EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
                 }
                 $return_value = !isset($return_value) ? TRUE : $return_value;
             } else {
                 // yeeeeeeeeerrrrrrrrrrr OUT !!!!
                 if ($show_all_notices) {
                     EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
                 }
                 $return_value = FALSE;
             }
         } else {
             if ($show_all_notices) {
                 // oops! that session var does not exist!
                 EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.', 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
                 $return_value = FALSE;
             }
         }
     }
     // end of foreach
     return $return_value;
 }
 private function _insert_term($update = FALSE, $taxonomy = 'espresso_people_categories')
 {
     if ($taxonomy == 'espresso_people_categories') {
         $term_id = $update ? $this->_req_data['PER_CAT_ID'] : '';
     } else {
         $term_id = $update ? $this->_req_data['PER_TYPE_ID'] : '';
     }
     $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
     $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
     $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
     $term_args = array('name' => $category_name, 'description' => $category_desc, 'parent' => $category_parent);
     //was the category_identifier input disabled?
     if (isset($this->_req_data['category_identifier'])) {
         $term_args['slug'] = $this->_req_data['category_identifier'];
     }
     $insert_ids = $update ? wp_update_term($term_id, $taxonomy, $term_args) : wp_insert_term($category_name, $taxonomy, $term_args);
     if (!is_array($insert_ids)) {
         $msg = $taxonomy == 'espresso_people_categories' ? __('An error occurred and the category has not been saved to the database.', 'event_espresso') : __('An error occurred and the people type has not been saved to the database.', 'event_espresso');
         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
     } else {
         $term_id = $insert_ids['term_id'];
         $msg = $taxonomy == 'espresso_people_categories' ? sprintf(__('The category %s was successfuly saved', 'event_espresso'), $category_name) : sprintf(__('The people type %s was successfuly saved', 'event_espresso'), $category_name);
         EE_Error::add_success($msg);
     }
     return $term_id;
 }
 /**
  * 		process_gateway_selection()
  * 		@access public
  * 		@return 	mixed	array on success or FALSE on fail
  */
 public function process_gateway_selection()
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     $msg = $this->_EEM_Gateways->display_name() . __(' gateway selected.', 'event_espresso');
     EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
 }
 /**
  * This duplicates the attendee object for the given incoming registration id and attendee_id.
  * @return void
  */
 protected function _duplicate_attendee()
 {
     $action = !empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
     //verify we have necessary info
     if (empty($this->_req_data['_REG_ID'])) {
         EE_Error::add_error(__('Unable to create the contact for the registration because the required paramaters are not present (_REG_ID )', 'event_espresso'), __FILE__, __LINE__, __FUNCTION__);
         $query_args = array('action' => $action);
         $this->_redirect_after_action('', '', '', $query_args, TRUE);
     }
     //okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
     $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
     $attendee = $registration->attendee();
     //remove relation of existing attendee on registration
     $registration->_remove_relation_to($attendee, 'Attendee');
     //new attendee
     $new_attendee = clone $attendee;
     $new_attendee->set('ATT_ID', 0);
     $new_attendee->save();
     //add new attendee to reg
     $registration->_add_relation_to($new_attendee, 'Attendee');
     EE_Error::add_success(__('New Contact record created.  Now make any edits you wish to make for this contact.', 'event_espresso'));
     //redirect to edit page for attendee
     $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
     $this->_redirect_after_action('', '', '', $query_args, TRUE);
 }
 protected function _reset_capabilities()
 {
     EE_Registry::instance()->CAP->init_caps(true);
     EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.', 'event_espresso'));
     $this->_redirect_after_action(FALSE, '', '', array('action' => 'data_reset'), TRUE);
 }
 /**
  *	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;
     }
 }
 /**
  * 		registers a payment or refund made towards a transaction
  *		@access public
  *		@return void
  */
 public function apply_payments_or_refunds()
 {
     $return_data = FALSE;
     if (isset($this->_req_data['txn_admin_payment'])) {
         $payment = $this->_req_data['txn_admin_payment'];
         $payment['PAY_ID'] = $payment['PAY_ID'];
         // payments have a type value of 1 and refunds have a type value of -1
         $type = $payment['type'] < 0 ? -1 : 1;
         // if this is a refund
         if ($type == -1) {
             // remove negative sign from amount if it exists
             $payment['amount'] = abs($payment['amount']);
         }
         // so multiplying amount by type will give a positive value for payments, and negative values for refunds
         $amount = $payment['amount'] * $type;
         switch ($payment['method']) {
             case 'PP':
                 $payment['gateway'] = 'PayPal';
                 break;
             case 'CC':
                 $payment['gateway'] = 'Credit_Card';
                 break;
             case 'CHQ':
                 $payment['gateway'] = 'Cheque';
                 break;
             case 'CSH':
                 $payment['gateway'] = 'Cash';
                 $payment['txn_id_chq_nmbr'] = '';
                 break;
             case 'DB':
                 $payment['gateway'] = 'Debit';
                 $payment['gateway_response'] = '';
                 break;
             case 'BK':
                 $payment['gateway'] = 'Bank';
                 break;
             case 'IV':
                 $payment['gateway'] = 'Invoice';
                 break;
             case 'MO':
                 $payment['gateway'] = 'Money_Order';
         }
         $payment['gateway_response'] = '';
         //savea  the new payment
         $payment = EE_Payment::new_instance(array('TXN_ID' => $payment['TXN_ID'], 'STS_ID' => $payment['status'], 'PAY_timestamp' => $payment['date'], 'PAY_method' => $payment['method'], 'PAY_amount' => $amount, 'PAY_gateway' => $payment['gateway'], 'PAY_gateway_response' => $payment['gateway_response'], 'PAY_txn_id_chq_nmbr' => $payment['txn_id_chq_nmbr'], 'PAY_po_number' => $payment['po_number'], 'PAY_extra_accntng' => $payment['accounting'], 'PAY_via_admin' => true, 'PAY_details' => $payment, 'PAY_ID' => $payment['PAY_ID']));
         if (!$payment->save()) {
             $msg = __('An error occurred. The payment has not been processed succesfully.', 'event_espresso');
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
         }
         //update the transaction with this payment
         if ($payment->apply_payment_to_transaction()) {
             $msg = __('The payment has been processed succesfully.', 'event_espresso');
             EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
         } else {
             $msg = __('An error occurred. The payment was processed succesfully but the amount paid for the transaction was not updated.', 'event_espresso');
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
         }
         //prepare to render page
         $transaction = $payment->transaction();
         $this->_get_payment_status_array();
         $return_data['amount'] = $payment->amount();
         $return_data['total_paid'] = $transaction->paid();
         $return_data['txn_status'] = $transaction->status_ID();
         $return_data['pay_status'] = $payment->STS_ID();
         $return_data['PAY_ID'] = $payment->ID();
         $return_data['STS_ID'] = $payment->STS_ID();
         $return_data['status'] = self::$_pay_status[$payment->STS_ID()];
         $return_data['date'] = $payment->timestamp('Y-m-d', 'h:i a');
         $return_data['method'] = strtoupper($payment->method());
         $this->_get_active_gateways();
         $return_data['gateway'] = isset($this->_template_args['active_gateways'][$payment->gateway()]) ? $this->_template_args['active_gateways'][$payment->gateway()] : $payment->gateway();
         $return_data['gateway_response'] = $payment->gateway_response();
         $return_data['txn_id_chq_nmbr'] = $payment->txn_id_chq_nmbr();
         $return_data['po_number'] = $payment->po_number();
         $return_data['extra_accntng'] = $payment->extra_accntng();
         $this->_process_payment_notification($payment);
         if (isset($this->_req_data['txn_reg_status_change'])) {
             $this->_process_registration_status_change($transaction);
         }
     } else {
         $msg = __('An error occurred. The payment form data could not be loaded.', 'event_espresso');
         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
     }
     $notices = EE_Error::get_notices(FALSE, FALSE, FALSE);
     echo json_encode(array('return_data' => $return_data, 'success' => $notices['success'], 'errors' => $notices['errors']));
     die;
 }
 /**
  * this handles saving the settings for a messenger or message type
  * @return json success or fail message
  */
 public function save_settings()
 {
     if (!isset($this->_req_data['type'])) {
         EE_Error::add_error(__('Cannot save settings because type is unknown (messenger settings or messsage type settings?)', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         $this->_template_args['error'] = TRUE;
         $this->_return_json();
     }
     if ($this->_req_data['type'] == 'messenger') {
         $settings = $this->_req_data['messenger_settings'];
         //this should be an array.
         $messenger = $settings['messenger'];
         //let's setup the settings data
         foreach ($settings as $key => $value) {
             switch ($key) {
                 case 'messenger':
                     unset($settings['messenger']);
                     break;
                 case 'message_types':
                     if (isset($this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'])) {
                         foreach ($this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'] as $mt => $v) {
                             if (isset($settings['message_types'][$mt])) {
                                 $settings[$messenger . '-message_types'][$mt]['settings'] = isset($this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt]) ? $this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt] : array();
                             }
                         }
                     } else {
                         foreach ($value as $mt => $v) {
                             //let's see if this message type is already present and has settings.
                             $settings[$messenger . '-message_types'][$mt]['settings'] = array();
                         }
                     }
                     //k settings are set let's get rid of the message types index
                     unset($settings['message_types']);
                     break;
                 default:
                     $settings[$key] = $value;
                     break;
             }
         }
         $this->_active_messengers[$messenger]['settings'] = $settings;
     } else {
         if ($this->_req_data['type'] == 'message_type') {
             $settings = $this->_req_data['message_type_settings'];
             $messenger = $settings['messenger'];
             $message_type = $settings['message_type'];
             foreach ($settings as $key => $value) {
                 switch ($key) {
                     case 'messenger':
                         unset($settings['messenger']);
                         break;
                     case 'message_type':
                         unset($settings['message_type']);
                         break;
                     default:
                         $settings['settings'][$key] = $value;
                         unset($settings[$key]);
                         break;
                 }
             }
             $this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'][$message_type] = $settings;
         }
     }
     //okay we should have the data all setup.  Now we just update!
     $success = EEH_MSG_Template::update_active_messengers_in_db($this->_active_messengers);
     if ($success) {
         EE_Error::add_success(__('Settings updated', 'event_espresso'));
     } else {
         EE_Error::add_error(__('Settings did not get updated', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
     }
     $this->_template_args['success'] = $success;
     $this->_return_json();
 }
 /**
  * 		process_gateway_selection()
  * 		@access public
  * 		@return 	mixed	array on success or FALSE on fail
  */
 public function process_gateway_selection()
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     // set  billing inputs in the individual gateways plz
     $reg_page_billing_inputs = array();
     // allow others to edit post input array
     $reg_page_billing_inputs = $this->espresso_reg_page_billing_inputs();
     $reg_page_billing_inputs = apply_filters('FHEE__EE_Onsite_Gateway__process_gateway_selection__reg_page_billing_inputs', $reg_page_billing_inputs);
     //printr( $reg_page_billing_inputs, '$reg_page_billing_inputs  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
     // validate and sanitize	post data
     $reg_page_billing_inputs = EE_Registry::instance()->load_class('EE_Validate_and_Sanitize')->validate_and_sanitize_post_inputs($reg_page_billing_inputs);
     if ($reg_page_billing_inputs) {
         // add billing info to the session
         if (EE_Registry::instance()->SSN->set_session_data(array('billing_info' => $reg_page_billing_inputs))) {
             $msg = __('Billing information submitted successfully.', 'event_espresso');
             EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
         }
     }
 }
 protected function _reset_button_url()
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     $in_uploads = $this->_EEM_Gateways->is_in_uploads($this->_gateway_name);
     if (is_array($in_uploads) && $in_uploads[$this->_gateway_name]) {
         $button_url = EVENT_ESPRESSO_GATEWAY_URL . "/" . $this->_gateway_name . '/lib/' . $this->_button_base;
     } else {
         $button_url = $this->_btn_img;
     }
     $this->_payment_settings['button_url'] = $button_url;
     // change windows style filepaths to Unix style filepaths
     $this->_payment_settings['current_path'] = str_replace('\\', '/', $this->_path);
     if ($this->_EEM_Gateways->update_payment_settings($this->_gateway_name, $this->_payment_settings)) {
         $msg = sprintf(__('The %s button URL was reset.', 'event_espresso'), $this->_payment_settings['display_name']);
         EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
     } else {
         $msg = sprintf(__('An error occurred. The %s button URL was not reset.', 'event_espresso'), $this->_payment_settings['display_name']);
         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
     }
 }
 /**
  * 	update_config'
  *
  *  @access 	public
  *  @return 	boolean success
  */
 public function update_config($add_success = FALSE, $add_error = TRUE)
 {
     do_action('AHEE__EE_Network_Config__update_config__begin', $this);
     // compare existing settings with what's already saved'
     $saved_config = $this->get_config();
     // update
     $saved = $saved_config == $this ? TRUE : update_site_option('ee_network_config', $this);
     do_action('AHEE__EE_Network_Config__update_config__end', $this, $saved);
     // if config remains the same or was updated successfully
     if ($saved) {
         if ($add_success) {
             $msg = is_multisite() ? __('The Event Espresso Network Configuration Settings have been successfully updated.', 'event_espresso') : __('Extra Event Espresso Configuration settings were successfully updated.', 'event_espresso');
             EE_Error::add_success($msg);
         }
         return TRUE;
     } else {
         if ($add_error) {
             $msg = is_multisite() ? __('The Event Espresso Network Configuration Settings were not updated.', 'event_espresso') : __('Extra Event Espresso Network Configuration settings were not updated.', 'event_espresso');
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
         }
         return FALSE;
     }
 }
 /**
  * Deletes a single EE_Checkin row
  * @return void
  */
 protected function _delete_checkin_row()
 {
     $query_args = array('action' => 'registration_checkins', 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0, '_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0);
     if (!empty($this->_req_data['CHK_ID'])) {
         if (!EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
             EE_Error::add_error(__('Something went wrong and this check-in record was not deleted', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         } else {
             EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
         }
     } else {
         EE_Error::add_error(__('In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
     }
     $this->_redirect_after_action(FALSE, '', '', $query_args, TRUE);
 }
 /**
  *        remove all events from the event cart
  *
  * @access        public
  * @return        void
  */
 public function empty_event_cart()
 {
     $this->init();
     EED_Multi_Event_Registration::load_classes();
     // remove all unwanted records from the db
     if (EE_Registry::instance()->CART->delete_cart()) {
         // and clear the session too
         EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
         // reset cached cart
         EE_Registry::instance()->CART = EE_Cart::instance(null);
         if (apply_filters('FHEE__EED_Multi_Event_Registration__display_success_messages', false)) {
             EE_Error::add_success(sprintf(__('The %1$s was successfully emptied!', 'event_espresso'), EED_Multi_Event_Registration::$event_cart_name), __FILE__, __FUNCTION__, __LINE__);
         }
     } else {
         EE_Error::add_error(sprintf(__('The %1$s could not be emptied!', 'event_espresso'), EED_Multi_Event_Registration::$event_cart_name), __FILE__, __FUNCTION__, __LINE__);
     }
     $this->send_ajax_response(true, apply_filters('FHEE__EED_Multi_Event_Registration__empty_event_cart__redirect_url', EE_EVENTS_LIST_URL));
 }
 /**
  * delete_payment_and_update_transaction
  * Before deleting the selected payment, we fetch it's transaction,
  * then delete the payment, and update the transactions' amount paid.
  *
  * @param EE_Payment $payment
  * @return boolean
  * @throws \EE_Error
  */
 public function delete_payment_and_update_transaction(EE_Payment $payment)
 {
     // verify payment
     if (!$payment instanceof EE_Payment) {
         EE_Error::add_error(__('A valid Payment object was not received.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     if (!$this->delete_registration_payments_and_update_registrations($payment)) {
         return false;
     }
     if (!$payment->delete()) {
         EE_Error::add_error(__('The payment could not be deleted.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     $transaction = $payment->transaction();
     $TXN_status = $transaction->status_ID();
     if ($TXN_status === EEM_Transaction::abandoned_status_code || $TXN_status === EEM_Transaction::failed_status_code || $payment->amount() === 0) {
         EE_Error::add_success(__('The Payment was successfully deleted.', 'event_espresso'));
         return true;
     }
     //if this fails, that just means that the transaction didn't get its status changed and/or updated.
     //however the payment was still deleted.
     if (!$this->calculate_total_payments_and_update_status($transaction)) {
         EE_Error::add_attention(__('It appears that the Payment was deleted but no change was recorded for the Transaction for an unknown reason. Please verify that all data for this Transaction looks correct..', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return true;
     }
     EE_Error::add_success(__('The Payment was successfully deleted, and the Transaction has been updated accordingly.', 'event_espresso'));
     return true;
 }
 protected function _insert_or_update_question_group($new_question_group = TRUE)
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     $set_column_values = $this->_set_column_values_for($this->_question_group_model);
     if ($new_question_group) {
         $QSG_ID = $this->_question_group_model->insert($set_column_values);
         $success = $QSG_ID ? 1 : 0;
     } else {
         $QSG_ID = absint($this->_req_data['QSG_ID']);
         unset($set_column_values['QSG_ID']);
         $success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
     }
     // update the existing related questions
     // BUT FIRST...  delete the phone question from the Question_Group_Question if it is being added to this question group (therefore removed from the existing group)
     if (isset($this->_req_data['questions'], $this->_req_data['questions'][EEM_Attendee::phone_question_id])) {
         // delete where QST ID = system phone question ID and Question Group ID is NOT this group
         EEM_Question_Group_Question::instance()->delete(array(array('QST_ID' => EEM_Attendee::phone_question_id, 'QSG_ID' => array('!=', $QSG_ID))));
     }
     /** @type EE_Question_Group $question_group */
     $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
     $questions = $question_group->questions();
     // make sure system phone question is added to list of questions for this group
     if (!isset($questions[EEM_Attendee::phone_question_id])) {
         $questions[EEM_Attendee::phone_question_id] = EEM_Question::instance()->get_one_by_ID(EEM_Attendee::phone_question_id);
     }
     foreach ($questions as $question_ID => $question) {
         // first we always check for order.
         if (!empty($this->_req_data['question_orders'][$question_ID])) {
             //update question order
             $question_group->update_question_order($question_ID, $this->_req_data['question_orders'][$question_ID]);
         }
         // then we always check if adding or removing.
         if (isset($this->_req_data['questions'], $this->_req_data['questions'][$question_ID])) {
             $question_group->add_question($question_ID);
         } else {
             // not found, remove it (but only if not a system question for the personal group)
             if (!($question->is_system_question() && $question_group->system_group() === EEM_Question_Group::system_personal)) {
                 $question_group->remove_question($question_ID);
             }
         }
     }
     // save new related questions
     if (isset($this->_req_data['questions'])) {
         foreach ($this->_req_data['questions'] as $QST_ID) {
             $question_group->add_question($QST_ID);
             if (isset($this->_req_data['question_orders'][$QST_ID])) {
                 $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][$QST_ID]);
             }
         }
     }
     if ($success !== FALSE) {
         $msg = $new_question_group ? sprintf(__('The %s has been created', 'event_espresso'), $this->_question_group_model->item_name()) : sprintf(__('The %s has been updated', 'event_espresso'), $this->_question_group_model->item_name());
         EE_Error::add_success($msg);
     }
     $this->_redirect_after_action(FALSE, '', '', array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID), TRUE);
 }
 /**
  * update_event_single_order
  *
  * @access    public
  * @return    void
  */
 public static function update_event_single_order()
 {
     $config_saved = false;
     $template_parts = sanitize_text_field($_POST['elements']);
     if (!empty($template_parts)) {
         $template_parts = explode(',', trim($template_parts, ','));
         foreach ($template_parts as $key => $template_part) {
             $template_part = "display_order_{$template_part}";
             $priority = $key * 10 + 100;
             EE_Registry::instance()->CFG->template_settings->EED_Event_Single->{$template_part} = $priority;
             do_action("AHEE__EED_Event_Single__update_event_single_order__{$template_part}", $priority);
         }
         $config_saved = EE_Registry::instance()->CFG->update_espresso_config(false, false);
     }
     if ($config_saved) {
         EE_Error::add_success(__('Display Order has been successfully updated.', 'event_espresso'));
     } else {
         EE_Error::add_error(__('Display Order was not updated.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
     }
     echo wp_json_encode(EE_Error::get_notices(false));
     exit;
 }
 /**
  * 		_trash_or_restore_price_type
  *		@param boolean 		$trash - whether to move item to trash (TRUE) or restore it (FALSE)
  *		@access protected
  *		@return void
  */
 protected function _trash_or_restore_price_type($trash = TRUE)
 {
     //echo '<h3>'. __CLASS__ . '->' . __FUNCTION__ . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h3>';
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     require_once EE_MODELS . 'EEM_Price_Type.model.php';
     $PRT = EEM_Price_Type::instance();
     $success = 1;
     $PRT_deleted = $trash ? TRUE : FALSE;
     //Checkboxes
     if (!empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
         // if array has more than one element than success message should be plural
         $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
         $what = count($this->_req_data['checkbox']) > 1 ? 'Price Types' : 'Price Type';
         // cycle thru checkboxes
         while (list($PRT_ID, $value) = each($this->_req_data['checkbox'])) {
             if (!$PRT->update_by_ID(array('PRT_deleted' => $PRT_deleted), $PRT_ID)) {
                 $success = 0;
             }
         }
     } else {
         // grab single id and delete
         $PRT_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
         if (empty($PRT_ID) || !$PRT->update_by_ID(array('PRT_deleted' => $PRT_deleted), $PRT_ID)) {
             $success = 0;
         }
         $what = 'Price Type';
     }
     $query_args = array('action' => 'price_types');
     if ($success) {
         if ($trash) {
             $msg = $success > 1 ? __('The Price Types have been trashed.', 'event_espresso') : __('The Price Type has been trashed.', 'event_espresso');
         } else {
             $msg = $success > 1 ? __('The Price Types have been restored.', 'event_espresso') : __('The Price Type has been restored.', 'event_espresso');
         }
         EE_Error::add_success($msg);
     }
     $this->_redirect_after_action(FALSE, '', '', $query_args, TRUE);
 }
 /**
  * delete_payment
  * 	delete a payment or refund made towards a transaction
  *
  * @access public
  *	@return void
  */
 public function delete_payment()
 {
     $json_response_data = array('return_data' => FALSE);
     $PAY_ID = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0;
     if ($PAY_ID) {
         $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false;
         $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
         if ($payment instanceof EE_Payment) {
             $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
             /** @type EE_Transaction_Payments $transaction_payments */
             $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
             if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
                 EE_Error::add_success(__('The Payment was successfully deleted.', 'event_espresso'));
                 $json_response_data['return_data'] = array('PAY_ID' => $PAY_ID, 'amount' => $payment->amount(), 'total_paid' => $payment->transaction()->paid(), 'txn_status' => $payment->transaction()->status_ID(), 'pay_status' => $payment->STS_ID(), 'delete_txn_reg_status_change' => $delete_txn_reg_status_change);
                 //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
                 if (!empty($REG_IDs)) {
                     EE_Registry::instance()->load_helper('Template');
                     $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
                     foreach ($registrations as $registration) {
                         $json_response_data['return_data']['registrations'][$registration->ID()] = array('owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()), 'paid' => $registration->pretty_paid());
                     }
                 }
                 if ($delete_txn_reg_status_change) {
                     $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
                     //MAKE sure we also add the delete_txn_req_status_change to the
                     //$_REQUEST global because that's how messages will be looking
                     //for it.
                     $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
                     $this->_process_registration_status_change($payment->transaction());
                 }
             }
         } else {
             EE_Error::add_error(__('Valid Payment data could not be retrieved from the database.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         }
     } else {
         $msg = __('A valid Payment ID was not received, therefore payment form data could not be loaded.', 'event_espresso');
         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
     }
     $notices = EE_Error::get_notices(FALSE, FALSE, FALSE);
     echo json_encode(array_merge($json_response_data, $notices));
     die;
 }
 /**
  * This hooks into the wp_redirect filter and if trashed is detected, then we'll redirect to the appropriate EE route
  * @param  string $location url
  * @param  string $status   status
  * @return string           url to redirect to
  */
 public function cpt_trash_post_location_redirect($location, $status)
 {
     if (isset($this->_req_data['action']) && $this->_req_data['action'] !== 'trash' && empty($this->_req_data['post'])) {
         return $location;
     }
     $post = get_post($this->_req_data['post']);
     $query_args = array('action' => 'default');
     $this->_cpt_object = get_post_type_object($post->post_type);
     EE_Error::add_success(sprintf(__('%s trashed.', 'event_espresso'), $this->_cpt_object->labels->singular_name));
     $this->_process_notices($query_args, TRUE);
     return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
 }
 /**
  * _process_action
  *
  * @access private
  * 	@return void
  */
 private function _process_form_action()
 {
     // what cha wanna do?
     switch ($this->checkout->action) {
         // AJAX next step reg form
         case 'display_spco_reg_step':
             $this->checkout->redirect = FALSE;
             if (EE_Registry::instance()->REQ->ajax) {
                 $this->checkout->json_response->set_reg_step_html($this->checkout->current_step->display_reg_form());
             }
             break;
         default:
             // meh... do one of those other steps first
             if (!empty($this->checkout->action) && is_callable(array($this->checkout->current_step, $this->checkout->action))) {
                 // dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
                 do_action("AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
                 // call action on current step
                 if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
                     // good registrant, you get to proceed
                     if ($this->checkout->current_step->success_message() != '') {
                         if (apply_filters('FHEE__Single_Page_Checkout___process_form_action__display_success', false)) {
                             EE_Error::add_success($this->checkout->current_step->success_message() . '<br />' . $this->checkout->next_step->_instructions());
                         }
                     }
                     // pack it up, pack it in...
                     $this->_setup_redirect();
                 }
                 // dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
                 do_action("AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
             } else {
                 EE_Error::add_error(sprintf(__('The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso'), $this->checkout->action, $this->checkout->current_step->name()), __FILE__, __FUNCTION__, __LINE__);
             }
             // end default
     }
     // store our progress so far
     $this->checkout->stash_transaction_and_checkout();
     // advance to the next step! If you pass GO, collect $200
     $this->go_to_next_step();
 }
 /**
  * @param bool|true $new_question
  * @throws \EE_Error
  */
 protected function _insert_or_update_question($new_question = TRUE)
 {
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     $set_column_values = $this->_set_column_values_for($this->_question_model);
     if ($new_question) {
         $ID = $this->_question_model->insert($set_column_values);
         $success = $ID ? true : false;
         $action_desc = 'added';
     } else {
         $ID = absint($this->_req_data['QST_ID']);
         $pk = $this->_question_model->primary_key_name();
         $wheres = array($pk => $ID);
         unset($set_column_values[$pk]);
         $success = $this->_question_model->update($set_column_values, array($wheres));
         $action_desc = 'updated';
     }
     if ($ID) {
         //save the related options
         //trash removed options, save old ones
         //get list of all options
         /** @type EE_Question $question */
         $question = $this->_question_model->get_one_by_ID($ID);
         $options = $question->options();
         if (!empty($options)) {
             foreach ($options as $option_ID => $option) {
                 $option_req_index = $this->_get_option_req_data_index($option_ID);
                 if ($option_req_index !== FALSE) {
                     $option->save($this->_req_data['question_options'][$option_req_index]);
                 } else {
                     //not found, remove it
                     $option->delete();
                 }
             }
         }
         //save new related options
         foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
             if (empty($option_req_data['QSO_ID']) && (isset($option_req_data['QSO_value']) && $option_req_data['QSO_value'] !== '' || !empty($option_req_data['QSO_desc']))) {
                 //no ID! save it!
                 if (!isset($option_req_data['QSO_value']) || $option_req_data['QSO_value'] === '') {
                     $option_req_data['QSO_value'] = $option_req_data['QSO_desc'];
                 }
                 $new_option = EE_Question_Option::new_instance(array('QSO_value' => $option_req_data['QSO_value'], 'QSO_desc' => $option_req_data['QSO_desc'], 'QSO_order' => $option_req_data['QSO_order'], 'QST_ID' => $question->ID()));
                 $new_option->save();
             }
         }
     }
     $query_args = array('action' => 'edit_question', 'QST_ID' => $ID);
     if ($success !== FALSE) {
         $msg = $new_question ? sprintf(__('The %s has been created', 'event_espresso'), $this->_question_model->item_name()) : sprintf(__('The %s has been updated', 'event_espresso'), $this->_question_model->item_name());
         EE_Error::add_success($msg);
     }
     $this->_redirect_after_action(FALSE, '', $action_desc, $query_args, TRUE);
 }
 /**
  * Message triggers for a resend registration confirmation (in admin)
  *
  * @access public
  * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages
  * @return bool          success/fail
  */
 public static function process_resend($req_data)
 {
     $regs_to_send = array();
     //first let's make sure we have the reg id (needed for resending!);
     if (!isset($req_data['_REG_ID'])) {
         EE_Error::add_error(__('Something went wrong because we\'re missing the registration ID', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     //if $req_data['_REG_ID'] is an array then let's group the registrations by transaction and reg status
     // so we can only trigger messages per group.
     if (is_array($req_data['_REG_ID'])) {
         foreach ($req_data['_REG_ID'] as $reg_id) {
             $reg = EE_Registry::instance()->load_model('Registration')->get_one_by_ID($reg_id);
             if (!$reg instanceof EE_Registration) {
                 EE_Error::add_error(sprintf(__('Unable to retrieve a registration object for the given reg id (%s)', 'event_espresso'), $req_data['_REG_ID']));
                 return false;
             }
             $regs_to_send[$reg->transaction_ID()][$reg->status_ID()][] = $reg;
         }
     } else {
         //we have a single registration id, so let's see if we can get a EE_Registration from it, and if so set it up for sending.
         //get reg object from reg_id
         $reg = EE_Registry::instance()->load_model('Registration')->get_one_by_ID($req_data['_REG_ID']);
         //if no reg object then send error
         if (!$reg instanceof EE_Registration) {
             EE_Error::add_error(sprintf(__('Unable to retrieve a registration object for the given reg id (%s)', 'event_espresso'), $req_data['_REG_ID']));
             return false;
         }
         $regs_to_send[$reg->transaction_ID()][$reg->status_ID()][] = $reg;
     }
     self::_load_controller();
     $status_match_array = self::_get_reg_status_array();
     $active_mts = self::$_EEMSG->get_active_message_types();
     $success = false;
     //loop through and send!
     foreach ($regs_to_send as $status_group) {
         foreach ($status_group as $status_id => $registrations) {
             if (!in_array($status_match_array[$status_id], $active_mts)) {
                 EE_Error::add_error(sprintf(__('Cannot resend the message for this registration because the corresponding message type (%1$s) is not active.  If you wish to send messages for this message type then please activate it by visiting the %2$sMessages Admin Page%3$s.', 'event_espresso'), $status_match_array[$reg->status_ID()], '<a href="' . admin_url('admin.php?page=espresso_messages&action=settings') . '">', '</a>'));
                 return false;
             }
             if (self::$_EEMSG->send_message($status_match_array[$status_id], array($registrations, $status_id))) {
                 EE_Error::overwrite_success();
                 EE_Error::add_success(__('The message for this registration has been re-sent', 'event_espresso'));
                 $success = true;
             } else {
                 EE_Error::add_error(__('Something went wrong and the message for this registration was NOT resent', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
             }
         }
     }
     /**
      * Note this returns true if ANY messages were sent successfully. So if client code wants to catch messages
      * that might not have sent successfully, it needs to check EE_Error for any errors.
      */
     return $success;
 }
 /**
  * updates  espresso configuration settings
  *
  * @access 	protected
  * @param string $tab
  * @param array $data
  * @param string $file	file where error occurred
  * @param string $func function  where error occurred
  * @param string $line	line no where error occurred
  * @return boolean
  */
 protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
 {
     //remove any options that are NOT going to be saved with the config settings.
     if (isset($config->core->ee_ueip_optin)) {
         $config->core->ee_ueip_has_notified = TRUE;
         // TODO: remove the following two lines and make sure values are migrated from 3.1
         update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
         update_option('ee_ueip_has_notified', TRUE);
     }
     // and save it (note we're also doing the network save here)
     $net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(FALSE, FALSE) : TRUE;
     $config_saved = EE_Config::instance()->update_espresso_config(FALSE, FALSE);
     if ($config_saved && $net_saved) {
         EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
         return TRUE;
     } else {
         EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
         return FALSE;
     }
 }
 /**
  *    update_config'
  *
  * @access    public
  * @param bool $add_success
  * @param bool $add_error
  * @return bool success
  */
 public function update_config($add_success = FALSE, $add_error = TRUE)
 {
     do_action('AHEE__EE_Network_Config__update_config__begin', $this);
     //we have to compare existing saved config with config in memory because if there is no difference that means
     //that the method executed fine but there just was no update.  WordPress doesn't distinguish between false because
     //there were 0 records updated because of no change vs false because some error produced problems with the update.
     $original = get_site_option('ee_network_config');
     if ($original == $this) {
         return true;
     }
     // update
     $saved = update_site_option('ee_network_config', $this);
     do_action('AHEE__EE_Network_Config__update_config__end', $this, $saved);
     // if config remains the same or was updated successfully
     if ($saved) {
         if ($add_success) {
             $msg = is_multisite() ? __('The Event Espresso Network Configuration Settings have been successfully updated.', 'event_espresso') : __('Extra Event Espresso Configuration settings were successfully updated.', 'event_espresso');
             EE_Error::add_success($msg);
         }
         return TRUE;
     } else {
         if ($add_error) {
             $msg = is_multisite() ? __('The Event Espresso Network Configuration Settings were not updated.', 'event_espresso') : __('Extra Event Espresso Network Configuration settings were not updated.', 'event_espresso');
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
         }
         return FALSE;
     }
 }
 /**
  * delegates message sending to messengers
  * @param  string  $type    What type of message are we sending (corresponds to message types)
  * @param  mixed  $vars    Data being sent for parsing in the message
  * @param  string $sending_messenger if included then we ONLY use the specified messenger for delivery.  Otherwise we cycle through all active messengers.
  * @param string $generating_messenger if included then this messenger is used for generating the message templates (but not for sending).
  * @param string $context If included then only a message type for a specific context will be generated.
  * @param bool  $send 			       Default TRUE.  If false, then this will just return the generated EE_Messages objects which might be used by the trigger to setup a batch message (typically html messenger uses it).
  * @return bool
  */
 public function send_message($type, $vars, $sending_messenger = '', $generating_messenger = '', $context = '', $send = TRUE)
 {
     $error = FALSE;
     $installed_message_types = $this->get_installed_message_types();
     //		$debug_index = 'Messages: ' . $type;
     //		foreach ( $vars as $var ) {
     //			if ( method_exists( $var, 'ID' ) ) {
     //				$debug_index = get_class( $var ) .  ': ' . $var->ID();
     //				break;
     //			} else if ( is_object( $var )) {
     //				$debug_index = spl_object_hash( $var );
     //			}
     //		}
     //EEH_Debug_Tools::log(
     //	__CLASS__, __FUNCTION__, __LINE__,
     //	array(
     //		'message_type' => $type,
     //		'incoming_data' => $vars,
     //		'sending_messenger' => $sending_messenger,
     //		'generating_messenger' => $generating_messenger,
     //		'context' => $context,
     //		'send' => $send,
     //		'installed_message_types' => $installed_message_types
     //		),
     //	false,
     //	$debug_index
     //);
     // is that a real class ?
     if (isset($installed_message_types[$type])) {
         //is the messenger specified? If so then let's see if can send.  This is the check where its possible secondary messengers might be in use.
         if (!empty($sending_messenger)) {
             $generating_messenger = !empty($generating_messenger) && !empty($this->_active_messengers[$generating_messenger]) ? $this->_active_messengers[$generating_messenger] : NULL;
             $generating_messenger = empty($generating_messenger) && !empty($this->_active_messengers[$sending_messenger]) ? $this->_active_messengers[$sending_messenger] : $generating_messenger;
             if (!$this->_is_generating_messenger_and_active($generating_messenger, $installed_message_types[$type])) {
                 return false;
             }
             $sending_messenger = !empty($this->_active_messengers[$sending_messenger]) ? $this->_active_messengers[$sending_messenger] : NULL;
             $context = !empty($context) ? $context : FALSE;
             $success = $this->_send_message($generating_messenger, $installed_message_types[$type], $vars, $sending_messenger, $context, $send);
             if (!$send) {
                 return $success;
                 //returning generated EE_Messages objects
             }
         } else {
             //no messenger sent so let's just loop through active messengers (this method is only acceptable for primary messengers)
             $send_messages = array();
             foreach ($this->_active_messengers as $active_messenger) {
                 //we ONLY continue if the given messenger is a primary messenger and is an active messenger for the given message type.  Otherwise we skip.
                 if (!$this->_is_generating_messenger_and_active($active_messenger, $installed_message_types[$type])) {
                     continue;
                 }
                 $success = $this->_send_message($active_messenger, $installed_message_types[$type], $vars, $active_messenger);
                 if ($success === FALSE) {
                     $error = TRUE;
                 } else {
                     $send_messages[] = $success;
                 }
             }
             //EEH_Debug_Tools::log(
             //	__CLASS__, __FUNCTION__, __LINE__,
             //	array(
             //		'message_type' => $type,
             //		'active_messenger' => $this->_active_messengers,
             //		'send_messages' => $send_messages,
             //		'error' => $error
             //		),
             //	false,
             //	$debug_index
             //	);
             //return generated EE_Messages objects?
             if (!$send) {
                 return $send_messages;
             }
         }
     } else {
         EE_Error::add_error(sprintf(__('Message type: %s does not exist', 'event_espresso'), $type), __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     // add a success message
     if (!$error) {
         EE_Error::add_success(sprintf(__('The %s message has been successfully sent.', 'event_espresso'), $installed_message_types[$type]->label['singular']), __FILE__, __FUNCTION__, __LINE__);
     }
     return $error ? FALSE : TRUE;
     //yeah backwards eh?  Really what we're returning is if there is a total success for all the messages or not.  We'll modify this once we get message recording in place.
 }
 private function _insert_category($update = FALSE)
 {
     $cat_id = $update ? $this->_req_data['VEN_CAT_ID'] : '';
     $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
     $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
     $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
     if (empty($category_name)) {
         $msg = __('You must add a name for the category.', 'event_espresso');
         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     $term_args = array('name' => $category_name, 'description' => $category_desc, 'parent' => $category_parent);
     $insert_ids = $update ? wp_update_term($cat_id, 'espresso_venue_categories', $term_args) : wp_insert_term($category_name, 'espresso_venue_categories', $term_args);
     if (!is_array($insert_ids)) {
         $msg = __('An error occurred and the category has not been saved to the database.', 'event_espresso');
         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
     } else {
         $cat_id = $insert_ids['term_id'];
         $msg = sprintf(__('The category %s was successfuly created', 'event_espresso'), $category_name);
         EE_Error::add_success($msg);
     }
     return $cat_id;
 }
 /**
  *    _process_payment_status
  *
  * @access private
  * @type    EE_Payment $payment
  * @param string $payment_occurs
  * @return bool
  * @throws \EE_Error
  */
 private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
 {
     // off-line payment? carry on
     if ($payment_occurs == EE_PMT_Base::offline) {
         return true;
     }
     // verify payment validity
     if ($payment instanceof EE_Payment) {
         do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
         $msg = $payment->gateway_response();
         // check results
         switch ($payment->status()) {
             // good payment
             case EEM_Payment::status_id_approved:
                 EE_Error::add_success(__('Your payment was processed successfully.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
                 return TRUE;
                 break;
                 // slow payment
             // slow payment
             case EEM_Payment::status_id_pending:
                 if (empty($msg)) {
                     $msg = __('Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.', 'event_espresso');
                 }
                 EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
                 return TRUE;
                 break;
                 // don't wanna payment
             // don't wanna payment
             case EEM_Payment::status_id_cancelled:
                 if (empty($msg)) {
                     $msg = _n('Payment cancelled. Please try again.', 'Payment cancelled. Please try again or select another method of payment.', count($this->checkout->available_payment_methods), 'event_espresso');
                 }
                 EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
                 return FALSE;
                 break;
                 // not enough payment
             // not enough payment
             case EEM_Payment::status_id_declined:
                 if (empty($msg)) {
                     $msg = _n('We\'re sorry but your payment was declined. Please try again.', 'We\'re sorry but your payment was declined. Please try again or select another method of payment.', count($this->checkout->available_payment_methods), 'event_espresso');
                 }
                 EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
                 return FALSE;
                 break;
                 // bad payment
             // bad payment
             case EEM_Payment::status_id_failed:
                 if (!empty($msg)) {
                     EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
                     return false;
                 }
                 // default to error below
                 break;
         }
     }
     // off-site payment gateway responses are too unreliable, so let's just assume that
     // the payment processing is just running slower than the registrant's request
     if ($payment_occurs == EE_PMT_Base::offsite) {
         return true;
     }
     EE_Error::add_error(sprintf(__('Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.', 'event_espresso'), '<br/>', EE_Registry::instance()->CFG->organization->get_pretty('email')), __FILE__, __FUNCTION__, __LINE__);
     return FALSE;
 }
 /**
  * 		delete_state
  *
  * 		@access 	public
  * 		@return 		boolean | void
  */
 public function delete_state()
 {
     $CNT_ISO = isset($this->_req_data['CNT_ISO']) ? strtoupper(sanitize_text_field($this->_req_data['CNT_ISO'])) : FALSE;
     $STA_ID = isset($this->_req_data['STA_ID']) ? sanitize_text_field($this->_req_data['STA_ID']) : FALSE;
     $STA_abbrev = isset($this->_req_data['STA_abbrev']) ? sanitize_text_field($this->_req_data['STA_abbrev']) : FALSE;
     if (!$STA_ID) {
         EE_Error::add_error(__('No State ID or an invalid State ID was received.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return FALSE;
     }
     $success = EEM_State::instance()->delete_by_ID($STA_ID);
     if ($success !== FALSE) {
         do_action('AHEE__General_Settings_Admin_Page__delete_state__state_deleted', $CNT_ISO, $STA_ID, array('STA_abbrev' => $STA_abbrev));
         EE_Error::add_success(__('The State was deleted successfully.', 'event_espresso'));
     }
     if (defined('DOING_AJAX')) {
         $notices = EE_Error::get_notices(FALSE, FALSE);
         $notices['return_data'] = TRUE;
         echo json_encode($notices);
         die;
     } else {
         $this->_redirect_after_action($success, 'State', 'deleted', array('action' => 'country_settings'));
     }
 }
 /**
  * Message triggers for a resend registration confirmation (in admin)
  *
  * @access public
  * @param  bool $success incoming success value (we return true or false on success/fail)
  * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages
  * @return bool          success/fail
  */
 public function process_resend($success, $req_data)
 {
     $success = TRUE;
     //first let's make sure we have the reg id (needed for resending!);
     if (!isset($req_data['_REG_ID'])) {
         EE_Error::add_error(__('Something went wrong because we\'re missing the registration ID', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         $success = FALSE;
     }
     //get reg object from reg_id
     $reg = EE_Registry::instance()->load_model('Registration')->get_one_by_ID($req_data['_REG_ID']);
     //if no reg object then send error
     if (empty($reg)) {
         EE_Error::add_error(sprintf(__('Unable to retrieve a registration object for the given reg id (%s)', 'event_espresso'), $req_data['_REG_ID']), __FILE__, __FUNCTION__, __LINE__);
         $success = FALSE;
     }
     if ($success) {
         $this->_load_controller();
         //get status_match_array
         $status_match_array = $this->_get_reg_status_array();
         $active_mts = $this->_EEMSG->get_active_message_types();
         if (!in_array($status_match_array[$reg->status_ID()], $active_mts)) {
             $success = FALSE;
             EE_Error::add_error(sprintf(__('Cannot resend the message for this registration because the corresponding message type (%s) is not active.  If you wish to send messages for this message type then please activate it by %sgoing here%s.', 'event_espresso'), $status_match_array[$reg->status_ID()], '<a href="' . admin_url('admin.php?page=espresso_messages&action=settings') . '">', '</a>'), __FILE__, __FUNCTION__, __LINE__);
             return $success;
         }
         $success = $this->_EEMSG->send_message($status_match_array[$reg->status_ID()], $reg);
     }
     if ($success) {
         EE_Error::overwrite_success();
         EE_Error::add_success(__('The message for this registration has been re-sent', 'event_espresso'));
     } else {
         EE_Error::add_error(__('Something went wrong and the message for this registration was NOT resent', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
     }
     return $success;
 }