/**
  * @param array $req_data
  */
 protected function _normalize($req_data)
 {
     parent::_normalize($req_data);
     $paypal_calculates_shipping = $this->get_input_value('paypal_shipping');
     $paypal_calculates_taxes = $this->get_input_value('paypal_taxes');
     $paypal_requests_address_info = $this->get_input_value('shipping_details');
     if (($paypal_calculates_shipping || $paypal_calculates_taxes) && $paypal_requests_address_info == EE_PMT_Paypal_Standard::shipping_info_none) {
         //they want paypal to calculate taxes or shipping. They need to ask for
         //address info, otherwise paypal can't calculate taxes or shipping
         /** @type EE_Select_Input $shipping_details_input */
         $shipping_details_input = $this->get_input('shipping_details');
         $shipping_details_input->set_default(EE_PMT_Paypal_Standard::shipping_info_optional);
         $shipping_details_input_options = $shipping_details_input->options();
         EE_Error::add_attention(sprintf(__('Automatically set "%s" to "%s" because Paypal requires address info in order to calculate shipping or taxes.', 'event_espresso'), strip_tags($shipping_details_input->html_label_text()), isset($shipping_details_input_options[EE_PMT_Paypal_Standard::shipping_info_optional]) ? $shipping_details_input_options[EE_PMT_Paypal_Standard::shipping_info_optional] : __('Unknown', 'event_espresso')), __FILE__, __FUNCTION__, __LINE__);
     }
 }
 protected function _init_props()
 {
     $this->label = __('Messenger Shortcodes', 'event_espresso');
     $this->description = __('All shortcodes that are messenger specific.', 'event_espresso');
     //add messages about what happens  when the messenger is active.
     $this->_active_messengers = EE_Registry::instance()->load_lib('messages')->get_active_messengers();
     $this->_shortcodes['[DISPLAY_HTML_URL]'] = __('This will return a link to view the template in a browser if the html messenger is active.', 'event_espresso');
     $this->_shortcodes['[DISPLAY_PDF_URL]'] = __('This will return a link to generate a pdf for the template if the pdf messenger is active.', 'event_espresso');
     $this->_shortcodes['[DISPLAY_PDF_BUTTON]'] = __('This will return html for a download pdf button trigger if the pdf messenger is active.', 'event_espresso');
     //show error message about buttons/urls not working as expected if messenger deactivated.
     if (is_admin() && isset($_REQUEST['action']) && $_REQUEST['action'] == 'update_message_template') {
         if (!isset($this->_active_messengers['pdf'])) {
             EE_Error::add_attention(__('Be aware that the pdf messenger is inactive.  This means that any pdf related shortcodes will parse to an empty string.', 'event_espresso'));
         }
         if (!isset($this->_active_messengers['html'])) {
             EE_Error::add_attention(__('Be aware that the html messenger is inactive. This means that any html related shortcodes will parse to an empty string.', 'event_espresso'));
         }
     }
 }
 protected function _set_hooks_properties()
 {
     $this->_name = 'pricing';
     //capability check
     if (!EE_Registry::instance()->CAP->current_user_can('ee_read_default_prices', 'advanced_ticket_datetime_metabox')) {
         return;
     }
     EE_Registry::instance()->load_helper('DTT_Helper');
     //if we were going to add our own metaboxes we'd use the below.
     $this->_metaboxes = array(0 => array('page_route' => array('edit', 'create_new'), 'func' => 'pricing_metabox', 'label' => __('Event Tickets & Datetimes', 'event_espresso'), 'priority' => 'high', 'context' => 'normal'));
     /**/
     $this->_remove_metaboxes = array(0 => array('page_route' => array('edit', 'create_new'), 'id' => 'espresso_event_editor_tickets', 'context' => 'normal'));
     /**
      * Format strings for date and time.  Defaults are existing behaviour from 4.1.
      * Note, that if you return null as the value for 'date', and 'time' in the array, then
      * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
      *
      * @since 4.6.7
      *
      * @var array  Expected an array returned with 'date' and 'time' keys.
      */
     $this->_date_format_strings = apply_filters('FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings', array('date' => 'Y-m-d', 'time' => 'h:i a'));
     //validate
     $this->_date_format_strings['date'] = isset($this->_date_format_strings['date']) ? $this->_date_format_strings['date'] : null;
     $this->_date_format_strings['time'] = isset($this->_date_format_strings['time']) ? $this->_date_format_strings['time'] : null;
     //validate format strings
     $format_validation = EEH_DTT_Helper::validate_format_string($this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time']);
     if (is_array($format_validation)) {
         $msg = '<p>' . sprintf(__('The format "%s" was likely added via a filter and is invalid for the following reasons:', 'event_espresso'), $this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time']) . '</p><ul>';
         foreach ($format_validation as $error) {
             $msg .= '<li>' . $error . '</li>';
         }
         $msg .= '</ul></p><p>' . sprintf(__('%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s', 'event_espresso'), '<span style="color:#D54E21;">', '</span>') . '</p>';
         EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
         $this->_date_format_strings = array('date' => 'Y-m-d', 'time' => 'h:i a');
     }
     $this->_scripts_styles = array('registers' => array('ee-tickets-datetimes-css' => array('url' => PRICING_ASSETS_URL . 'event-tickets-datetimes.css', 'type' => 'css'), 'ee-dtt-ticket-metabox' => array('url' => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js', 'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'))), 'deregisters' => array('event-editor-css' => array('type' => 'css'), 'event-datetime-metabox' => array('type' => 'js')), 'enqueues' => array('ee-tickets-datetimes-css' => array('edit', 'create_new'), 'ee-dtt-ticket-metabox' => array('edit', 'create_new')), 'localize' => array('ee-dtt-ticket-metabox' => array('DTT_TRASH_BLOCK' => array('main_warning' => __('The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):', 'event_espresso'), 'after_warning' => __('In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.', 'event_espresso'), 'cancel_button' => '<button class="button-secondary ee-modal-cancel">' . __('Cancel', 'event_espresso') . '</button>', 'single_warning_from_tkt' => __('The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.', 'event_espresso'), 'single_warning_from_dtt' => __('The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket.  Tickets must always have at least one datetime assigned to them.', 'event_espresso'), 'dismiss_button' => '<button class="button-secondary ee-modal-cancel">' . __('Dismiss', 'event_espresso') . '</button>'), 'DTT_ERROR_MSG' => array('no_ticket_name' => __('General Admission', 'event_espresso'), 'dismiss_button' => '<div class="save-cancel-button-container"><button class="button-secondary ee-modal-cancel">' . __('Dismiss', 'event_espresso') . '</button></div>'), 'DTT_OVERSELL_WARNING' => array('datetime_ticket' => __('You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.', 'event_espresso'), 'ticket_datetime' => __('You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.', 'event_espresso')), 'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats($this->_date_format_strings['date'], $this->_date_format_strings['time']), 'DTT_START_OF_WEEK' => array('dayValue' => (int) get_option('start_of_week')))));
     add_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page', array($this, 'autosave_handling'), 10);
     add_filter('FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks', array($this, 'caf_updates'), 10);
 }
 /**
  * This just updates the active_messengers usermeta field when a messenger or message type is activated/deactivated.
  * NOTE: deactivating will remove the messenger (or message type) from the active_messengers wp_options field so all saved settings WILL be lost for the messenger AND message_types associated with that messenger (or message type).
  *
  * @param  string  $messenger What messenger we're toggling
  * @param  boolean $deactivate if true then we deactivate
  * @param  mixed   $message_type if present what message type we're toggling
  * @return void
  */
 protected function _activate_messenger($messenger, $deactivate = FALSE, $message_type = FALSE)
 {
     global $espresso_wp_user;
     $templates = TRUE;
     $this->_set_m_mt_settings();
     if (!$deactivate) {
         //we are activating.  we can use $this->_m_mt_settings to get all the installed messengers
         $this->_active_messengers[$messenger]['settings'] = !isset($this->_active_messengers[$messenger]['settings']) ? array() : $this->_active_messengers[$messenger]['settings'];
         $this->_active_messengers[$messenger]['obj'] = $this->_m_mt_settings['messenger_tabs'][$messenger]['obj'];
         //get has_active so we can sure its kept up to date.
         $has_activated = get_option('ee_has_activated_messages');
         if (empty($has_activated[$messenger])) {
             $has_activated[$messenger] = array();
         }
         //k we need to get what default message types are to be associated with the messenger that's been activated.
         $default_types = $message_type ? (array) $message_type : $this->_active_messengers[$messenger]['obj']->get_default_message_types();
         foreach ($default_types as $type) {
             $settings_fields = $this->_m_mt_settings['message_type_tabs'][$messenger]['inactive'][$type]['obj']->get_admin_settings_fields();
             if (!empty($settings_fields)) {
                 //we have fields for this message type so let's get the defaults for saving.
                 foreach ($settings_fields as $field => $values) {
                     $settings[$field] = $values['default'];
                 }
                 //let's set the data for reloading this message type form in ajax
                 $this->_template_args['data']['mt_reload'][] = $type;
             } else {
                 $settings = array();
             }
             $this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'][$type]['settings'] = $settings;
             if (!in_array($type, $has_activated[$messenger])) {
                 $has_activated[$messenger][] = $type;
             }
         }
         //any default settings for the messenger?
         $msgr_settings = $this->_active_messengers[$messenger]['obj']->get_admin_settings_fields();
         if (!empty($msgr_settings)) {
             foreach ($msgr_settings as $field => $value) {
                 $this->_active_messengers[$messenger]['settings'][$field] = $value;
             }
         }
         //update settings in database
         EEH_MSG_Template::update_active_messengers_in_db($this->_active_messengers);
         update_option('ee_has_activated_messages', $has_activated);
         //generate new templates (if necessary)
         $templates = $this->_generate_new_templates($messenger, $default_types, 0, TRUE);
         EE_Error::overwrite_success();
         //if generation failed then we need to remove the active messenger.
         if (!$templates) {
             unset($this->_active_messengers[$messenger]);
             EEH_MSG_Template::update_active_messengers_in_db($this->_active_messengers);
         } else {
             //all is good let's do a success message
             if ($message_type) {
                 EE_Error::add_success(sprintf(__('%s message type has been successfully activated with the %s messenger', 'event_espresso'), ucwords($this->_m_mt_settings['message_type_tabs'][$messenger]['inactive'][$message_type]['obj']->label['singular']), ucwords($this->_active_messengers[$messenger]['obj']->label['singular'])));
                 //if message type was invoice then let's make sure we activate the invoice payment method.
                 if ($message_type == 'invoice') {
                     EE_Registry::instance()->load_lib('Payment_Method_Manager');
                     $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
                     if ($pm instanceof EE_Payment_Method) {
                         EE_Error::add_attention(__('Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.', 'event_espresso'));
                     }
                 }
             } else {
                 EE_Error::add_success(sprintf(__('%s messenger has been successfully activated', 'event_espresso'), ucwords($this->_active_messengers[$messenger]['obj']->label['singular'])));
             }
         }
         $this->_template_args['data']['active_mts'] = $default_types;
     } else {
         //we're deactivating
         $MTP = EEM_Message_Template_Group::instance();
         //okay let's update the message templates that match this messenger so that they are deactivated in the database as well.
         $update_array = array('MTP_messenger' => $messenger);
         if ($message_type) {
             $update_array['MTP_message_type'] = $message_type;
         }
         $success = $MTP->update(array('MTP_is_active' => 0), array($update_array));
         $messenger_obj = $this->_active_messengers[$messenger]['obj'];
         //if this is a message type deactivation then we're only unsetting the message type otherwise unset the messenger
         if ($message_type) {
             unset($this->_active_messengers[$messenger]['settings'][$messenger . '-message_types'][$message_type]);
         } else {
             unset($this->_active_messengers[$messenger]);
         }
         EEH_MSG_Template::update_active_messengers_in_db($this->_active_messengers);
         EE_Error::overwrite_success();
         if ($message_type) {
             EE_Error::add_success(sprintf(__('%s message type has been successfully deactivated', 'event_espresso'), ucwords($this->_m_mt_settings['message_type_tabs'][$messenger]['active'][$message_type]['obj']->label['singular'])));
         } else {
             EE_Error::add_success(sprintf(__('%s messenger has been successfully deactivated', 'event_espresso'), ucwords($messenger_obj->label['singular'])));
         }
         //if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
         if ($messenger == 'html' || $message_type == 'invoice') {
             EE_Registry::instance()->load_lib('Payment_Method_Manager');
             $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
             if ($count_updated > 0) {
                 $msg = $message_type == 'invoice' ? __('Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then vist the payment methods admin page to reactivate the invoice payment method.', 'event_espresso') : __('Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.', 'event_espresso');
                 EE_Error::add_attention($msg);
             }
         }
     }
     return true;
 }
 /**
  * default maintenance page. If we're in maintenance mode level 2, then we need to show
  * the migration scripts and all that UI.
  */
 public function _maintenance()
 {
     //it all depends if we're in maintenance model level 1 (frontend-only) or
     //level 2 (everything except maintenance page)
     try {
         //get the current maintenance level and check if
         //we are removed
         $mm = EE_Maintenance_Mode::instance()->level();
         $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
         if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && !$placed_in_mm) {
             //we just took the site out of maintenance mode, so notify the user.
             //unfortunately this message appears to be echoed on the NEXT page load...
             //oh well, we should really be checking for this on addon deactivation anyways
             EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required', 'event_espresso'));
             $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false);
         }
         //in case an exception is thrown while trying to handle migrations
         switch (EE_Maintenance_Mode::instance()->level()) {
             case EE_Maintenance_Mode::level_0_not_in_maintenance:
             case EE_Maintenance_Mode::level_1_frontend_only_maintenance:
                 $show_maintenance_switch = true;
                 $show_backup_db_text = false;
                 $show_migration_progress = false;
                 $script_names = array();
                 $addons_should_be_upgraded_first = false;
                 break;
             case EE_Maintenance_Mode::level_2_complete_maintenance:
                 $show_maintenance_switch = false;
                 $show_migration_progress = true;
                 if (isset($this->_req_data['continue_migration'])) {
                     $show_backup_db_text = false;
                 } else {
                     $show_backup_db_text = true;
                 }
                 $scripts_needing_to_run = EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts();
                 $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating();
                 $script_names = array();
                 $current_script = NULL;
                 foreach ($scripts_needing_to_run as $script) {
                     if ($script instanceof EE_Data_Migration_Script_Base) {
                         if (!$current_script) {
                             $current_script = $script;
                             $current_script->migration_page_hooks();
                         }
                         $script_names[] = $script->pretty_name();
                     }
                 }
                 break;
         }
         $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true);
         $exception_thrown = false;
     } catch (EE_Error $e) {
         EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage());
         //now, just so we can display the page correctly, make a error migration script stage object
         //and also put the error on it. It only persists for the duration of this request
         $most_recent_migration = new EE_DMS_Unknown_1_0_0();
         $most_recent_migration->add_error($e->getMessage());
         $exception_thrown = true;
     }
     $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set();
     if ($exception_thrown || $most_recent_migration && $most_recent_migration instanceof EE_Data_Migration_Script_Base && $most_recent_migration->is_broken()) {
         $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php';
         $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/';
         $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action' => 'confirm_migration_crash_report_sent', 'success' => '0'), EE_MAINTENANCE_ADMIN_URL);
     } elseif ($addons_should_be_upgraded_first) {
         $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php';
     } else {
         if ($most_recent_migration && $most_recent_migration instanceof EE_Data_Migration_Script_Base && $most_recent_migration->can_continue()) {
             $show_backup_db_text = false;
             $show_continue_current_migration_script = true;
             $show_most_recent_migration = true;
         } elseif (isset($this->_req_data['continue_migration'])) {
             $show_most_recent_migration = true;
             $show_continue_current_migration_script = false;
         } else {
             $show_most_recent_migration = false;
             $show_continue_current_migration_script = false;
         }
         if (isset($current_script)) {
             $migrates_to = $current_script->migrates_to_version();
             $plugin_slug = $migrates_to['slug'];
             $new_version = $migrates_to['version'];
             $this->_template_args = array_merge($this->_template_args, array('current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"), isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug), 'next_db_state' => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'), $new_version, $plugin_slug) : NULL));
         }
         $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php';
         $this->_template_args = array_merge($this->_template_args, array('show_most_recent_migration' => $show_most_recent_migration, 'show_migration_progress' => $show_migration_progress, 'show_backup_db_text' => $show_backup_db_text, 'show_maintenance_switch' => $show_maintenance_switch, 'script_names' => $script_names, 'show_continue_current_migration_script' => $show_continue_current_migration_script, 'reset_db_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), EE_MAINTENANCE_ADMIN_URL), 'update_migration_script_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'), EE_MAINTENANCE_ADMIN_URL), 'ultimate_db_state' => sprintf(__("EE%s", 'event_espresso'), espresso_version())));
         //make sure we have the form fields helper available. It usually is, but sometimes it isn't
         EE_Registry::instance()->load_helper('Form_Fields');
         //localize script stuff
         wp_localize_script('ee-maintenance', 'ee_maintenance', array('migrating' => __("Migrating...", "event_espresso"), 'next' => __("Next", "event_espresso"), 'fatal_error' => __("A Fatal Error Has Occurred", "event_espresso"), 'click_next_when_ready' => __("The current Migration has ended. Click 'next' when ready to proceed", "event_espresso"), 'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts, 'status_fatal_error' => EE_Data_Migration_Manager::status_fatal_error, 'status_completed' => EE_Data_Migration_Manager::status_completed));
     }
     $this->_template_args['most_recent_migration'] = $most_recent_migration;
     //the actual most recently ran migration
     $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, $this->_template_args, TRUE);
     $this->display_admin_page_with_sidebar();
 }
Ejemplo n.º 6
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;
     }
 }
 /**
  *    _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_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;
 }
 /**
  *    alpha_banner_admin_notice
  *    displays admin notice that current version of EE is not a stable release
  *
  * @access public
  * @return void
  */
 public function alpha_banner_admin_notice()
 {
     EE_Error::add_attention(sprintf(__('This version of Event Espresso is for testing and/or evaluation purposes only. It is %1$snot%2$s considered a stable release and should therefore %1$snot%2$s be activated on a live or production website.', 'event_espresso'), '<strong>', '</strong>'), __FILE__, __FUNCTION__, __LINE__);
 }
 /**
  * verify_no_exclusive_promotions_combined
  * verifies that no exclusive promotions are being combined together
  *
  * @since   1.0.0
  *
  * @param EE_Line_Item $parent_line_item
  * @param EE_Promotion $promotion
  * @return EE_Line_Item
  */
 public function verify_no_exclusive_promotions_combined(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
 {
     /** @type EEM_Line_Item $EEM_Line_Item */
     $EEM_Line_Item = EE_Registry::instance()->load_model('Line_Item');
     // get all existing promotions that have already been added to the cart
     $existing_promotion_line_items = $EEM_Line_Item->get_all_promotion_line_items($parent_line_item);
     if (!empty($existing_promotion_line_items)) {
         // can't apply this new promotion if it is exclusive
         if ($promotion->is_exclusive()) {
             EE_Error::add_attention(sprintf(apply_filters('FHEE__EED_Promotions__verify_no_exclusive_promotions_combined__new_promotion_is_exclusive_notice', __('We\'re sorry, but %3$s have already been added to the cart and the "%1$s%2$s" promotion can not be combined with others.', 'event_espresso')), $promotion->code() ? $promotion->code() . ' : ' : '', $promotion->name(), strtolower($this->_config->label->plural)), __FILE__, __FUNCTION__, __LINE__);
             return false;
         }
         // new promotion is not exclusive...
         // so now determine if any existing ones are
         foreach ($existing_promotion_line_items as $existing_promotion_line_item) {
             if ($existing_promotion_line_item instanceof EE_Line_Item) {
                 $existing_promotion = $this->get_promotion_from_line_item($existing_promotion_line_item);
                 if ($existing_promotion instanceof EE_Promotion && $existing_promotion->is_exclusive()) {
                     EE_Error::add_attention(sprintf(apply_filters('FHEE__EED_Promotions__verify_no_exclusive_promotions_combined__existing_promotion_is_exclusive_notice', __('We\'re sorry, but the "%1$s%2$s" %3$s has already been added to the cart and can not be combined with others.', 'event_espresso')), $existing_promotion->code() ? $existing_promotion->code() . ' : ' : '', $existing_promotion->name(), strtolower($this->_config->label->singular)), __FILE__, __FUNCTION__, __LINE__);
                     return false;
                 }
             }
         }
     }
     return true;
 }
 /**
  * update registrations REG_paid field after successful payment and link registrations with payment
  *
  * @param EE_Transaction $transaction
  * @param EE_Payment $payment
  * @param EE_Registration[] $registrations
  * @throws \EE_Error
  */
 public function process_registration_payments(EE_Transaction $transaction, EE_Payment $payment, $registrations = array())
 {
     // only process if payment was successful
     if ($payment->status() !== EEM_Payment::status_id_approved) {
         return;
     }
     //EEM_Registration::instance()->show_next_x_db_queries();
     if (empty($registrations)) {
         // find registrations with monies owing that can receive a payment
         $registrations = $transaction->registrations(array(array('STS_ID' => array('IN', EEM_Registration::reg_statuses_that_allow_payment()), 'REG_final_price' => array('!=', 0), 'REG_final_price*' => array('!=', 'REG_paid', true))));
     }
     // still nothing ??!??
     if (empty($registrations)) {
         return;
     }
     // todo: break out the following logic into a separate strategy class
     // todo: named something like "Sequential_Reg_Payment_Strategy"
     // todo: which would apply payments using the capitalist "first come first paid" approach
     // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
     // todo: which would be the socialist "everybody gets a piece of pie" approach,
     // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
     $refund = $payment->is_a_refund();
     // how much is available to apply to registrations?
     $available_payment_amount = abs($payment->amount());
     foreach ($registrations as $registration) {
         if ($registration instanceof EE_Registration) {
             // nothing left?
             if ($available_payment_amount <= 0) {
                 break;
             }
             if ($refund) {
                 $available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
             } else {
                 $available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
             }
         }
     }
     if ($available_payment_amount > 0 && apply_filters('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', false)) {
         EE_Error::add_attention(sprintf(__('A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).', 'event_espresso'), EEH_Template::format_currency($available_payment_amount), implode(', ', array_keys($registrations)), '<br/>', EEH_Template::format_currency($payment->amount())), __FILE__, __FUNCTION__, __LINE__);
     }
 }
 /**
  * 	process_ticket_selections
  *
  *	@access public
  * 	@access 		public
  * 	@return		array  or FALSE
  */
 public function process_ticket_selections()
 {
     do_action('EED_Ticket_Selector__process_ticket_selections__before');
     // check nonce
     if (!is_admin() && (!EE_Registry::instance()->REQ->is_set('process_ticket_selections_nonce') || !wp_verify_nonce(EE_Registry::instance()->REQ->get('process_ticket_selections_nonce'), 'process_ticket_selections'))) {
         EE_Error::add_error(sprintf(__('We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.', 'event_espresso'), '<br/>'), __FILE__, __FUNCTION__, __LINE__);
         return FALSE;
     }
     //		d( EE_Registry::instance()->REQ );
     self::$_available_spaces = array('tickets' => array(), 'datetimes' => array());
     //we should really only have 1 registration in the works now (ie, no MER) so clear any previous items in the cart.
     // When MER happens this will probably need to be tweaked, possibly wrapped in a conditional checking for some constant defined in MER etc.
     EE_Registry::instance()->load_core('Session');
     // unless otherwise requested, clear the session
     if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', TRUE)) {
         EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
     }
     //d( EE_Registry::instance()->SSN );
     do_action('AHEE_log', __FILE__, __FUNCTION__, '');
     // do we have an event id?
     if (EE_Registry::instance()->REQ->is_set('tkt-slctr-event-id')) {
         // validate/sanitize data
         $valid = self::_validate_post_data();
         //EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
         //EEH_Debug_Tools::printr( $valid, '$valid', __FILE__, __LINE__ );
         //EEH_Debug_Tools::printr( $valid[ 'total_tickets' ], 'total_tickets', __FILE__, __LINE__ );
         //EEH_Debug_Tools::printr( $valid[ 'max_atndz' ], 'max_atndz', __FILE__, __LINE__ );
         //check total tickets ordered vs max number of attendees that can register
         if ($valid['total_tickets'] > $valid['max_atndz']) {
             // ordering too many tickets !!!
             $total_tickets_string = _n('You have attempted to purchase %s ticket.', 'You have attempted to purchase %s tickets.', $valid['total_tickets'], 'event_espresso');
             $limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
             // dev only message
             $max_atndz_string = _n('The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.', 'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.', $valid['max_atndz'], 'event_espresso');
             $limit_error_2 = sprintf($max_atndz_string, $valid['max_atndz'], $valid['max_atndz']);
             EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
         } else {
             // all data appears to be valid
             $tckts_slctd = FALSE;
             $success = TRUE;
             // load cart
             EE_Registry::instance()->load_core('Cart');
             // cycle thru the number of data rows sent from the event listing
             for ($x = 0; $x < $valid['rows']; $x++) {
                 // does this row actually contain a ticket quantity?
                 if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
                     // YES we have a ticket quantity
                     $tckts_slctd = TRUE;
                     //						d( $valid['ticket_obj'][$x] );
                     if ($valid['ticket_obj'][$x] instanceof EE_Ticket) {
                         // then add ticket to cart
                         $ticket_added = self::_add_ticket_to_cart($valid['ticket_obj'][$x], $valid['qty'][$x]);
                         $success = !$ticket_added ? FALSE : $success;
                         if (EE_Error::has_error()) {
                             break;
                         }
                     } else {
                         // nothing added to cart retrieved
                         EE_Error::add_error(sprintf(__('A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.', 'event_espresso'), '<br/>'), __FILE__, __FUNCTION__, __LINE__);
                     }
                 }
             }
             //d( EE_Registry::instance()->CART );
             //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
             if ($tckts_slctd) {
                 if ($success) {
                     do_action('FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout', EE_Registry::instance()->CART, $this);
                     EE_Registry::instance()->CART->recalculate_all_cart_totals();
                     EE_Registry::instance()->CART->save_cart(FALSE);
                     EE_Registry::instance()->SSN->update();
                     //d( EE_Registry::instance()->CART );
                     //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< OR HERE TO KILL REDIRECT AFTER CART UPDATE
                     // just return TRUE for registrations being made from admin
                     if (is_admin()) {
                         return TRUE;
                     }
                     wp_safe_redirect(apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url', EE_Registry::instance()->CFG->core->reg_page_url()));
                     exit;
                 } else {
                     if (!EE_Error::has_error()) {
                         // nothing added to cart
                         EE_Error::add_attention(__('No tickets were added for the event', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
                     }
                 }
             } else {
                 // no ticket quantities were selected
                 EE_Error::add_error(__('You need to select a ticket quantity before you can proceed.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
             }
         }
         //die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
         // at this point, just return if registration is being made from admin
         if (is_admin()) {
             return FALSE;
         }
         if ($valid['return_url']) {
             EE_Error::get_notices(FALSE, TRUE);
             wp_safe_redirect($valid['return_url']);
             exit;
         } elseif (isset($event_to_add['id'])) {
             EE_Error::get_notices(FALSE, TRUE);
             wp_safe_redirect(get_permalink($event_to_add['id']));
             exit;
         } else {
             echo EE_Error::get_notices();
         }
     } else {
         // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
         EE_Error::add_error(sprintf(__('An event id was not provided or was not received.%sPlease click the back button on your browser and try again.', 'event_espresso'), '<br/>'), __FILE__, __FUNCTION__, __LINE__);
     }
     return FALSE;
 }
 /**
  * debug_logging_options
  *
  * @param array $template_args
  * @return void
  */
 public function debug_logging_options($template_args = array())
 {
     if (EE_Registry::instance()->CFG->admin->use_full_logging === NULL) {
         $this->_request_filesystem_credentials(FALSE);
         $template_args['use_full_logging'] = TRUE;
         EE_Error::get_notices(FALSE);
         EE_Error::reset_notices();
         EE_Error::add_attention(__('In order to enable Full Logging, the connection settings below are required.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         echo EE_Error::get_notices();
     } else {
         $template_args['use_full_logging'] = EE_Registry::instance()->CFG->admin->use_full_logging;
     }
     $template_args['use_remote_logging'] = isset(EE_Registry::instance()->CFG->admin->use_remote_logging) ? absint(EE_Registry::instance()->CFG->admin->use_remote_logging) : FALSE;
     $template_args['remote_logging_url'] = isset(EE_Registry::instance()->CFG->admin->remote_logging_url) && !empty(EE_Registry::instance()->CFG->admin->remote_logging_url) ? stripslashes(EE_Registry::instance()->CFG->admin->remote_logging_url) : '';
     $template = GEN_SET_CAF_TEMPLATE_PATH . 'debug_log_settings.template.php';
     EEH_Template::display_template($template, $template_args);
 }
 /**
  * Activates a payment method of the given type.
  *
  * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
  * @return \EE_Payment_Method
  * @throws \EE_Error
  */
 public function activate_a_payment_method_of_type($payment_method_type)
 {
     $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
     if (!$payment_method instanceof EE_Payment_Method) {
         $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
         if (class_exists($pm_type_class)) {
             /** @var $pm_type_obj EE_PMT_Base */
             $pm_type_obj = new $pm_type_class();
             $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
             if (!$payment_method) {
                 $payment_method = $this->create_payment_method_of_type($pm_type_obj);
             }
             $payment_method->set_type($payment_method_type);
             $this->initialize_payment_method($payment_method);
         } else {
             throw new EE_Error(sprintf(__('There is no payment method of type %1$s, so it could not be activated', 'event_espresso'), $pm_type_class));
         }
     }
     $payment_method->set_active();
     $payment_method->save();
     $this->set_usable_currencies_on_payment_method($payment_method);
     if ($payment_method->type() === 'Invoice') {
         /** @type EE_Message_Resource_Manager $message_resource_manager */
         $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
         $message_resource_manager->ensure_message_type_is_active('invoice', 'html');
         $message_resource_manager->ensure_messenger_is_active('pdf');
         EE_Error::add_attention(sprintf(__('Note, when the invoice payment method is activated, the invoice message type, html messenger, and pdf messenger are activated as well for the %1$smessages system%2$s.', 'event_espresso'), '<a href="' . admin_url('admin.php?page=espresso_messages') . '">', '</a>'));
     }
     return $payment_method;
 }
 /**
  * Verifies the button urls on all the passed payment methods have a valid button url. If not, resets them to their default.
  * @param EE_Payment_Method[] $payment_methods. If NULL is provided defaults to all payment methods active in the cart
  */
 function verify_button_urls($payment_methods = NULL)
 {
     $payment_methods = is_array($payment_methods) ? $payment_methods : $this->get_all_active(EEM_Payment_Method::scope_cart);
     foreach ($payment_methods as $payment_method) {
         try {
             $current_button_url = $payment_method->button_url();
             $buttons_urls_to_try = apply_filters('FHEE__EEM_Payment_Method__verify_button_urls__button_urls_to_try', array('current_ssl' => str_replace("http://", "https://", $current_button_url), 'current' => str_replace("https://", "http://", $current_button_url), 'default_ssl' => str_replace("http://", "https://", $payment_method->type_obj()->default_button_url()), 'default' => str_replace("https://", "http://", $payment_method->type_obj()->default_button_url())));
             foreach ($buttons_urls_to_try as $button_url_to_try) {
                 if ($button_url_to_try == $current_button_url && EEH_URL::remote_file_exists($button_url_to_try, array('sslverify' => false, 'limit_response_size' => 4095)) || $button_url_to_try != $current_button_url && EEH_URL::remote_file_exists($button_url_to_try)) {
                     if ($current_button_url != $button_url_to_try) {
                         $payment_method->save(array('PMD_button_url' => $button_url_to_try));
                         EE_Error::add_attention(sprintf(__("Payment Method %s's button url was set to %s, because the old image either didnt exist or SSL was recently enabled.", "event_espresso"), $payment_method->name(), $button_url_to_try));
                     }
                     //this image exists. So if wasn't set before, now it is;
                     //or if it was already set, we have nothing to do
                     break;
                 }
             }
         } catch (EE_Error $e) {
             $payment_method->set_active(FALSE);
         }
     }
 }
 /**
  * This sets up the appropriate response for deactivating a messenger and/or message type.
  *
  * @param EE_messenger         $messenger
  * @param EE_message_type|null $message_type
  *
  * @return bool
  */
 protected function _setup_response_message_for_deactivating_messenger_with_message_types($messenger, EE_message_type $message_type = null)
 {
     EE_Error::overwrite_success();
     //if $messenger isn't a valid messenger object then get out.
     if (!$messenger instanceof EE_Messenger) {
         EE_Error::add_error(__('The messenger being deactivated is not a valid messenger', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         return false;
     }
     if ($message_type instanceof EE_message_type) {
         $message_type_name = $message_type->name;
         EE_Error::add_success(sprintf(__('%s message type has been successfully deactivated for the %s messenger.', 'event_espresso'), ucwords($message_type->label['singular']), ucwords($messenger->label['singular'])));
     } else {
         $message_type_name = '';
         EE_Error::add_success(sprintf(__('%s messenger has been successfully deactivated.', 'event_espresso'), ucwords($messenger->label['singular'])));
     }
     //if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
     if ($messenger->name == 'html' || $message_type_name == 'invoice') {
         EE_Registry::instance()->load_lib('Payment_Method_Manager');
         $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
         if ($count_updated > 0) {
             $msg = $message_type_name == 'invoice' ? __('Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.', 'event_espresso') : __('Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.', 'event_espresso');
             EE_Error::add_attention($msg);
         }
     }
     return true;
 }
 /**
  * Activates a payment method of the given type.
  * @global type $current_user
  * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
  * @return EE_Payment_Method
  */
 public function activate_a_payment_method_of_type($payment_method_type)
 {
     $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
     if (!$payment_method) {
         global $current_user;
         $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
         if (class_exists($pm_type_class)) {
             /** @var $pm_type_obj EE_PMT_Base */
             $pm_type_obj = new $pm_type_class();
             $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
             if (!$payment_method) {
                 $payment_method = EE_Payment_Method::new_instance(array('PMD_type' => $pm_type_obj->system_name(), 'PMD_name' => $pm_type_obj->pretty_name(), 'PMD_admin_name' => $pm_type_obj->pretty_name(), 'PMD_slug' => $pm_type_obj->system_name(), 'PMD_wp_user' => $current_user->ID, 'PMD_order' => EEM_Payment_Method::instance()->count(array(array('PMD_type' => array('!=', 'Admin_Only')))) * 10));
             }
             $payment_method->set_active();
             $payment_method->set_description($pm_type_obj->default_description());
             //handles the goofy case where someone activates the invoice gateway which is also
             $payment_method->set_type($pm_type_obj->system_name());
             if (!$payment_method->button_url()) {
                 $payment_method->set_button_url($pm_type_obj->default_button_url());
             }
             $payment_method->save();
             foreach ($payment_method->get_all_usable_currencies() as $currency_obj) {
                 $payment_method->_add_relation_to($currency_obj, 'Currency');
             }
             //now add setup its default extra meta properties
             $extra_metas = $payment_method->type_obj()->settings_form()->extra_meta_inputs();
             foreach ($extra_metas as $meta_name => $input) {
                 $payment_method->update_extra_meta($meta_name, $input->raw_value());
             }
         }
     } else {
         $payment_method->set_active();
         $payment_method->save();
     }
     if ($payment_method->type() == 'Invoice') {
         $messages = EE_Registry::instance()->load_lib('messages');
         $messages->ensure_message_type_is_active('invoice', 'html');
         $messages->ensure_messenger_is_active('pdf');
         EE_Error::add_attention(sprintf(__('Note, when the invoice payment method is activated, the invoice message type, html messenger, and pdf messenger are activated as well for the %1$smessages system%2$s.', 'event_espresso'), '<a href="' . admin_url('admin.php?page=espresso_messages') . '">', '</a>'));
     }
     return $payment_method;
 }
 /**
  * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
  * but also verifies the payment method type of each is a usable object. If not,
  * deactivate it, sets a notification, and deactivates it
  * @param array $rows
  * @return EE_Payment_Method[]
  */
 protected function _create_objects($rows = array())
 {
     $payment_methods = parent::_create_objects($rows);
     /* @var $payment_methods EE_Payment_Method[] */
     $usable_payment_methods = array();
     foreach ($payment_methods as $key => $payment_method) {
         try {
             $payment_method->type_obj();
             $usable_payment_methods[$key] = $payment_method;
         } catch (EE_Error $e) {
             //if it threw an exception, its because the payment type object
             //isn't defined (probably because somehow the DB got borked,
             //or an addon which defined it got deactivated
             //so deactivate it and move on
             $payment_method->deactivate();
             $payment_method->save();
             EE_Error::add_attention(sprintf(__("There is no payment method type '%s', so the payment method '%s' was deactivated", "event_espresso"), $payment_method->type(), $payment_method->name()), __FILE__, __FUNCTION__, __LINE__);
         }
     }
     return $usable_payment_methods;
 }
 /**
  * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a warning (via EE_Error::add_error());
  *
  * @param  EE_Event    $event 	Event object
  * @access public
  * @return void
  */
 public function verify_event_edit($event = NULL)
 {
     // no event?
     if (empty($event)) {
         // set event
         $event = $this->_cpt_model_obj;
     }
     // STILL no event?
     if (empty($event)) {
         return;
     }
     // first check if event is active.
     if ($event->is_expired() || $event->is_inactive() || $event->status() == EEM_Event::cancelled || $event->status() == EEM_Event::postponed) {
         return;
     }
     $orig_status = $event->status();
     //made it here so it IS active... next check that any of the tickets are sold.
     if ($event->is_sold_out(true)) {
         if ($event->status() !== $orig_status && $orig_status !== EEM_Event::sold_out) {
             EE_Error::add_attention(sprintf(__('Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.', 'event_espresso'), EEH_Template::pretty_status(EEM_Event::sold_out, FALSE, 'sentence')));
         }
         return;
     } else {
         if ($orig_status === EEM_Event::sold_out) {
             EE_Error::add_attention(sprintf(__('Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.', 'event_espresso'), EEH_Template::pretty_status($event->status(), false, 'sentence')));
         }
     }
     //now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
     if (!$event->tickets_on_sale()) {
         return;
     }
     //made it here so show warning
     EE_Error::add_attention($this->_edit_event_warning());
 }
 /**
  * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
  * but also verifies the payment method type of each is a usable object. If not,
  * deactivate it, sets a notification, and deactivates it
  * @param array $rows
  * @return EE_Payment_Method[]
  */
 protected function _create_objects($rows = array())
 {
     $payment_methods = parent::_create_objects($rows);
     /* @var $payment_methods EE_Payment_Method[] */
     $usable_payment_methods = array();
     foreach ($payment_methods as $key => $payment_method) {
         try {
             $payment_method->type_obj();
             $usable_payment_methods[$key] = $payment_method;
         } catch (EE_Error $e) {
             //if it threw an exception, its because the payment type object
             //isn't defined (probably because somehow the DB got borked,
             //or an addon which defined it got deactivated
             //so deactivate it and move on
             $payment_method->deactivate();
             $payment_method->save();
             EE_Error::add_attention(sprintf(__('An error occurred while attempting to use the "%1$s" payment method, so it was deactivated.%2$sWas the "%1$s" Plugin recently deactivated?%2$sIt can be reactivated on the %3$sPlugins admin page%4$s||%2$sThe actual error was:%2$s%5$s', 'event_espresso'), $payment_method->name(), '<br />', '<a href="' . admin_url('plugins.php') . '">', '</a>', $e->getMessage()), __FILE__, __FUNCTION__, __LINE__);
         }
     }
     return $usable_payment_methods;
 }
 /**
  * This is the text used for when an event is being edited that is public and has tickets for sale.
  * When needed, hook this into a EE_Error::add_error() notice.
  *
  * @access protected
  * @return string
  */
 protected function _edit_event_warning()
 {
     // we don't want to add warnings during these requests
     if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
         return;
     }
     EE_Error::add_attention(__('Please be advised that this event has been published and is open for registrations on your website. If you update any registration-related details (i.e. custom questions, messages, tickets, datetimes, etc.) while a registration is in process, the registration process could be interrupted and result in errors for the person registering and potentially incorrect registration or transaction data inside Event Espresso. We recommend editing events during a period of slow traffic, or even temporarily changing the status of an event to "Draft" until your edits are complete.', 'event_espresso'));
 }
 /**
  * plugin_uninstall
  *
  * @access public
  * @static
  * @param bool $remove_all
  * @return void
  */
 public static function delete_all_espresso_tables_and_data($remove_all = true)
 {
     global $wpdb;
     $undeleted_tables = array();
     // load registry
     foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
         if (method_exists($model_name, 'instance')) {
             $model_obj = call_user_func(array($model_name, 'instance'));
             if ($model_obj instanceof EEM_Base) {
                 foreach ($model_obj->get_tables() as $table) {
                     if (strpos($table->get_table_name(), 'esp_')) {
                         switch (EEH_Activation::delete_unused_db_table($table->get_table_name())) {
                             case false:
                                 $undeleted_tables[] = $table->get_table_name();
                                 break;
                             case 0:
                                 // echo '<h4 style="color:red;">the table : ' . $table->get_table_name() . ' was not deleted  <br /></h4>';
                                 break;
                             default:
                                 // echo '<h4>the table : ' . $table->get_table_name() . ' was deleted successfully <br /></h4>';
                         }
                     }
                 }
             }
         }
     }
     //there are some tables whose models were removed.
     //they should be removed when removing all EE core's data
     $tables_without_models = array('esp_promotion', 'esp_promotion_applied', 'esp_promotion_object', 'esp_promotion_rule', 'esp_rule');
     foreach ($tables_without_models as $table) {
         EEH_Activation::delete_db_table_if_empty($table);
     }
     $wp_options_to_delete = array('ee_no_ticket_prices' => true, 'ee_active_messengers' => true, 'ee_has_activated_messenger' => true, 'ee_flush_rewrite_rules' => true, 'ee_config' => false, 'ee_data_migration_current_db_state' => true, 'ee_data_migration_mapping_' => false, 'ee_data_migration_script_' => false, 'ee_data_migrations' => true, 'ee_dms_map' => false, 'ee_notices' => true, 'lang_file_check_' => false, 'ee_maintenance_mode' => true, 'ee_ueip_optin' => true, 'ee_ueip_has_notified' => true, 'ee_plugin_activation_errors' => true, 'ee_id_mapping_from' => false, 'espresso_persistent_admin_notices' => true, 'ee_encryption_key' => true, 'pue_force_upgrade_' => false, 'pue_json_error_' => false, 'pue_install_key_' => false, 'pue_verification_error_' => false, 'pu_dismissed_upgrade_' => false, 'external_updates-' => false, 'ee_extra_data' => true, 'ee_ssn_' => false, 'ee_rss_' => false, 'ee_rte_n_tx_' => false, 'ee_pers_admin_notices' => true, 'ee_job_parameters_' => false, 'ee_upload_directories_incomplete' => true);
     if (is_main_site()) {
         $wp_options_to_delete['ee_network_config'] = true;
     }
     $undeleted_options = array();
     foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
         if ($no_wildcard) {
             if (!delete_option($option_name)) {
                 $undeleted_options[] = $option_name;
             }
         } else {
             $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%{$option_name}%'");
             foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
                 if (!delete_option($option_name_from_wildcard)) {
                     $undeleted_options[] = $option_name_from_wildcard;
                 }
             }
         }
     }
     //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
     remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
     if ($remove_all && ($espresso_db_update = get_option('espresso_db_update'))) {
         $db_update_sans_ee4 = array();
         foreach ($espresso_db_update as $version => $times_activated) {
             if ($version[0] == '3') {
                 //if its NON EE4
                 $db_update_sans_ee4[$version] = $times_activated;
             }
         }
         update_option('espresso_db_update', $db_update_sans_ee4);
     }
     $errors = '';
     if (!empty($undeleted_tables)) {
         $errors .= sprintf(__('The following tables could not be deleted: %s%s', 'event_espresso'), '<br/>', implode(',<br/>', $undeleted_tables));
     }
     if (!empty($undeleted_options)) {
         $errors .= !empty($undeleted_tables) ? '<br/>' : '';
         $errors .= sprintf(__('The following wp-options could not be deleted: %s%s', 'event_espresso'), '<br/>', implode(',<br/>', $undeleted_options));
     }
     if ($errors != '') {
         EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
     }
 }
 /**
  *	Given an array of data (usually from a CSV import) attempts to save that data to the db.
  *	If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
  *	next level being numeric indexes adn each value representing a model object, and the last layer down
  *	being keys of model fields and their proposed values.
  *	If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
  *	If the CSV data says (in the metadata row) that it's from the SAME database,
  *	we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
  *	IDs DON'T exist in the database, they're treated as temporary IDs,
  *	which can used elsewhere to refer to the same object. Once an item
  *	with a temporary ID gets inserted, we record its mapping from temporary
  *	ID to real ID, and use the real ID in place of the temporary ID
  *	when that temporary ID was used as a foreign key.
  *	If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
  *	we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
  *	ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
  *	and insert a new event, and map it's temporary ID of 1 over to its new real ID.
  *	An important exception are non-auto-increment primary keys. If one entry in the
  *	CSV file has the same ID as one in the DB, we assume they are meant to be
  *	the same item, and instead update the item in the DB with that same ID.
  *	Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
  *	time you import a CSV from a different site, we remember their mappings, and
  * will try to update the item in the DB instead of inserting another item (eg
  * if we previously imported an event with temporary ID 1, and then it got a
  * real ID of 123, we remember that. So the next time we import an event with
  * temporary ID, from the same site, we know that it's real ID is 123, and will
  * update that event, instead of adding a new event).
  *		  @access public
  *			@param array $csv_data_array - the array containing the csv data produced from EE_CSV::import_csv_to_model_data_array()
  *			@param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table fields they will be saved to
  *			@return TRUE on success, FALSE on fail
  */
 public function save_csv_data_array_to_db($csv_data_array, $model_name = FALSE)
 {
     $success = FALSE;
     $error = FALSE;
     //whther to treat this import as if it's data froma different database or not
     //ie, if it IS from a different database, ignore foreign keys whihf
     $export_from_site_a_to_b = true;
     // first level of array is not table information but a table name was passed to the function
     // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
     if ($model_name) {
         $csv_data_array = array($csv_data_array);
     }
     // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
     $old_site_url = 'none-specified';
     //hanlde metadata
     if (isset($csv_data_array[EE_CSV::metadata_header])) {
         $csv_metadata = array_shift($csv_data_array[EE_CSV::metadata_header]);
         //ok so its metadata, dont try to save it to ehte db obviously...
         if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
             EE_Error::add_attention(sprintf(__("CSV Data appears to be from the same database, so attempting to update data", "event_espresso")));
             $export_from_site_a_to_b = false;
         } else {
             $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
             EE_Error::add_attention(sprintf(__("CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database", "event_espresso"), $old_site_url, site_url()));
         }
         unset($csv_data_array[EE_CSV::metadata_header]);
     }
     /**
      * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
      * the value will be the newly-inserted ID.
      * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
      */
     $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
     if ($old_db_to_new_db_mapping) {
         EE_Error::add_attention(sprintf(__("We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s", "event_espresso"), $old_site_url, site_url()));
     }
     $old_db_to_new_db_mapping = $this->save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping);
     //save the mapping from old db to new db in case they try re-importing the same data from the same website again
     update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping);
     if ($this->_total_updates > 0) {
         EE_Error::add_success(sprintf(__("%s existing records in the database were updated.", "event_espresso"), $this->_total_updates));
         $success = true;
     }
     if ($this->_total_inserts > 0) {
         EE_Error::add_success(sprintf(__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts));
         $success = true;
     }
     if ($this->_total_update_errors > 0) {
         EE_Error::add_error(sprintf(__("'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", "event_espresso"), $this->_total_update_errors), __FILE__, __FUNCTION__, __LINE__);
         $error = true;
     }
     if ($this->_total_insert_errors > 0) {
         EE_Error::add_error(sprintf(__("One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", "event_espresso"), $this->_total_insert_errors), __FILE__, __FUNCTION__, __LINE__);
         $error = true;
     }
     //lastly, we need to update the datetime and ticket sold amounts
     //as those may ahve been affected by this
     EEM_Datetime::instance()->update_sold(EEM_Datetime::instance()->get_all());
     EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
     // if there was at least one success and absolutely no errors
     if ($success && !$error) {
         return TRUE;
     } else {
         return FALSE;
     }
 }