pause(); // use our own error handler set_error_handler(array('ImportViewStep4','handleImportErrors'),E_ALL); global $mod_strings, $app_strings, $current_user, $import_bean_map; global $app_list_strings, $timedate; $update_only = ( isset($_REQUEST['import_type']) && $_REQUEST['import_type'] == 'update' ); $firstrow = unserialize(base64_decode($_REQUEST['firstrow'])); // All the Look Up Caches are initialized here $enum_lookup_cache=array(); // setup the importable fields array. $importable_fields = $this->bean->get_importable_fields(); // loop through all request variables $importColumns = array(); foreach ($_REQUEST as $name => $value) { // only look for var names that start with "fieldNum" if (strncasecmp($name, "colnum_", 7) != 0) { continue; } // pull out the column position for this field name $pos = substr($name, 7); if ( isset($importable_fields[$value]) ) { // now mark that we've seen this field $importColumns[$pos] = $value; } } // set the default locale settings $ifs = new ImportFieldSanitize(); $ifs->dateformat = $_REQUEST['importlocale_dateformat']; $ifs->timeformat = $_REQUEST['importlocale_timeformat']; $ifs->timezone = $_REQUEST['importlocale_timezone']; $currency = new Currency(); $currency->retrieve($_REQUEST['importlocale_currency']); $ifs->currency_symbol = $currency->symbol; $ifs->default_currency_significant_digits = $_REQUEST['importlocale_default_currency_significant_digits']; $ifs->num_grp_sep = $_REQUEST['importlocale_num_grp_sep']; $ifs->dec_sep = $_REQUEST['importlocale_dec_sep']; $ifs->default_locale_name_format = $_REQUEST['importlocale_default_locale_name_format']; // Check to be sure we are getting an import file that is in the right place if ( realpath(dirname($_REQUEST['tmp_file']).'/') != realpath($sugar_config['upload_dir']) ) trigger_error($mod_strings['LBL_CANNOT_OPEN'],E_USER_ERROR); // Open the import file $importFile = new ImportFile( $_REQUEST['tmp_file'], $_REQUEST['custom_delimiter'], html_entity_decode($_REQUEST['custom_enclosure'],ENT_QUOTES) ); if ( !$importFile->fileExists() ) { trigger_error($mod_strings['LBL_CANNOT_OPEN'],E_USER_ERROR); } $fieldDefs = $this->bean->getFieldDefinitions(); while ( $row = $importFile->getNextRow() ) { $focus = clone $this->bean; $focus->unPopulateDefaultValues(); $focus->save_from_post = false; $focus->team_id = null; $ifs->createdBeans = array(); $do_save = true; for ( $fieldNum = 0; $fieldNum < $_REQUEST['columncount']; $fieldNum++ ) { // loop if this column isn't set if ( !isset($importColumns[$fieldNum]) ) { continue; } // get this field's properties $field = $importColumns[$fieldNum]; $fieldDef = $focus->getFieldDefinition($field); $fieldTranslated = translate((isset($fieldDef['vname'])?$fieldDef['vname']:$fieldDef['name']), $_REQUEST['module'])." (".$fieldDef['name'].")"; // Bug 37241 - Don't re-import over a field we already set during the importing of another field if ( !empty($focus->$field) ) { continue; } //DETERMINE WHETHER OR NOT $fieldDef['name'] IS DATE_MODIFIED AND SET A VAR, USE DOWN BELOW // translate strings global $locale; if(empty($locale)) { $locale = new Localization(); } if ( isset($row[$fieldNum]) ) $rowValue = $locale->translateCharset( strip_tags(trim($row[$fieldNum])), $_REQUEST['importlocale_charset'], $sugar_config['default_charset'] ); else $rowValue = ''; // If there is an default value then use it instead if ( !empty($_REQUEST[$field]) ) { if ( is_array($_REQUEST[$field]) ) $defaultRowValue = encodeMultienumValue($_REQUEST[$field]); else $defaultRowValue = $_REQUEST[$field]; // translate default values to the date/time format for the import file if ( $fieldDef['type'] == 'date' && $ifs->dateformat != $timedate->get_date_format() ) $defaultRowValue = $timedate->swap_formats( $defaultRowValue, $ifs->dateformat, $timedate->get_date_format()); if ( $fieldDef['type'] == 'time' && $ifs->timeformat != $timedate->get_time_format() ) $defaultRowValue = $timedate->swap_formats( $defaultRowValue, $ifs->timeformat, $timedate->get_time_format()); if ( ($fieldDef['type'] == 'datetime' || $fieldDef['type'] == 'datetimecombo') && $ifs->dateformat.' '.$ifs->timeformat != $timedate->get_date_time_format() ) $defaultRowValue = $timedate->swap_formats( $defaultRowValue, $ifs->dateformat.' '.$ifs->timeformat, $timedate->get_date_time_format()); if ( in_array($fieldDef['type'],array('currency','float','int','num')) && $ifs->num_grp_sep != $current_user->getPreference('num_grp_sep') ) $defaultRowValue = str_replace($current_user->getPreference('num_grp_sep'), $ifs->num_grp_sep,$defaultRowValue); if ( in_array($fieldDef['type'],array('currency','float')) && $ifs->dec_sep != $current_user->getPreference('dec_sep') ) $defaultRowValue = str_replace($current_user->getPreference('dec_sep'), $ifs->dec_sep,$defaultRowValue); $currency->retrieve('-99'); $user_currency_symbol = $currency->symbol; if ( $fieldDef['type'] == 'currency' && $ifs->currency_symbol != $user_currency_symbol ) $defaultRowValue = str_replace($user_currency_symbol, $ifs->currency_symbol,$defaultRowValue); if ( empty($rowValue) ) { $rowValue = $defaultRowValue; unset($defaultRowValue); } } // Bug 22705 - Don't update the First Name or Last Name value if Full Name is set if ( in_array($field, array('first_name','last_name')) && !empty($focus->full_name) ) continue; // loop if this value has not been set if ( !isset($rowValue) ) continue; // If the field is required and blank then error out if ( array_key_exists($field,$focus->get_import_required_fields()) && empty($rowValue) && $rowValue!='0') { $importFile->writeError( $mod_strings['LBL_REQUIRED_VALUE'], $fieldTranslated, 'NULL' ); $do_save = false; } // Handle the special case "Sync to Outlook" if ( $focus->object_name == "Contacts" && $field == 'sync_contact' ) { $bad_names = array(); $returnValue = $ifs->synctooutlook( $rowValue, $fieldDef, $bad_names); // try the default value on fail if ( !$returnValue && !empty($defaultRowValue) ) $returnValue = $ifs->synctooutlook( $defaultRowValue, $fieldDef, $bad_names); if ( !$returnValue ) { $importFile->writeError( $mod_strings['LBL_ERROR_SYNC_USERS'], $fieldTranslated, explode(",",$bad_names)); $do_save = 0; } } // Handle email1 and email2 fields ( these don't have the type of email ) if ( $field == 'email1' || $field == 'email2' ) { $returnValue = $ifs->email($rowValue, $fieldDef, $focus); // try the default value on fail if ( !$returnValue && !empty($defaultRowValue) ) $returnValue = $ifs->email( $defaultRowValue, $fieldDef); if ( $returnValue === FALSE ) { $do_save=0; $importFile->writeError( $mod_strings['LBL_ERROR_INVALID_EMAIL'], $fieldTranslated, $rowValue); } else { $rowValue = $returnValue; // check for current opt_out and invalid email settings for this email address // if we find any, set them now $emailres = $focus->db->query( "SELECT opt_out, invalid_email FROM email_addresses WHERE email_address = '".$focus->db->quote($rowValue)."'"); if ( $emailrow = $focus->db->fetchByAssoc($emailres) ) { $focus->email_opt_out = $emailrow['opt_out']; $focus->invalid_email = $emailrow['invalid_email']; } } } // Handle splitting Full Name into First and Last Name parts if ( $field == 'full_name' && !empty($rowValue) ) { $ifs->fullname( $rowValue, $fieldDef, $focus); } // to maintain 451 compatiblity if(!isset($fieldDef['module']) && $fieldDef['type']=='relate') $fieldDef['module'] = ucfirst($fieldDef['table']); if(isset($fieldDef['custom_type']) && !empty($fieldDef['custom_type'])) $fieldDef['type'] = $fieldDef['custom_type']; // If the field is empty then there is no need to check the data if( !empty($rowValue) ) { switch ($fieldDef['type']) { case 'enum': case 'multienum': if ( isset($fieldDef['type']) && $fieldDef['type'] == "multienum" ) $returnValue = $ifs->multienum($rowValue,$fieldDef); else $returnValue = $ifs->enum($rowValue,$fieldDef); // try the default value on fail if ( !$returnValue && !empty($defaultRowValue) ) if ( isset($fieldDef['type']) && $fieldDef['type'] == "multienum" ) $returnValue = $ifs->multienum($defaultRowValue,$fieldDef); else $returnValue = $ifs->enum($defaultRowValue,$fieldDef); if ( $returnValue === FALSE ) { $importFile->writeError( $mod_strings['LBL_ERROR_NOT_IN_ENUM'] . implode(",",$app_list_strings[$fieldDef['options']]), $fieldTranslated, $rowValue); $do_save = 0; } else $rowValue = $returnValue; break; case 'relate': case 'parent': $returnValue = $ifs->relate( $rowValue, $fieldDef, $focus, empty($defaultRowValue)); if ( !$returnValue && !empty($defaultRowValue) ) $returnValue = $ifs->relate( $defaultRowValue, $fieldDef, $focus); // Bug 33623 - Set the id value found from the above method call as an importColumn if ( $returnValue !== false ) $importColumns[] = $fieldDef['id_name']; break; case 'teamset': $returnValue = $ifs->teamset( $rowValue, $fieldDef, $focus); $importColumns[] = 'team_set_id'; $importColumns[] = 'team_id'; break; case 'fullname': break; default: $fieldtype = $fieldDef['type']; $returnValue = $ifs->$fieldtype($rowValue, $fieldDef, $focus); // try the default value on fail if ( !$returnValue && !empty($defaultRowValue) ) $returnValue = $ifs->$fieldtype( $defaultRowValue, $fieldDef, $focus); if ( !$returnValue ) { $do_save=0; $importFile->writeError( $mod_strings['LBL_ERROR_INVALID_'.strtoupper($fieldDef['type'])], $fieldTranslated, $rowValue, $focus); } else { $rowValue = $returnValue; } } } $focus->$field = $rowValue; unset($defaultRowValue); } // Now try to validate flex relate fields if ( isset($focus->field_defs['parent_name']) && isset($focus->parent_name) && ($focus->field_defs['parent_name']['type'] == 'parent') ) { // populate values from the picker widget if the import file doesn't have them $parent_idField = $focus->field_defs['parent_name']['id_name']; if ( empty($focus->$parent_idField) && !empty($_REQUEST[$parent_idField]) ) $focus->$parent_idField = $_REQUEST[$parent_idField]; $parent_typeField = $focus->field_defs['parent_name']['type_name']; if ( empty($focus->$parent_typeField) && !empty($_REQUEST[$parent_typeField]) ) $focus->$parent_typeField = $_REQUEST[$parent_typeField]; // now validate it $returnValue = $ifs->parent( $focus->parent_name, $focus->field_defs['parent_name'], $focus, empty($_REQUEST['parent_name'])); if ( !$returnValue && !empty($_REQUEST['parent_name']) ) $returnValue = $ifs->parent( $_REQUEST['parent_name'], $focus->field_defs['parent_name'], $focus); } // check to see that the indexes being entered are unique. if (isset($_REQUEST['display_tabs_def']) && $_REQUEST['display_tabs_def'] != ""){ $idc = new ImportDuplicateCheck($focus); if ( $idc->isADuplicateRecord(explode('&', $_REQUEST['display_tabs_def'])) ){ $importFile->markRowAsDuplicate(); $this->_undoCreatedBeans($ifs->createdBeans); continue; } } // if the id was specified $newRecord = true; if ( !empty($focus->id) ) { $focus->id = $this->_convertId($focus->id); // check if it already exists $query = "SELECT * FROM {$focus->table_name} WHERE id='".$focus->db->quote($focus->id)."'"; $result = $focus->db->query($query) or sugar_die("Error selecting sugarbean: "); $dbrow = $focus->db->fetchByAssoc($result); if (isset ($dbrow['id']) && $dbrow['id'] != -1) { // if it exists but was deleted, just remove it if (isset ($dbrow['deleted']) && $dbrow['deleted'] == 1 && $update_only==false) { $query2 = "DELETE FROM {$focus->table_name} WHERE id='".$focus->db->quote($focus->id)."'"; $result2 = $focus->db->query($query2) or sugar_die($mod_strings['LBL_ERROR_DELETING_RECORD']." ".$focus->id); if ($focus->hasCustomFields()) { $query3 = "DELETE FROM {$focus->table_name}_cstm WHERE id_c='".$focus->db->quote($focus->id)."'"; $result2 = $focus->db->query($query3); } $focus->new_with_id = true; } else { if( !$update_only ) { $do_save = 0; $importFile->writeError($mod_strings['LBL_ID_EXISTS_ALREADY'],'ID',$focus->id); $this->_undoCreatedBeans($ifs->createdBeans); continue; } $existing_focus = clone $this->bean; $newRecord = false; if ( !( $existing_focus->retrieve($dbrow['id']) instanceOf SugarBean ) ) { $do_save = 0; $importFile->writeError($mod_strings['LBL_RECORD_CANNOT_BE_UPDATED'],'ID',$focus->id); $this->_undoCreatedBeans($ifs->createdBeans); continue; } else { $newData = $focus->toArray(); foreach ( $newData as $focus_key => $focus_value ) if ( in_array($focus_key,$importColumns) ) $existing_focus->$focus_key = $focus_value; $focus = $existing_focus; $focus->update_date_entered = true; } unset($existing_focus); } } else { $focus->new_with_id = true; } } if ($do_save) { // Populate in any default values to the bean $focus->populateDefaultValues(); if ( !isset($focus->assigned_user_id) || $focus->assigned_user_id == '' && $newRecord ) { $focus->assigned_user_id = $current_user->id; } /* * Bug 34854: Added all conditions besides the empty check on date modified. Currently, if * we do an update to a record, it doesn't update the date_modified value. * Hack note: I'm doing a to_display and back to_db on the fetched row to make sure that any truncating that happens * when $focus->date_modified goes to_display and back to_db also happens on the fetched db value. Otherwise, * in some cases we truncate the seconds on one and not the other, and the comparison fails when it should pass */ if ( ( !empty($focus->new_with_id) && !empty($focus->date_modified) ) || ( empty($focus->new_with_id) && $timedate->to_db($focus->date_modified) != $timedate->to_db($timedate->to_display_date_time($focus->fetched_row['date_modified'])) ) ) $focus->update_date_modified = false; $focus->optimistic_lock = false; if ( $focus->object_name == "Contacts" && isset($focus->sync_contact) ) { //copy the potential sync list to another varible $list_of_users=$focus->sync_contact; //and set it to false for the save $focus->sync_contact=false; } else if($focus->object_name == "User" && (empty($current_user) || !$current_user->isAdminForModule( 'Users'))) { sugar_die($GLOBALS['mod_strings']['ERR_IMPORT_SYSTEM_ADMININSTRATOR']); } //bug# 40260 setting it true as the module in focus is involved in an import $focus->in_import=true; // call any logic needed for the module preSave $focus->beforeImportSave(); $focus->save(false); // call any logic needed for the module postSave $focus->afterImportSave(); if ( $focus->object_name == "Contacts" && isset($list_of_users) ) $focus->process_sync_to_outlook($list_of_users); // Update the created/updated counter $importFile->markRowAsImported($newRecord); // Add ID to User's Last Import records if ( $newRecord ) ImportFile::writeRowToLastImport( $_REQUEST['import_module'], ($focus->object_name == 'Case' ? 'aCase' : $focus->object_name), $focus->id); } else $this->_undoCreatedBeans($ifs->createdBeans); unset($defaultRowValue); } // save mapping if requested if ( isset($_REQUEST['save_map_as']) && $_REQUEST['save_map_as'] != '' ) { $mapping_file = new ImportMap(); if ( isset($_REQUEST['has_header']) && $_REQUEST['has_header'] == 'on') { $header_to_field = array (); foreach ($importColumns as $pos => $field_name) { if (isset($firstrow[$pos]) && isset($field_name)) { $header_to_field[$firstrow[$pos]] = $field_name; } } $mapping_file->setMapping($header_to_field); } else { $mapping_file->setMapping($importColumns); } // save default fields $defaultValues = array(); for ( $i = 0; $i < $_REQUEST['columncount']; $i++ ) if (isset($importColumns[$i]) && !empty($_REQUEST[$importColumns[$i]])) { $field = $importColumns[$i]; $fieldDef = $focus->getFieldDefinition($field); if(!empty($fieldDef['custom_type']) && $fieldDef['custom_type'] == 'teamset') { require_once('include/SugarFields/Fields/Teamset/SugarFieldTeamset.php'); $sugar_field = new SugarFieldTeamset('Teamset'); $teams = $sugar_field->getTeamsFromRequest($field); if(isset($_REQUEST['primary_team_name_collection'])) { $primary_index = $_REQUEST['primary_team_name_collection']; } //If primary_index was selected, ensure that the first Array entry is the primary team if(isset($primary_index)) { $count = 0; $new_teams = array(); foreach($teams as $id=>$name) { if($primary_index == $count++) { $new_teams[$id] = $name; unset($teams[$id]); break; } } foreach($teams as $id=>$name) { $new_teams[$id] = $name; } $teams = $new_teams; } //if $json = getJSONobj(); $defaultValues[$field] = $json->encode($teams); } else { $defaultValues[$field] = $_REQUEST[$importColumns[$i]]; } } $mapping_file->setDefaultValues($defaultValues); $result = $mapping_file->save( $current_user->id, $_REQUEST['save_map_as'], $_REQUEST['import_module'], $_REQUEST['source'], ( isset($_REQUEST['has_header']) && $_REQUEST['has_header'] == 'on'), $_REQUEST['custom_delimiter'], html_entity_decode($_REQUEST['custom_enclosure'],ENT_QUOTES) ); } $importFile->writeStatus(); } /** * If a bean save is not done for some reason, this method will undo any of the beans that were created * * @param array $ids ids of user_last_import records created */ protected function _undoCreatedBeans( array $ids ) { $focus = new UsersLastImport(); foreach ($ids as $id) $focus->undoById($id); } /** * clean id's when being imported * * @param string $string * @return string */ protected function _convertId( $string ) { return preg_replace_callback( '|[^A-Za-z0-9\-]|', create_function( // single quotes are essential here, // or alternative escape all $ as \$ '$matches', 'return ord($matches[0]);' ) , $string); } /** * Replaces PHP error handler in Step4 * * @param int $errno * @param string $errstr * @param string $errfile * @param string $errline */ public static function handleImportErrors( $errno, $errstr, $errfile, $errline ) { if ( !defined('E_DEPRECATED') ) define('E_DEPRECATED','8192'); if ( !defined('E_USER_DEPRECATED') ) define('E_USER_DEPRECATED','16384'); // check to see if current reporting level should be included based upon error_reporting() setting, if not // then just return if ( !(error_reporting() & $errno) ) return true; switch ($errno) { case E_USER_ERROR: echo "ERROR: [$errno] $errstr on line $errline in file $errfile
\n"; exit(1); break; case E_USER_WARNING: case E_WARNING: echo "WARNING: [$errno] $errstr on line $errline in file $errfile
\n"; break; case E_USER_NOTICE: case E_NOTICE: echo "NOTICE: [$errno] $errstr on line $errline in file $errfile
\n"; break; case E_STRICT: case E_DEPRECATED: case E_USER_DEPRECATED: // don't worry about these //echo "STRICT ERROR: [$errno] $errstr on line $errline in file $errfile
\n"; break; default: echo "Unknown error type: [$errno] $errstr on line $errline in file $errfile
\n"; break; } return true; } }