/** * @see SugarView::display() */ public function display() { global $mod_strings, $app_strings, $current_user; global $sugar_config; $this->ss->assign("MODULE_TITLE", $this->getModuleTitle(false)); $this->ss->assign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline', 'align="absmiddle" alt="' . $app_strings['LNK_DELETE'] . '" border="0"')); $this->ss->assign("PUBLISH_INLINE_PNG", SugarThemeRegistry::current()->getImage('publish_inline', 'align="absmiddle" alt="' . $mod_strings['LBL_PUBLISH'] . '" border="0"')); $this->ss->assign("UNPUBLISH_INLINE_PNG", SugarThemeRegistry::current()->getImage('unpublish_inline', 'align="absmiddle" alt="' . $mod_strings['LBL_UNPUBLISH'] . '" border="0"')); $this->ss->assign("IMPORT_MODULE", $_REQUEST['import_module']); $this->ss->assign("JAVASCRIPT", $this->_getJS()); $this->ss->assign("CURRENT_STEP", $this->currentStep); //BEGIN DRAG DROP WIDGET $idc = new ImportDuplicateCheck($this->bean); $dupe_indexes = $idc->getDuplicateCheckIndexes(); $dupe_disabled = array(); foreach ($dupe_indexes as $dk => $dv) { $dupe_disabled[] = array("dupeVal" => $dk, "label" => $dv); } //set dragdrop value $this->ss->assign('enabled_dupes', json_encode(array())); $this->ss->assign('disabled_dupes', json_encode($dupe_disabled)); //END DRAG DROP WIDGET $this->ss->assign("RECORDTHRESHOLD", $sugar_config['import_max_records_per_file']); $content = $this->ss->fetch('modules/Import/tpls/extdupcheck.tpl'); $this->ss->assign("CONTENT", $content); $this->ss->display('modules/Import/tpls/wizardWrapper.tpl'); }
/** * Returns JS used in this view */ private function _getJS() { global $mod_strings, $sugar_config; $has_header = $_REQUEST['has_header'] == 'on' ? TRUE : FALSE; $uploadFileName = "upload://" . basename($_REQUEST['tmp_file']); $splitter = new ImportFileSplitter($uploadFileName, $sugar_config['import_max_records_per_file']); $splitter->splitSourceFile($_REQUEST['custom_delimiter'], html_entity_decode($_REQUEST['custom_enclosure'], ENT_QUOTES), $has_header); $count = $splitter->getFileCount() - 1; $recCount = $splitter->getRecordCount(); //BEGIN DRAG DROP WIDGET $idc = new ImportDuplicateCheck($this->bean); $dupe_indexes = $idc->getDuplicateCheckIndexes(); //grab all the import enabled fields and the field map $field_map = $this->getImportMap(); $import_fields = $idc->getDuplicateCheckIndexedFiles(); //check for saved entries from mapping $dupe_disabled = array(); $dupe_enabled = array(); $mapped_fields = array('full_name'); //grab the list of user mapped fields foreach ($_REQUEST as $req_k => $req_v) { if (strpos($req_k, 'olnum') > 0) { if (empty($req_v) || $req_v != '-1') { $mapped_fields[] = $req_v; } } } foreach ($import_fields as $ik => $iv) { //grab the field value from the key $ik_field = explode('::', $ik); //field is not a custom field and was not included in the key, or was not in mapped fields, so skip if (strpos($ik_field[0], 'ustomfield::') > 0 || (empty($ik_field[1]) || !in_array($ik_field[1], $mapped_fields))) { //skip indexed fields that are not defined in user mapping or continue; } if (isset($field_map['dupe_' . $ik])) { //index is defined in mapping, so set this index as enabled if not already defined $dupe_enabled[] = array("dupeVal" => $ik, "label" => $iv); } else { //index is not defined in mapping, so display as disabled if not already defined $dupe_disabled[] = array("dupeVal" => $ik, "label" => $iv); } } $enabled_dupes = json_encode($dupe_enabled); $disabled_dupes = json_encode($dupe_disabled); $stepTitle4 = $mod_strings['LBL_IMPORT_RECORDS']; $dateTimeFormat = $GLOBALS['timedate']->get_cal_date_time_format(); $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : ''; $lblUsed = str_replace(":", "", $mod_strings['LBL_INDEX_USED']); $lblNotUsed = str_replace(":", "", $mod_strings['LBL_INDEX_NOT_USED']); return <<<EOJAVASCRIPT /** * Singleton to handle processing the import */ ProcessImport = new function() { /* * number of file to process processed */ this.fileCount = 0; /* * total files to processs */ this.fileTotal = {$count}; /* * total records to process */ this.recordCount = {$recCount}; /* * maximum number of records per file */ this.recordThreshold = {$sugar_config['import_max_records_per_file']}; /* * submits the form */ this.submit = function() { document.getElementById("importstepdup").tmp_file.value = document.getElementById("importstepdup").tmp_file_base.value + '-' + this.fileCount; YAHOO.util.Connect.setForm(document.getElementById("importstepdup")); YAHOO.util.Connect.asyncRequest('POST', 'index.php', { success: function(o) { if (o.responseText.replace(/^\\s+|\\s+\$/g, '') != '') { this.failure(o); } else { var locationStr = "index.php?module=Import" + "&action=Last" + "¤t_step=" + document.getElementById("importstepdup").current_step.value + "&type={$type}" + "&import_module={$_REQUEST['import_module']}" + "&has_header=" + document.getElementById("importstepdup").has_header.value ; if ( ProcessImport.fileCount >= ProcessImport.fileTotal ) { \tYAHOO.SUGAR.MessageBox.updateProgress(1,'{$mod_strings['LBL_IMPORT_COMPLETED']}'); \tSUGAR.util.hrefURL(locationStr); } else { document.getElementById("importstepdup").save_map_as.value = ''; ProcessImport.fileCount++; ProcessImport.submit(); } } }, failure: function(o) { \tYAHOO.SUGAR.MessageBox.minWidth = 500; \tYAHOO.SUGAR.MessageBox.show({ \ttype: "alert", \ttitle: '{$mod_strings['LBL_IMPORT_ERROR']}', \tmsg: o.responseText, fn: function() { window.location.reload(true); } }); } } ); var move = 0; if ( this.fileTotal > 0 ) { move = this.fileCount/this.fileTotal; } YAHOO.SUGAR.MessageBox.updateProgress( move, "{$mod_strings['LBL_IMPORT_RECORDS']} " + ((this.fileCount * this.recordThreshold) + 1) + " {$mod_strings['LBL_IMPORT_RECORDS_TO']} " + Math.min(((this.fileCount+1) * this.recordThreshold),this.recordCount) + " {$mod_strings['LBL_IMPORT_RECORDS_OF']} " + this.recordCount ); } /* * begins the form submission process */ this.begin = function() { datestarted = '{$mod_strings['LBL_IMPORT_STARTED']} ' + YAHOO.util.Date.format('{$dateTimeFormat}'); YAHOO.SUGAR.MessageBox.show({ title: '{$stepTitle4}', msg: datestarted, width: 500, type: "progress", closable:false, animEl: 'importnow' }); SUGAR.saveConfigureDupes(); this.submit(); } } //begin dragdrop code \tvar enabled_dupes = {$enabled_dupes}; \tvar disabled_dupes = {$disabled_dupes}; \tvar lblEnabled = '{$lblUsed}'; \tvar lblDisabled = '{$lblNotUsed}'; \tSUGAR.enabledDupesTable = new YAHOO.SUGAR.DragDropTable( \t\t"enabled_div", \t\t[{key:"label", label: lblEnabled, width: 225, sortable: false}, \t\t {key:"module", label: lblEnabled, hidden:true}], \t\tnew YAHOO.util.LocalDataSource(enabled_dupes, { \t\t\tresponseSchema: { \t\t\t resultsList : "dupeVal", \t\t\t fields : [{key : "dupeVal"}, {key : "label"}] \t\t\t} \t\t}), \t\t{ \t\t\theight: "300px", \t\t\tgroup: ["enabled_div", "disabled_div"] \t\t} \t); \tSUGAR.disabledDupesTable = new YAHOO.SUGAR.DragDropTable( \t\t"disabled_div", \t\t[{key:"label", label: lblDisabled, width: 225, sortable: false}, \t\t {key:"module", label: lblDisabled, hidden:true}], \t\tnew YAHOO.util.LocalDataSource(disabled_dupes, { \t\t\tresponseSchema: { \t\t\t resultsList : "dupeVal", \t\t\t fields : [{key : "dupeVal"}, {key : "label"}] \t\t\t} \t\t}), \t\t{ \t\t\theight: "300px", \t\t \tgroup: ["enabled_div", "disabled_div"] \t\t } \t); \tSUGAR.enabledDupesTable.disableEmptyRows = true; SUGAR.disabledDupesTable.disableEmptyRows = true; SUGAR.enabledDupesTable.addRow({module: "", label: ""}); SUGAR.disabledDupesTable.addRow({module: "", label: ""}); \tSUGAR.enabledDupesTable.render(); \tSUGAR.disabledDupesTable.render(); \tSUGAR.saveConfigureDupes = function() \t{ \t\tvar enabledTable = SUGAR.enabledDupesTable; \t\tvar dupeVal = []; \t\tfor(var i=0; i < enabledTable.getRecordSet().getLength(); i++){ \t\t\tvar data = enabledTable.getRecord(i).getData(); \t\t\tif (data.dupeVal && data.dupeVal != '') \t\t\t dupeVal[i] = data.dupeVal; \t\t} \t\t YAHOO.util.Dom.get('enabled_dupes').value = YAHOO.lang.JSON.stringify(dupeVal); var disabledTable = SUGAR.disabledDupesTable; \t\tvar dupeVal = []; \t\tfor(var i=0; i < disabledTable.getRecordSet().getLength(); i++){ \t\t\tvar data = disabledTable.getRecord(i).getData(); \t\t\tif (data.dupeVal && data.dupeVal != '') \t\t\t dupeVal[i] = data.dupeVal; \t\t} \t\t\tYAHOO.util.Dom.get('disabled_dupes').value = YAHOO.lang.JSON.stringify(dupeVal); \t} document.getElementById('goback').onclick = function(){ document.getElementById('importstepdup').action.value = 'step3'; document.getElementById('importstepdup').to_pdf.value = '0'; var success = function(data) { \t\t\tvar response = YAHOO.lang.JSON.parse(data.responseText); \t\t\timportWizardDialogDiv = document.getElementById('importWizardDialogDiv'); \t\t\timportWizardDialogTitle = document.getElementById('importWizardDialogTitle'); \t\t\tsubmitDiv = document.getElementById('submitDiv'); \t\t\timportWizardDialogDiv.innerHTML = response['html']; \t\t\timportWizardDialogTitle.innerHTML = response['title']; \t\t\tSUGAR.util.evalScript(response['html']); \t\t\tsubmitDiv.innerHTML = response['submitContent']; \t\t\teval(response['script']); \t\t} var formObject = document.getElementById('importstepdup'); \t\tYAHOO.util.Connect.setForm(formObject); \t\tvar cObj = YAHOO.util.Connect.asyncRequest('POST', "index.php", {success: success, failure: success}); } document.getElementById('importnow').onclick = function(){ SUGAR.saveConfigureDupes(); var form = document.getElementById('importstepdup'); // Move on to next step document.getElementById('importstepdup').action.value = 'Step4'; ProcessImport.begin(); } enableQS(false); EOJAVASCRIPT; }
protected function importRow($row) { global $sugar_config, $mod_strings, $current_user; $focus = clone $this->bean; $focus->unPopulateDefaultValues(); $focus->save_from_post = false; $focus->team_id = null; $this->ifs->createdBeans = array(); $this->importSource->resetRowErrorCounter(); $do_save = true; for ($fieldNum = 0; $fieldNum < $_REQUEST['columncount']; $fieldNum++) { // loop if this column isn't set if (!isset($this->importColumns[$fieldNum])) { continue; } // get this field's properties $field = $this->importColumns[$fieldNum]; $fieldDef = $focus->getFieldDefinition($field); $fieldTranslated = translate(isset($fieldDef['vname']) ? $fieldDef['vname'] : $fieldDef['name'], $focus->module_dir) . " (" . $fieldDef['name'] . ")"; $defaultRowValue = ''; // Bug 37241 - Don't re-import over a field we already set during the importing of another field if (!empty($focus->{$field})) { continue; } // translate strings global $locale; if (empty($locale)) { $locale = new Localization(); } if (isset($row[$fieldNum])) { $rowValue = $locale->translateCharset(strip_tags(trim($row[$fieldNum])), $this->importSource->importlocale_charset, $sugar_config['default_charset']); } else { if (isset($this->sugarToExternalSourceFieldMap[$field]) && isset($row[$this->sugarToExternalSourceFieldMap[$field]])) { $rowValue = $locale->translateCharset(strip_tags(trim($row[$this->sugarToExternalSourceFieldMap[$field]])), $this->importSource->importlocale_charset, $sugar_config['default_charset']); } else { $rowValue = ''; } } // If there is an default value then use it instead if (!empty($_REQUEST[$field])) { $defaultRowValue = $this->populateDefaultMapValue($field, $_REQUEST[$field], $fieldDef); if (empty($rowValue)) { $rowValue = $defaultRowValue; //reset the default value to empty $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') { $this->importSource->writeError($mod_strings['LBL_REQUIRED_VALUE'], $fieldTranslated, 'NULL'); $do_save = false; } // Handle the special case "Sync to Outlook" if ($focus->object_name == "Contact" && $field == 'sync_contact') { /** * Bug #41194 : if true used as value of sync_contact - add curent user to list to sync */ if (true == $rowValue || 'true' == strtolower($rowValue)) { $focus->sync_contact = $focus->id; } elseif (false == $rowValue || 'false' == strtolower($rowValue)) { $focus->sync_contact = ''; } else { $bad_names = array(); $returnValue = $this->ifs->synctooutlook($rowValue, $fieldDef, $bad_names); // try the default value on fail if (!$returnValue && !empty($defaultRowValue)) { $returnValue = $this->ifs->synctooutlook($defaultRowValue, $fieldDef, $bad_names); } if (!$returnValue) { $this->importSource->writeError($mod_strings['LBL_ERROR_SYNC_USERS'], $fieldTranslated, $bad_names); $do_save = 0; } else { $focus->sync_contact = $returnValue; } } } // Handle email field, if it's a semi-colon separated export if ($field == 'email_addresses_non_primary' && !empty($rowValue)) { if (strpos($rowValue, ';') !== false) { $rowValue = explode(';', $rowValue); } else { $rowValue = array($rowValue); } } // Handle email1 and email2 fields ( these don't have the type of email ) if ($field == 'email1' || $field == 'email2') { $returnValue = $this->ifs->email($rowValue, $fieldDef, $focus); // try the default value on fail if (!$returnValue && !empty($defaultRowValue)) { $returnValue = $this->ifs->email($defaultRowValue, $fieldDef); } if ($returnValue === FALSE) { $do_save = 0; $this->importSource->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)) { $this->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)) { // If it's an array of non-primary e-mails, check each mail if ($field == "email_addresses_non_primary" && is_array($rowValue)) { foreach ($rowValue as $tempRow) { $tempRow = $this->sanitizeFieldValueByType($tempRow, $fieldDef, $defaultRowValue, $focus, $fieldTranslated); if ($tempRow === FALSE) { $rowValue = false; $do_save = false; break; } } } else { $rowValue = $this->sanitizeFieldValueByType($rowValue, $fieldDef, $defaultRowValue, $focus, $fieldTranslated); } if ($rowValue === false) { /* BUG 51213 - jeff @ neposystems.com */ $do_save = false; continue; } } // if the parent type is in singular form, get the real module name for parent_type if (isset($fieldDef['type']) && $fieldDef['type'] == 'parent_type') { $rowValue = get_module_from_singular($rowValue); } $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 = $this->ifs->parent($focus->parent_name, $focus->field_defs['parent_name'], $focus, empty($_REQUEST['parent_name'])); if (!$returnValue && !empty($_REQUEST['parent_name'])) { $returnValue = $this->ifs->parent($_REQUEST['parent_name'], $focus->field_defs['parent_name'], $focus); } } // check to see that the indexes being entered are unique. if (isset($_REQUEST['enabled_dupes']) && $_REQUEST['enabled_dupes'] != "") { $toDecode = html_entity_decode($_REQUEST['enabled_dupes'], ENT_QUOTES); $enabled_dupes = json_decode($toDecode); $idc = new ImportDuplicateCheck($focus); if ($idc->isADuplicateRecord($enabled_dupes)) { $this->importSource->markRowAsDuplicate($idc->_dupedFields); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } } else { if (!empty($_REQUEST['enabled_dup_fields'])) { $toDecode = html_entity_decode($_REQUEST['enabled_dup_fields'], ENT_QUOTES); $enabled_dup_fields = json_decode($toDecode); $idc = new ImportDuplicateCheck($focus); if ($idc->isADuplicateRecordByFields($enabled_dup_fields)) { $this->importSource->markRowAsDuplicate($idc->_dupedFields); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } } } // 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 && $this->isUpdateOnly == false) { $this->removeDeletedBean($focus); $focus->new_with_id = true; } else { if (!$this->isUpdateOnly) { $this->importSource->writeError($mod_strings['LBL_ID_EXISTS_ALREADY'], 'ID', $focus->id); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } $clonedBean = $this->cloneExistingBean($focus); if ($clonedBean === FALSE) { $this->importSource->writeError($mod_strings['LBL_RECORD_CANNOT_BE_UPDATED'], 'ID', $focus->id); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } else { $focus = $clonedBean; $newRecord = FALSE; } } } else { $focus->new_with_id = true; } } if ($do_save) { $this->saveImportBean($focus, $newRecord); // Update the created/updated counter $this->importSource->markRowAsImported($newRecord); } else { $this->_undoCreatedBeans($this->ifs->createdBeans); } unset($defaultRowValue); }
/** * @see SugarView::display() */ public function display() { global $mod_strings, $app_strings, $current_user, $sugar_config, $app_list_strings, $locale; $this->ss->assign("IMPORT_MODULE", $_REQUEST['import_module']); $has_header = isset($_REQUEST['has_header']) ? 1 : 0; $sugar_config['import_max_records_per_file'] = empty($sugar_config['import_max_records_per_file']) ? 1000 : $sugar_config['import_max_records_per_file']; // Clear out this user's last import $seedUsersLastImport = new UsersLastImport(); $seedUsersLastImport->mark_deleted_by_user_id($current_user->id); ImportCacheFiles::clearCacheFiles(); // attempt to lookup a preexisting field map // use the custom one if specfied to do so in step 1 $field_map = array(); $default_values = array(); $ignored_fields = array(); if (!empty($_REQUEST['source_id'])) { $mapping_file = new ImportMap(); $mapping_file->retrieve($_REQUEST['source_id'], false); $_REQUEST['source'] = $mapping_file->source; $has_header = $mapping_file->has_header; if (isset($mapping_file->delimiter)) { $_REQUEST['custom_delimiter'] = $mapping_file->delimiter; } if (isset($mapping_file->enclosure)) { $_REQUEST['custom_enclosure'] = htmlentities($mapping_file->enclosure); } $field_map = $mapping_file->getMapping(); $default_values = $mapping_file->getDefaultValues(); $this->ss->assign("MAPNAME", $mapping_file->name); $this->ss->assign("CHECKMAP", 'checked="checked" value="on"'); } else { // Try to see if we have a custom mapping we can use // based upon the where the records are coming from // and what module we are importing into $classname = 'ImportMap' . ucfirst($_REQUEST['source']); if (file_exists("modules/Import/{$classname}.php")) { require_once "modules/Import/{$classname}.php"; } elseif (file_exists("custom/modules/Import/{$classname}.php")) { require_once "custom/modules/Import/{$classname}.php"; } else { require_once "custom/modules/Import/ImportMapOther.php"; $classname = 'ImportMapOther'; $_REQUEST['source'] = 'other'; } if (class_exists($classname)) { $mapping_file = new $classname(); if (isset($mapping_file->delimiter)) { $_REQUEST['custom_delimiter'] = $mapping_file->delimiter; } if (isset($mapping_file->enclosure)) { $_REQUEST['custom_enclosure'] = htmlentities($mapping_file->enclosure); } $ignored_fields = $mapping_file->getIgnoredFields($_REQUEST['import_module']); $field_map = $mapping_file->getMapping($_REQUEST['import_module']); } } $this->ss->assign("CUSTOM_DELIMITER", !empty($_REQUEST['custom_delimiter']) ? $_REQUEST['custom_delimiter'] : ","); $this->ss->assign("CUSTOM_ENCLOSURE", !empty($_REQUEST['custom_enclosure']) ? $_REQUEST['custom_enclosure'] : ""); // handle uploaded file $uploadFile = new UploadFile('userfile'); if (isset($_FILES['userfile']) && $uploadFile->confirm_upload()) { $uploadFile->final_move('IMPORT_' . $this->bean->object_name . '_' . $current_user->id); $uploadFileName = $uploadFile->get_upload_path('IMPORT_' . $this->bean->object_name . '_' . $current_user->id); } else { $this->_showImportError($mod_strings['LBL_IMPORT_MODULE_ERROR_NO_UPLOAD'], $_REQUEST['import_module'], 'Step2'); return; } // split file into parts $splitter = new ImportFileSplitter($uploadFileName, $sugar_config['import_max_records_per_file']); $splitter->splitSourceFile($_REQUEST['custom_delimiter'], html_entity_decode($_REQUEST['custom_enclosure'], ENT_QUOTES), $has_header); // Now parse the file and look for errors $importFile = new ImportFile($uploadFileName, $_REQUEST['custom_delimiter'], html_entity_decode($_REQUEST['custom_enclosure'], ENT_QUOTES)); if (!$importFile->fileExists()) { $this->_showImportError($mod_strings['LBL_CANNOT_OPEN'], $_REQUEST['import_module'], 'Step2'); return; } // retrieve first 3 rows $rows = array(); $system_charset = $locale->default_export_charset; $user_charset = $locale->getExportCharset(); $other_charsets = 'UTF-8, UTF-7, ASCII, CP1252, EUC-JP, SJIS, eucJP-win, SJIS-win, JIS, ISO-2022-JP'; $detectable_charsets = "UTF-8, {$user_charset}, {$system_charset}, {$other_charsets}"; // Bug 26824 - mb_detect_encoding() thinks CP1252 is IS0-8859-1, so use that instead in the encoding list passed to the function $detectable_charsets = str_replace('CP1252', 'ISO-8859-1', $detectable_charsets); $charset_for_import = $user_charset; //We will set the default import charset option by user's preference. $able_to_detect = function_exists('mb_detect_encoding'); for ($i = 0; $i < 3; $i++) { $rows[$i] = $importFile->getNextRow(); if (!empty($rows[$i]) && $able_to_detect) { foreach ($rows[$i] as &$temp_value) { $current_charset = mb_detect_encoding($temp_value, $detectable_charsets); if (!empty($current_charset) && $current_charset != "UTF-8") { $temp_value = $locale->translateCharset($temp_value, $current_charset); // we will use utf-8 for displaying the data on the page. $charset_for_import = $current_charset; //set the default import charset option according to the current_charset. //If it is not utf-8, tt may be overwritten by the later one. So the uploaded file should not contain two types of charset($user_charset, $system_charset), and I think this situation will not occur. } } } } $ret_field_count = $importFile->getFieldCount(); // Bug 14689 - Parse the first data row to make sure it has non-empty data in it $isempty = true; if ($rows[(int) $has_header] != false) { foreach ($rows[(int) $has_header] as $value) { if (strlen(trim($value)) > 0) { $isempty = false; break; } } } if ($isempty || $rows[(int) $has_header] == false) { $this->_showImportError($mod_strings['LBL_NO_LINES'], $_REQUEST['import_module'], 'Step2'); return; } // save first row to send to step 4 $this->ss->assign("FIRSTROW", base64_encode(serialize($rows[0]))); // Now build template $this->ss->assign("TMP_FILE", $uploadFileName); $this->ss->assign("FILECOUNT", $splitter->getFileCount()); $this->ss->assign("RECORDCOUNT", $splitter->getRecordCount()); $this->ss->assign("RECORDTHRESHOLD", $sugar_config['import_max_records_per_file']); $this->ss->assign("SOURCE", $_REQUEST['source']); $this->ss->assign("TYPE", $_REQUEST['type']); $this->ss->assign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('basic_search', 'align="absmiddle" alt="' . $app_strings['LNK_DELETE'] . '" border="0"')); $this->ss->assign("PUBLISH_INLINE_PNG", SugarThemeRegistry::current()->getImage('advanced_search', 'align="absmiddle" alt="' . $mod_strings['LBL_PUBLISH'] . '" border="0"')); $this->ss->assign("MODULE_TITLE", $this->getModuleTitle()); $this->ss->assign("STEP4_TITLE", strip_tags(str_replace("\n", "", getClassicModuleTitle($mod_strings['LBL_MODULE_NAME'], array($mod_strings['LBL_MODULE_NAME'], $mod_strings['LBL_STEP_4_TITLE']), false)))); $this->ss->assign("HEADER", $app_strings['LBL_IMPORT'] . " " . $mod_strings['LBL_MODULE_NAME']); // we export it as email_address, but import as email1 $field_map['email_address'] = 'email1'; // build each row; row count is determined by the the number of fields in the import file $columns = array(); $mappedFields = array(); for ($field_count = 0; $field_count < $ret_field_count; $field_count++) { // See if we have any field map matches $defaultValue = ""; // Bug 31260 - If the data rows have more columns than the header row, then just add a new header column if (!isset($rows[0][$field_count])) { $rows[0][$field_count] = ''; } // See if we can match the import row to a field in the list of fields to import $firstrow_name = trim(str_replace(":", "", $rows[0][$field_count])); if ($has_header && isset($field_map[$firstrow_name])) { $defaultValue = $field_map[$firstrow_name]; } elseif (isset($field_map[$field_count])) { $defaultValue = $field_map[$field_count]; } elseif (empty($_REQUEST['source_id'])) { $defaultValue = trim($rows[0][$field_count]); } // build string of options $fields = $this->bean->get_importable_fields(); $options = array(); $defaultField = ''; foreach ($fields as $fieldname => $properties) { // get field name if (!empty($properties['vname'])) { $displayname = str_replace(":", "", translate($properties['vname'], $this->bean->module_dir)); } else { $displayname = str_replace(":", "", translate($properties['name'], $this->bean->module_dir)); } // see if this is required $req_mark = ""; $req_class = ""; if (array_key_exists($fieldname, $this->bean->get_import_required_fields())) { $req_mark = ' ' . $app_strings['LBL_REQUIRED_SYMBOL']; $req_class = ' class="required" '; } // see if we have a match $selected = ''; if (!empty($defaultValue) && !in_array($fieldname, $mappedFields) && !in_array($fieldname, $ignored_fields)) { if (strtolower($fieldname) == strtolower($defaultValue) || strtolower($fieldname) == str_replace(" ", "_", strtolower($defaultValue)) || strtolower($displayname) == strtolower($defaultValue) || strtolower($displayname) == str_replace(" ", "_", strtolower($defaultValue))) { $selected = ' selected="selected" '; $defaultField = $fieldname; $mappedFields[] = $fieldname; } } // get field type information $fieldtype = ''; if (isset($properties['type']) && isset($mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])])) { $fieldtype = ' [' . $mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])] . '] '; } if (isset($properties['comment'])) { $fieldtype .= ' - ' . $properties['comment']; } $options[$displayname . $fieldname] = '<option value="' . $fieldname . '" title="' . $displayname . htmlentities($fieldtype) . '"' . $selected . $req_class . '>' . $displayname . $req_mark . '</option>\\n'; } // get default field value $defaultFieldHTML = ''; if (!empty($defaultField)) { $defaultFieldHTML = getControl($_REQUEST['import_module'], $defaultField, $fields[$defaultField], isset($default_values[$defaultField]) ? $default_values[$defaultField] : ''); } if (isset($default_values[$defaultField])) { unset($default_values[$defaultField]); } // Bug 27046 - Sort the column name picker alphabetically ksort($options); $columns[] = array('field_choices' => implode('', $options), 'default_field' => $defaultFieldHTML, 'cell1' => str_replace(""", '', htmlspecialchars($rows[0][$field_count])), 'cell2' => str_replace(""", '', htmlspecialchars($rows[1][$field_count])), 'cell3' => str_replace(""", '', htmlspecialchars($rows[2][$field_count])), 'show_remove' => false); } // add in extra defaulted fields if they are in the mapping record if (count($default_values) > 0) { foreach ($default_values as $field_name => $default_value) { // build string of options $fields = $this->bean->get_importable_fields(); $options = array(); $defaultField = ''; foreach ($fields as $fieldname => $properties) { // get field name if (!empty($properties['vname'])) { $displayname = str_replace(":", "", translate($properties['vname'], $this->bean->module_dir)); } else { $displayname = str_replace(":", "", translate($properties['name'], $this->bean->module_dir)); } // see if this is required $req_mark = ""; $req_class = ""; if (array_key_exists($fieldname, $this->bean->get_import_required_fields())) { $req_mark = ' ' . $app_strings['LBL_REQUIRED_SYMBOL']; $req_class = ' class="required" '; } // see if we have a match $selected = ''; if (strtolower($fieldname) == strtolower($field_name) && !in_array($fieldname, $mappedFields) && !in_array($fieldname, $ignored_fields)) { $selected = ' selected="selected" '; $defaultField = $fieldname; $mappedFields[] = $fieldname; } // get field type information $fieldtype = ''; if (isset($properties['type']) && isset($mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])])) { $fieldtype = ' [' . $mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])] . '] '; } if (isset($properties['comment'])) { $fieldtype .= ' - ' . $properties['comment']; } $options[$displayname . $fieldname] = '<option value="' . $fieldname . '" title="' . $displayname . $fieldtype . '"' . $selected . $req_class . '>' . $displayname . $req_mark . '</option>\\n'; } // get default field value $defaultFieldHTML = ''; if (!empty($defaultField)) { $defaultFieldHTML = getControl($_REQUEST['import_module'], $defaultField, $fields[$defaultField], $default_value); } // Bug 27046 - Sort the column name picker alphabetically ksort($options); $columns[] = array('field_choices' => implode('', $options), 'default_field' => $defaultFieldHTML, 'show_remove' => true); $ret_field_count++; } } $this->ss->assign("COLUMNCOUNT", $ret_field_count); $this->ss->assign("rows", $columns); // get list of valid date/time formats $timeFormat = $current_user->getUserDateTimePreferences(); $timeOptions = get_select_options_with_id($sugar_config['time_formats'], $timeFormat['time']); $dateOptions = get_select_options_with_id($sugar_config['date_formats'], $timeFormat['date']); $this->ss->assign('TIMEOPTIONS', $timeOptions); $this->ss->assign('DATEOPTIONS', $dateOptions); $this->ss->assign('datetimeformat', $GLOBALS['timedate']->get_cal_date_time_format()); // get list of valid timezones $userTZ = $current_user->getPreference('timezone'); if (empty($userTZ)) { $userTZ = TimeDate::userTimezone(); } $this->ss->assign('TIMEZONE_CURRENT', $userTZ); $this->ss->assign('TIMEZONEOPTIONS', TimeDate::getTimezoneList()); // get currency preference require_once 'modules/Currencies/ListCurrency.php'; $currency = new ListCurrency(); $cur_id = $locale->getPrecedentPreference('currency', $current_user); if ($cur_id) { $selectCurrency = $currency->getSelectOptions($cur_id); $this->ss->assign("CURRENCY", $selectCurrency); } else { $selectCurrency = $currency->getSelectOptions(); $this->ss->assign("CURRENCY", $selectCurrency); } $currenciesVars = ""; $i = 0; foreach ($locale->currencies as $id => $arrVal) { $currenciesVars .= "currencies[{$i}] = '{$arrVal['symbol']}';\n"; $i++; } $currencySymbolsJs = <<<eoq var currencies = new Object; {$currenciesVars} function setSymbolValue(id) { document.getElementById('symbol').value = currencies[id]; } eoq; $this->ss->assign('currencySymbolJs', $currencySymbolsJs); // fill significant digits dropdown $significantDigits = $locale->getPrecedentPreference('default_currency_significant_digits', $current_user); $sigDigits = ''; for ($i = 0; $i <= 6; $i++) { if ($significantDigits == $i) { $sigDigits .= '<option value="' . $i . '" selected="true">' . $i . '</option>'; } else { $sigDigits .= '<option value="' . $i . '">' . $i . '</option>'; } } $this->ss->assign('sigDigits', $sigDigits); $num_grp_sep = $current_user->getPreference('num_grp_sep'); $dec_sep = $current_user->getPreference('dec_sep'); $this->ss->assign("NUM_GRP_SEP", empty($num_grp_sep) ? $sugar_config['default_number_grouping_seperator'] : $num_grp_sep); $this->ss->assign("DEC_SEP", empty($dec_sep) ? $sugar_config['default_decimal_seperator'] : $dec_sep); $this->ss->assign('getNumberJs', $locale->getNumberJs()); // Name display format $this->ss->assign('default_locale_name_format', $locale->getLocaleFormatMacro($current_user)); $this->ss->assign('getNameJs', $locale->getNameJs()); // Charset $charsetOptions = get_select_options_with_id($locale->getCharsetSelect(), $charset_for_import); //wdong, bug 25927, here we should use the charset testing results from above. $this->ss->assign('CHARSETOPTIONS', $charsetOptions); // handle building index selector global $dictionary, $current_language; require_once "include/templates/TemplateGroupChooser.php"; $chooser_array = array(); $chooser_array[0] = array(); $idc = new ImportDuplicateCheck($this->bean); $chooser_array[1] = $idc->getDuplicateCheckIndexes(); $chooser = new TemplateGroupChooser(); $chooser->args['id'] = 'selected_indices'; $chooser->args['values_array'] = $chooser_array; $chooser->args['left_name'] = 'choose_index'; $chooser->args['right_name'] = 'ignore_index'; $chooser->args['left_label'] = $mod_strings['LBL_INDEX_USED']; $chooser->args['right_label'] = $mod_strings['LBL_INDEX_NOT_USED']; $this->ss->assign("TAB_CHOOSER", $chooser->display()); // show notes if ($this->bean instanceof Person) { $module_key = "LBL_CONTACTS_NOTE_"; } elseif ($this->bean instanceof Company) { $module_key = "LBL_ACCOUNTS_NOTE_"; } else { $module_key = "LBL_" . strtoupper($_REQUEST['import_module']) . "_NOTE_"; } $notetext = ''; for ($i = 1; isset($mod_strings[$module_key . $i]); $i++) { $notetext .= '<li>' . $mod_strings[$module_key . $i] . '</li>'; } $this->ss->assign("NOTETEXT", $notetext); $this->ss->assign("HAS_HEADER", $has_header ? 'on' : 'off'); // get list of required fields $required = array(); foreach (array_keys($this->bean->get_import_required_fields()) as $name) { $properties = $this->bean->getFieldDefinition($name); if (!empty($properties['vname'])) { $required[$name] = str_replace(":", "", translate($properties['vname'], $this->bean->module_dir)); } else { $required[$name] = str_replace(":", "", translate($properties['name'], $this->bean->module_dir)); } } // include anything needed for quicksearch to work require_once "include/TemplateHandler/TemplateHandler.php"; $quicksearch_js = TemplateHandler::createQuickSearchCode($fields, $fields, 'importstep3'); $this->ss->assign("JAVASCRIPT", $quicksearch_js . "\n" . $this->_getJS($required)); $this->ss->assign('required_fields', implode(', ', $required)); $this->ss->display('modules/Import/tpls/step3.tpl'); }
/** * @see SugarView::display() */ public function display() { global $sugar_config; // Increase the max_execution_time since this step can take awhile ini_set("max_execution_time", max($sugar_config['import_max_execution_time'], 3600)); // stop the tracker TrackerManager::getInstance()->pause(); // use our own error handler set_error_handler('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(); // Let's try and load the import bean $focus = loadImportBean($_REQUEST['import_module']); if (!$focus) { trigger_error($mod_strings['LBL_ERROR_IMPORTS_NOT_SET_UP'], E_USER_ERROR); } // setup the importable fields array. $importable_fields = $focus->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 = $focus->getFieldDefinitions(); unset($focus); while ($row = $importFile->getNextRow()) { $focus = loadImportBean($_REQUEST['import_module']); $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); // 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 \n 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: if (method_exists('ImportFieldSanitize', $fieldDef['type'])) { $fieldtype = $fieldDef['type']; $returnValue = $ifs->{$fieldtype}($rowValue, $fieldDef); // try the default value on fail if (!$returnValue && !empty($defaultRowValue)) { $returnValue = $ifs->{$fieldtype}($defaultRowValue, $fieldDef); } if (!$returnValue) { $do_save = 0; $importFile->writeError($mod_strings['LBL_ERROR_INVALID_' . strtoupper($fieldDef['type'])], $fieldTranslated, $rowValue); } 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 = loadImportBean($_REQUEST['import_module']); $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; } 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) && $focus->is_admin && !is_admin($current_user) && is_admin_for_module($current_user, '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); } } // 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(); }
public function testCompareOnlySelectedIndexesFromDupeCheck() { //create a bean, values, populate and save $focus = loadBean('Contacts'); $focus->first_name = 'first ' . date("YmdHis"); $focus->last_name = 'last ' . date("YmdHis"); $focus->assigned_user_id = '1'; $focus->save(); //create the importDuplicateCheck object and get the list of duplicateCheckIndexes $idc = new ImportDuplicateCheck($focus); //we are going to test agains the first name, last name, full name, and assigned to indexes //to prove that only selected indexes are being used. //lets do a straight dupe check with the same bean on first name, should return true $this->assertTrue($idc->isADuplicateRecord(array('idx_cont_last_first::first_name')), 'simulated check against first name index (idx_cont_last_first::first_name) failed (returned false instead of true).'); //now lets test on full name index should also return true $this->assertTrue($idc->isADuplicateRecord(array('full_name::full_name')), 'first simulated check against full name index (full_name::full_name) failed (returned false instead of true). This check means BOTH first AND last name must match.'); //now lets remove the first name and redo the check, should return false $focus->first_name = ''; $idc = new ImportDuplicateCheck($focus); $this->assertFalse($idc->isADuplicateRecord(array('idx_cont_last_first::first_name')), 'simulated check against first name index (idx_cont_last_first::first_name) failed (returned true instead of false). This is wrong because we removed the first name so there should be no match.'); //lets retest on full name index should return false now as first AND last do not match the original $this->assertFalse($idc->isADuplicateRecord(array('full_name::full_name')), 'second simulated check against full name index (full_name::full_name) failed (returned true instead of false). This check means BOTH first AND last name must match and is wrong because we removed the first name so there should be no match.'); //now lets rename the contact and test on assigned user, should return true $focus->first_name = 'first ' . date("YmdHis"); $focus->last_name = 'last ' . date("YmdHis"); $idc = new ImportDuplicateCheck($focus); $this->assertTrue($idc->isADuplicateRecord(array('idx_del_id_user::assigned_user_id')), 'simulated check against assigned user index (idx_del_id_user::assigned_user_id) failed (returned false instead of true). This is wrong because we have not changed this field and it should remain a duplicate'); //we're done, lets delete the focus bean now $focus->mark_deleted($focus->id); }
protected function importRow($row) { global $sugar_config, $mod_strings, $current_user; $focus = BeanFactory::getBean($this->bean->module_dir); $focus->unPopulateDefaultValues(); $focus->save_from_post = false; $focus->team_id = null; $this->ifs->createdBeans = array(); $this->importSource->resetRowErrorCounter(); $do_save = true; // set the currency for the row, if it has a currency_id in the row if ($this->currencyFieldPosition !== false && !empty($row[$this->currencyFieldPosition])) { $currency_id = $row[$this->currencyFieldPosition]; if (!isset($this->cachedCurrencySymbols[$currency_id])) { /** @var Currency $currency */ $currency = BeanFactory::getBean('Currencies', $currency_id); $this->cachedCurrencySymbols[$currency_id] = $currency->symbol; unset($currency); } $this->ifs->currency_symbol = $this->cachedCurrencySymbols[$currency_id]; $this->ifs->currency_id = $currency_id; } // Collect email addresses, and add them before save $emailAddresses = array('non-primary' => array()); $fields_order = $this->getImportColumnsOrder($focus->getFieldDefinitions()); foreach ($fields_order as $fieldNum) { // loop if this column isn't set if (!isset($this->importColumns[$fieldNum])) { continue; } // get this field's properties $field = $this->importColumns[$fieldNum]; $fieldDef = $focus->getFieldDefinition($field); $fieldTranslated = translate(isset($fieldDef['vname']) ? $fieldDef['vname'] : $fieldDef['name'], $focus->module_dir) . " (" . $fieldDef['name'] . ")"; $defaultRowValue = ''; // Bug 37241 - Don't re-import over a field we already set during the importing of another field if (!empty($focus->{$field})) { continue; } // translate strings global $locale; if (empty($locale)) { $locale = Localization::getObject(); } if (isset($row[$fieldNum])) { $rowValue = strip_tags(trim($row[$fieldNum])); } else { if (isset($this->sugarToExternalSourceFieldMap[$field]) && isset($row[$this->sugarToExternalSourceFieldMap[$field]])) { $rowValue = strip_tags(trim($row[$this->sugarToExternalSourceFieldMap[$field]])); } else { $rowValue = ''; } } // If there is an default value then use it instead if (!empty($_REQUEST[$field])) { $defaultRowValue = $this->populateDefaultMapValue($field, $_REQUEST[$field], $fieldDef); if (!empty($fieldDef['custom_type']) && $fieldDef['custom_type'] == 'teamset' && empty($rowValue)) { require_once 'include/SugarFields/Fields/Teamset/SugarFieldTeamset.php'; $sugar_field = new SugarFieldTeamset('Teamset'); $rowValue = implode(', ', $sugar_field->getTeamsFromRequest($field)); } if (empty($rowValue)) { $rowValue = $defaultRowValue; //reset the default value to empty $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') { $this->importSource->writeError($mod_strings['LBL_REQUIRED_VALUE'], $fieldTranslated, 'NULL'); $do_save = false; } // Handle the special case 'Sync to Mail Client' if ($focus->object_name == "Contact" && $field == 'sync_contact') { /** * Bug #41194 : if true used as value of sync_contact - add curent user to list to sync */ if (true == $rowValue || 'true' == strtolower($rowValue)) { $focus->sync_contact = $focus->id; } elseif (false == $rowValue || 'false' == strtolower($rowValue)) { $focus->sync_contact = ''; } else { $bad_names = array(); $returnValue = $this->ifs->synctooutlook($rowValue, $fieldDef, $bad_names); // try the default value on fail if (!$returnValue && !empty($defaultRowValue)) { $returnValue = $this->ifs->synctooutlook($defaultRowValue, $fieldDef, $bad_names); } if (!$returnValue) { $this->importSource->writeError($mod_strings['LBL_ERROR_SYNC_USERS'], $fieldTranslated, $bad_names); $do_save = 0; } else { $focus->sync_contact = $returnValue; } } } // Handle email1 and email2 fields ( these don't have the type of email ) if ($field == 'email1' || $field == 'email2') { $returnValue = $this->ifs->email($rowValue, $fieldDef, $focus); // try the default value on fail if (!$returnValue && !empty($defaultRowValue)) { $returnValue = $this->ifs->email($defaultRowValue, $fieldDef); } if ($returnValue === FALSE) { $do_save = 0; $this->importSource->writeError($mod_strings['LBL_ERROR_INVALID_EMAIL'], $fieldTranslated, $rowValue); } else { $rowValue = $returnValue; $address = array('email_address' => $rowValue, 'primary_address' => $field == 'email1', 'invalid_email' => false, 'opt_out' => false); // 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)) { $address = array_merge($address, $emailrow); } if ($field === 'email1') { //flip the array so we can use it to get the key # $flippedVals = array_flip($this->importColumns); //if the opt out column is set, then attempt to retrieve the values if (isset($flippedVals['email_opt_out'])) { //if the string for this value has a length, then use it. if (isset($row[$flippedVals['email_opt_out']]) && strlen($row[$flippedVals['email_opt_out']]) > 0) { $address['opt_out'] = $row[$flippedVals['email_opt_out']]; } } //if the invalid email column is set, then attempt to retrieve the values if (isset($flippedVals['invalid_email'])) { //if the string for this value has a length, then use it. if (isset($row[$flippedVals['invalid_email']]) && strlen($row[$flippedVals['invalid_email']]) > 0) { $address['invalid_email'] = $row[$flippedVals['invalid_email']]; } } $emailAddresses['primary'] = $address; } else { $emailAddresses['non-primary'][] = $address; } } } if ($field == 'email_addresses_non_primary') { $nonPrimaryAddresses = $this->handleNonPrimaryEmails($rowValue, $defaultRowValue, $fieldTranslated); $emailAddresses['non-primary'] = array_merge($emailAddresses['non-primary'], $nonPrimaryAddresses); } // Handle splitting Full Name into First and Last Name parts if ($field == 'full_name' && !empty($rowValue)) { $this->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)) { //Start $rowValue = $this->sanitizeFieldValueByType($rowValue, $fieldDef, $defaultRowValue, $focus, $fieldTranslated); if ($rowValue === FALSE) { /* BUG 51213 - jeff @ neposystems.com */ $do_save = false; continue; } } // if the parent type is in singular form, get the real module name for parent_type if (isset($fieldDef['type']) && $fieldDef['type'] == 'parent_type') { $rowValue = get_module_from_singular($rowValue); } $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 = $this->ifs->parent($focus->parent_name, $focus->field_defs['parent_name'], $focus, empty($_REQUEST['parent_name'])); if (!$returnValue && !empty($_REQUEST['parent_name'])) { $returnValue = $this->ifs->parent($_REQUEST['parent_name'], $focus->field_defs['parent_name'], $focus); } } // check to see that the indexes being entered are unique. if (isset($_REQUEST['enabled_dupes']) && $_REQUEST['enabled_dupes'] != "") { $toDecode = html_entity_decode($_REQUEST['enabled_dupes'], ENT_QUOTES); $enabled_dupes = json_decode($toDecode); $idc = new ImportDuplicateCheck($focus); if ($idc->isADuplicateRecord($enabled_dupes)) { $this->importSource->markRowAsDuplicate($idc->_dupedFields); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } } else { if (!empty($_REQUEST['enabled_dup_fields'])) { $toDecode = html_entity_decode($_REQUEST['enabled_dup_fields'], ENT_QUOTES); $enabled_dup_fields = json_decode($toDecode); $idc = new ImportDuplicateCheck($focus); if ($idc->isADuplicateRecordByFields($enabled_dup_fields)) { $this->importSource->markRowAsDuplicate($idc->_dupedFields); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } } } // 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 && $this->isUpdateOnly == false) { $this->removeDeletedBean($focus); $focus->new_with_id = true; } else { if (!$this->isUpdateOnly) { $this->importSource->writeError($mod_strings['LBL_ID_EXISTS_ALREADY'], 'ID', $focus->id); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } $clonedBean = $this->cloneExistingBean($focus); if ($clonedBean === FALSE) { $this->importSource->writeError($mod_strings['LBL_RECORD_CANNOT_BE_UPDATED'], 'ID', $focus->id); $this->_undoCreatedBeans($this->ifs->createdBeans); return; } else { $focus = $clonedBean; $newRecord = FALSE; } } } else { $focus->new_with_id = true; } } try { // Update e-mails here, because we're calling retrieve, and it overwrites the emailAddress object if ($focus->hasEmails()) { $this->handleEmailUpdate($focus, $emailAddresses); } } catch (Exception $e) { $this->importSource->writeError($e->getMessage(), $fieldTranslated, $focus->id); $do_save = false; } if ($do_save) { $this->saveImportBean($focus, $newRecord); // Update the created/updated counter $this->importSource->markRowAsImported($newRecord); } else { $this->_undoCreatedBeans($this->ifs->createdBeans); } unset($defaultRowValue); }
public function testIsADuplicateRecordEmailNotFound() { $email = date("YmdHis") . '@badfoobar.com'; $focus = loadBean('Contacts'); $focus->email1 = $email; $idc = new ImportDuplicateCheck($focus); $this->assertFalse($idc->isADuplicateRecord(array('special_idx_email1'))); }
/** * @group 51264 */ public function testIsADuplicateRecord() { $contact = new Contact(); $contact->email1 = $this->contact->email1; $idc = new ImportDuplicateCheck($contact); $result = $idc->isADuplicateRecord(array('special_idx_email1::email1')); $this->assertTrue($result); }