3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2019
35 * This class gets the name of the file to upload.
37 class CRM_Contact_Import_Form_MapField
extends CRM_Import_Form_MapField
{
39 use CRM_Contact_Import_MetadataTrait
;
42 * An array of all contact fields with
43 * formatted custom field names.
47 protected $_formattedFieldNames;
56 protected $_dedupeFields;
58 protected static $customFields;
61 * Attempt to match header labels with our mapper fields.
63 * FIXME: This is essentially the same function as parent::defaultFromHeader
65 * @param string $columnName name of column header
69 public function defaultFromColumnName($columnName) {
71 if (!preg_match('/^[a-z0-9 ]$/i', $columnName)) {
72 if ($columnKey = array_search($columnName, $this->getFieldTitles())) {
73 $this->_fieldUsed
[$columnKey] = TRUE;
78 foreach ($this->getHeaderPatterns() as $key => $re) {
79 // Skip empty key/patterns
80 if (!$key ||
!$re ||
strlen("$re") < 5) {
84 if (preg_match($re, $columnName)) {
85 $this->_fieldUsed
[$key] = TRUE;
93 * Set variables up before form is built.
95 public function preProcess() {
96 $dataSource = $this->get('dataSource');
97 $skipColumnHeader = $this->get('skipColumnHeader');
98 $this->_mapperFields
= $this->get('fields');
99 $this->_importTableName
= $this->get('importTableName');
100 $this->_onDuplicate
= $this->get('onDuplicate');
101 $highlightedFields = [];
102 $highlightedFields[] = 'email';
103 $highlightedFields[] = 'external_identifier';
104 //format custom field names, CRM-2676
105 switch ($this->get('contactType')) {
106 case CRM_Import_Parser
::CONTACT_INDIVIDUAL
:
107 $contactType = 'Individual';
108 $highlightedFields[] = 'first_name';
109 $highlightedFields[] = 'last_name';
112 case CRM_Import_Parser
::CONTACT_HOUSEHOLD
:
113 $contactType = 'Household';
114 $highlightedFields[] = 'household_name';
117 case CRM_Import_Parser
::CONTACT_ORGANIZATION
:
118 $contactType = 'Organization';
119 $highlightedFields[] = 'organization_name';
122 $this->_contactType
= $contactType;
123 if ($this->_onDuplicate
== CRM_Import_Parser
::DUPLICATE_SKIP
) {
124 unset($this->_mapperFields
['id']);
127 $highlightedFields[] = 'id';
130 if ($this->_onDuplicate
!= CRM_Import_Parser
::DUPLICATE_NOCHECK
) {
131 //Mark Dedupe Rule Fields as required, since it's used in matching contact
132 foreach (['Individual', 'Household', 'Organization'] as $cType) {
134 'contact_type' => $cType,
135 'used' => 'Unsupervised',
137 $this->_dedupeFields
[$cType] = CRM_Dedupe_BAO_Rule
::dedupeRuleFields($ruleParams);
140 //Modify mapper fields title if fields are present in dedupe rule
141 if (is_array($this->_dedupeFields
[$contactType])) {
142 foreach ($this->_dedupeFields
[$contactType] as $val) {
143 if ($valTitle = CRM_Utils_Array
::value($val, $this->_mapperFields
)) {
144 $this->_mapperFields
[$val] = $valTitle . ' (match to contact)';
149 // retrieve and highlight required custom fields
150 $formattedFieldNames = $this->formatCustomFieldName($this->_mapperFields
);
151 self
::$customFields = CRM_Core_BAO_CustomField
::getFields($this->_contactType
);
152 foreach (self
::$customFields as $key => $attr) {
153 if (!empty($attr['is_required'])) {
154 $highlightedFields[] = "custom_$key";
157 $this->assign('highlightedFields', $highlightedFields);
158 $this->_formattedFieldNames
[$contactType] = $this->_mapperFields
= array_merge($this->_mapperFields
, $formattedFieldNames);
161 //get original col headers from csv if present.
162 if ($dataSource == 'CRM_Import_DataSource_CSV' && $skipColumnHeader) {
163 $columnNames = $this->get('originalColHeader');
166 // get the field names from the temp. DB table
167 $dao = new CRM_Core_DAO();
168 $db = $dao->getDatabaseConnection();
170 $columnsQuery = "SHOW FIELDS FROM $this->_importTableName
171 WHERE Field NOT LIKE '\_%'";
172 $columnsResult = $db->query($columnsQuery);
173 while ($row = $columnsResult->fetchRow(DB_FETCHMODE_ASSOC
)) {
174 $columnNames[] = $row['Field'];
178 $showColNames = TRUE;
179 if ($dataSource === 'CRM_Import_DataSource_CSV' && !$skipColumnHeader) {
180 $showColNames = FALSE;
182 $this->assign('showColNames', $showColNames);
184 $this->_columnCount
= count($columnNames);
185 $this->_columnNames
= $columnNames;
186 $this->assign('columnNames', $columnNames);
187 //$this->_columnCount = $this->get( 'columnCount' );
188 $this->assign('columnCount', $this->_columnCount
);
189 $this->_dataValues
= $this->get('dataValues');
190 $this->assign('dataValues', $this->_dataValues
);
191 $this->assign('rowDisplayCount', 2);
195 * Build the form object.
197 * @throws \CiviCRM_API3_Exception
199 public function buildQuickForm() {
200 $savedMappingID = (int) $this->get('savedMapping');
201 //to save the current mappings
202 if (!$savedMappingID) {
203 $saveDetailsName = ts('Save this field mapping');
204 $this->applyFilter('saveMappingName', 'trim');
205 $this->add('text', 'saveMappingName', ts('Name'));
206 $this->add('text', 'saveMappingDesc', ts('Description'));
209 $savedMapping = $this->get('savedMapping');
211 list($mappingName) = CRM_Core_BAO_Mapping
::getMappingFields($savedMapping, TRUE);
213 //get loaded Mapping Fields
214 $mappingName = CRM_Utils_Array
::value(1, $mappingName);
216 $this->assign('loadedMapping', $savedMapping);
217 $this->set('loadedMapping', $savedMapping);
219 $params = ['id' => $savedMapping];
221 $mappingDetails = CRM_Core_BAO_Mapping
::retrieve($params, $temp);
223 $this->assign('savedName', $mappingDetails->name
);
225 $this->add('hidden', 'mappingId', $savedMapping);
227 $this->addElement('checkbox', 'updateMapping', ts('Update this field mapping'), NULL);
228 $saveDetailsName = ts('Save as a new field mapping');
229 $this->add('text', 'saveMappingName', ts('Name'));
230 $this->add('text', 'saveMappingDesc', ts('Description'));
233 $this->addElement('checkbox', 'saveMapping', $saveDetailsName, NULL, ['onclick' => "showSaveDetails(this)"]);
235 $this->addFormRule(['CRM_Contact_Import_Form_MapField', 'formRule']);
237 //-------- end of saved mapping stuff ---------
240 $mapperKeys = array_keys($this->_mapperFields
);
241 $hasColumnNames = !empty($this->_columnNames
);
242 $hasLocationTypes = $this->get('fieldTypes');
244 $this->_location_types
= ['Primary' => ts('Primary')] + CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
245 $defaultLocationType = CRM_Core_BAO_LocationType
::getDefault();
247 // Pass default location to js
248 if ($defaultLocationType) {
249 $this->assign('defaultLocationType', $defaultLocationType->id
);
250 $this->assign('defaultLocationTypeLabel', $this->_location_types
[$defaultLocationType->id
]);
253 /* Initialize all field usages to false */
254 foreach ($mapperKeys as $key) {
255 $this->_fieldUsed
[$key] = FALSE;
258 $sel1 = $this->_mapperFields
;
261 $phoneTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Phone', 'phone_type_id');
262 $imProviders = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id');
263 $websiteTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Website', 'website_type_id');
265 foreach ($this->_location_types
as $key => $value) {
266 $sel3['phone'][$key] = &$phoneTypes;
267 //build array for IM service provider type for contact
268 $sel3['im'][$key] = &$imProviders;
273 // store and cache all relationship types
274 $contactRelation = new CRM_Contact_DAO_RelationshipType();
275 $contactRelation->find();
276 while ($contactRelation->fetch()) {
277 $contactRelationCache[$contactRelation->id
] = [];
278 $contactRelationCache[$contactRelation->id
]['contact_type_a'] = $contactRelation->contact_type_a
;
279 $contactRelationCache[$contactRelation->id
]['contact_sub_type_a'] = $contactRelation->contact_sub_type_a
;
280 $contactRelationCache[$contactRelation->id
]['contact_type_b'] = $contactRelation->contact_type_b
;
281 $contactRelationCache[$contactRelation->id
]['contact_sub_type_b'] = $contactRelation->contact_sub_type_b
;
283 $highlightedFields = $highlightedRelFields = [];
285 $highlightedFields['email'] = 'All';
286 $highlightedFields['external_identifier'] = 'All';
287 $highlightedFields['first_name'] = 'Individual';
288 $highlightedFields['last_name'] = 'Individual';
289 $highlightedFields['household_name'] = 'Household';
290 $highlightedFields['organization_name'] = 'Organization';
292 foreach ($mapperKeys as $key) {
293 // check if there is a _a_b or _b_a in the key
294 if (strpos($key, '_a_b') ||
strpos($key, '_b_a')) {
295 list($id, $first, $second) = explode('_', $key);
298 $id = $first = $second = NULL;
300 if (($first === 'a' && $second === 'b') ||
($first === 'b' && $second === 'a')) {
301 $cType = $contactRelationCache[$id]["contact_type_{$second}"];
303 //CRM-5125 for contact subtype specific relationshiptypes
305 if (!empty($contactRelationCache[$id]["contact_sub_type_{$second}"])) {
306 $cSubType = $contactRelationCache[$id]["contact_sub_type_{$second}"];
313 $relatedFields = CRM_Contact_BAO_Contact
::importableFields($cType);
314 unset($relatedFields['']);
316 foreach ($relatedFields as $name => $field) {
317 $values[$name] = $field['title'];
318 if (isset($hasLocationTypes[$name])) {
319 $sel3[$key][$name] = $this->_location_types
;
321 elseif ($name === 'url') {
322 $sel3[$key][$name] = $websiteTypes;
329 //fix to append custom group name to field name, CRM-2676
330 if (empty($this->_formattedFieldNames
[$cType]) ||
$cType == $this->_contactType
) {
331 $this->_formattedFieldNames
[$cType] = $this->formatCustomFieldName($values);
334 $this->_formattedFieldNames
[$cType] = array_merge($values, $this->_formattedFieldNames
[$cType]);
336 //Modified the Relationship fields if the fields are
337 //present in dedupe rule
338 if ($this->_onDuplicate
!= CRM_Import_Parser
::DUPLICATE_NOCHECK
&& !empty($this->_dedupeFields
[$cType]) &&
339 is_array($this->_dedupeFields
[$cType])
341 static $cTypeArray = [];
342 if ($cType != $this->_contactType
&& !in_array($cType, $cTypeArray)) {
343 foreach ($this->_dedupeFields
[$cType] as $val) {
344 if ($valTitle = CRM_Utils_Array
::value($val, $this->_formattedFieldNames
[$cType])) {
345 $this->_formattedFieldNames
[$cType][$val] = $valTitle . ' (match to contact)';
348 $cTypeArray[] = $cType;
352 foreach ($highlightedFields as $k => $v) {
353 if ($v == $cType ||
$v === 'All') {
354 $highlightedRelFields[$key][] = $k;
357 $this->assign('highlightedRelFields', $highlightedRelFields);
358 $sel2[$key] = $this->_formattedFieldNames
[$cType];
360 if (!empty($cSubType)) {
361 //custom fields for sub type
362 $subTypeFields = CRM_Core_BAO_CustomField
::getFieldsForImport($cSubType);
364 if (!empty($subTypeFields)) {
366 foreach ($subTypeFields as $customSubTypeField => $details) {
367 $subType[$customSubTypeField] = $details['title'];
368 $sel2[$key] = array_merge($sel2[$key], $this->formatCustomFieldName($subType));
373 foreach ($this->_location_types
as $k => $value) {
374 $sel4[$key]['phone'][$k] = &$phoneTypes;
375 //build array of IM service provider for related contact
376 $sel4[$key]['im'][$k] = &$imProviders;
381 if (!empty($hasLocationTypes[$key])) {
382 $options = $this->_location_types
;
384 elseif ($key === 'url') {
385 $options = $websiteTypes;
387 $sel2[$key] = $options;
391 $js = "<script type='text/javascript'>\n";
392 $formName = 'document.forms.' . $this->_name
;
393 //used to warn for mismatch column count or mismatch mapping
394 CRM_Core_Session
::singleton()->setStatus(NULL);
395 $processor = new CRM_Import_ImportProcessor();
396 $processor->setMappingID($savedMappingID);
397 $processor->setFormName($formName);
398 $processor->setMetadata($this->getContactImportMetadata());
399 $processor->setContactTypeByConstant($this->get('contactType'));
400 $processor->setContactSubType($this->get('contactSubType'));
402 for ($i = 0; $i < $this->_columnCount
; $i++
) {
403 $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL);
405 if ($this->get('savedMapping')) {
406 list($defaults, $js) = $this->loadSavedMapping($processor, $mappingName, $i, $defaults, $js, $hasColumnNames);
409 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
410 if ($hasColumnNames) {
411 // do array search first to see if has mapped key
412 $columnKey = array_search($this->_columnNames
[$i], $this->getFieldTitles());
413 if (isset($this->_fieldUsed
[$columnKey])) {
414 $defaults["mapper[$i]"] = $columnKey;
415 $this->_fieldUsed
[$key] = TRUE;
418 // Infer the default from the column names if we have them
419 $defaults["mapper[$i]"] = [
420 $this->defaultFromColumnName($this->_columnNames
[$i]),
426 // Otherwise guess the default from the form of the data
427 $defaults["mapper[$i]"] = [
428 $this->defaultFromData($this->getDataPatterns(), $i),
429 // $defaultLocationType->id
434 $sel->setOptions([$sel1, $sel2, $sel3, $sel4]);
437 $js .= "</script>\n";
438 $this->assign('initHideBoxes', $js);
440 //set warning if mismatch in more than
441 if (isset($mappingName) &&
442 ($this->_columnCount
!= count($mappingName))
444 CRM_Core_Session
::singleton()->setStatus(ts('The data columns in this import file appear to be different from the saved mapping. Please verify that you have selected the correct saved mapping before continuing.'));
447 $this->setDefaults($defaults);
452 'name' => ts('Previous'),
456 'name' => ts('Continue'),
457 'spacing' => ' ',
462 'name' => ts('Cancel'),
468 * Global validation rules for the form.
470 * @param array $fields
471 * Posted values of the form.
474 * list of errors to be posted back to the form
476 public static function formRule($fields) {
478 if (!empty($fields['saveMapping'])) {
479 $nameField = CRM_Utils_Array
::value('saveMappingName', $fields);
480 if (empty($nameField)) {
481 $errors['saveMappingName'] = ts('Name is required to save Import Mapping');
484 $mappingTypeId = CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', 'Import Contact');
485 if (CRM_Core_BAO_Mapping
::checkMapping($nameField, $mappingTypeId)) {
486 $errors['saveMappingName'] = ts('Duplicate Import Mapping Name');
490 $template = CRM_Core_Smarty
::singleton();
491 if (!empty($fields['saveMapping'])) {
492 $template->assign('isCheked', TRUE);
495 if (!empty($errors)) {
497 $assignError = new CRM_Core_Page();
498 $assignError->assign('mappingDetailsError', $_flag);
507 * Process the mapped fields and map it into the uploaded file.
509 public function postProcess() {
510 $params = $this->controller
->exportValues('MapField');
512 //reload the mapfield if load mapping is pressed
513 if (!empty($params['savedMapping'])) {
514 $this->set('savedMapping', $params['savedMapping']);
515 $this->controller
->resetPage($this->_name
);
518 $mapperKeys = $this->controller
->exportValue($this->_name
, 'mapper');
520 $parser = $this->submit($params, $mapperKeys);
522 // add all the necessary variables to the form
527 * Format custom field name.
529 * Combine group and field name to avoid conflict.
531 * @param array $fields
535 public function formatCustomFieldName($fields) {
536 //CRM-2676, replacing the conflict for same custom field name from different custom group.
537 $fieldIds = $formattedFieldNames = [];
538 foreach ($fields as $key => $value) {
539 if ($customFieldId = CRM_Core_BAO_CustomField
::getKeyID($key)) {
540 $fieldIds[] = $customFieldId;
544 if (!empty($fieldIds) && is_array($fieldIds)) {
545 $groupTitles = CRM_Core_BAO_CustomGroup
::getGroupTitles($fieldIds);
547 if (!empty($groupTitles)) {
548 foreach ($groupTitles as $fId => $values) {
549 $key = "custom_{$fId}";
550 $groupTitle = $values['groupTitle'];
551 $formattedFieldNames[$key] = $fields[$key] . ' :: ' . $groupTitle;
556 return $formattedFieldNames;
560 * Main submit function.
562 * Extracted to add testing & start refactoring.
567 * @return \CRM_Contact_Import_Parser_Contact
568 * @throws \CiviCRM_API3_Exception
570 public function submit($params, $mapperKeys) {
571 $mapper = $mapperKeysMain = $locations = [];
572 $parserParameters = CRM_Contact_Import_Parser_Contact
::getParameterForParser($this->_columnCount
);
574 $phoneTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Phone', 'phone_type_id');
575 $imProviders = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id');
576 $websiteTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Website', 'website_type_id');
577 $locationTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
578 $locationTypes['Primary'] = ts('Primary');
580 for ($i = 0; $i < $this->_columnCount
; $i++
) {
582 $fldName = CRM_Utils_Array
::value(0, $mapperKeys[$i]);
583 $selOne = CRM_Utils_Array
::value(1, $mapperKeys[$i]);
584 $selTwo = CRM_Utils_Array
::value(2, $mapperKeys[$i]);
585 $selThree = CRM_Utils_Array
::value(3, $mapperKeys[$i]);
586 $mapper[$i] = $this->_mapperFields
[$mapperKeys[$i][0]];
587 $mapperKeysMain[$i] = $fldName;
589 //need to differentiate non location elements.
590 if ($selOne && (is_numeric($selOne) ||
$selOne === 'Primary')) {
591 if ($fldName === 'url') {
592 $parserParameters['mapperWebsiteType'][$i] = $websiteTypes[$selOne];
595 $locations[$i] = $locationTypes[$selOne];
596 $parserParameters['mapperLocType'][$i] = $selOne;
597 if ($selTwo && is_numeric($selTwo)) {
598 if ($fldName === 'phone') {
599 $parserParameters['mapperPhoneType'][$i] = $phoneTypes[$selTwo];
601 elseif ($fldName === 'im') {
602 $parserParameters['mapperImProvider'][$i] = $imProviders[$selTwo];
608 //relationship contact mapper info.
609 list($id, $first, $second) = CRM_Utils_System
::explode('_', $fldName, 3);
610 if (($first === 'a' && $second === 'b') ||
611 ($first === 'b' && $second === 'a')
613 $parserParameters['mapperRelated'][$i] = $this->_mapperFields
[$fldName];
615 if ($selOne === 'url') {
616 $parserParameters['relatedContactWebsiteType'][$i] = $websiteTypes[$selTwo];
619 $parserParameters['relatedContactLocType'][$i] = CRM_Utils_Array
::value($selTwo, $locationTypes);
621 if ($selOne === 'phone') {
622 $parserParameters['relatedContactPhoneType'][$i] = $phoneTypes[$selThree];
624 elseif ($selOne === 'im') {
625 $parserParameters['relatedContactImProvider'][$i] = $imProviders[$selThree];
630 //get the related contact type.
631 $relationType = new CRM_Contact_DAO_RelationshipType();
632 $relationType->id
= $id;
633 $relationType->find(TRUE);
634 $parserParameters['relatedContactType'][$i] = $relationType->{"contact_type_$second"};
635 $parserParameters['relatedContactDetails'][$i] = $this->_formattedFieldNames
[$parserParameters['relatedContactType'][$i]][$selOne];
640 $this->set('columnNames', $this->_columnNames
);
641 $this->set('websites', $parserParameters['mapperWebsiteType']);
642 $this->set('locations', $locations);
643 $this->set('phones', $parserParameters['mapperPhoneType']);
644 $this->set('ims', $parserParameters['mapperImProvider']);
645 $this->set('related', $parserParameters['mapperRelated']);
646 $this->set('relatedContactType', $parserParameters['relatedContactType']);
647 $this->set('relatedContactDetails', $parserParameters['relatedContactDetails']);
648 $this->set('relatedContactLocType', $parserParameters['relatedContactLocType']);
649 $this->set('relatedContactPhoneType', $parserParameters['relatedContactPhoneType']);
650 $this->set('relatedContactImProvider', $parserParameters['relatedContactImProvider']);
651 $this->set('relatedContactWebsiteType', $parserParameters['relatedContactWebsiteType']);
652 $this->set('mapper', $mapper);
654 // store mapping Id to display it in the preview page
655 $this->set('loadMappingId', CRM_Utils_Array
::value('mappingId', $params));
657 //Updating Mapping Records
658 if (!empty($params['updateMapping'])) {
660 $mappingFields = new CRM_Core_DAO_MappingField();
661 $mappingFields->mapping_id
= $params['mappingId'];
662 $mappingFields->find();
664 $mappingFieldsId = [];
665 while ($mappingFields->fetch()) {
666 if ($mappingFields->id
) {
667 $mappingFieldsId[$mappingFields->column_number
] = $mappingFields->id
;
671 for ($i = 0; $i < $this->_columnCount
; $i++
) {
672 $updateMappingFields = new CRM_Core_DAO_MappingField();
673 $updateMappingFields->id
= CRM_Utils_Array
::value($i, $mappingFieldsId);
674 $updateMappingFields->mapping_id
= $params['mappingId'];
675 $updateMappingFields->column_number
= $i;
677 $mapperKeyParts = explode('_', $mapperKeys[$i][0], 3);
678 $id = isset($mapperKeyParts[0]) ?
$mapperKeyParts[0] : NULL;
679 $first = isset($mapperKeyParts[1]) ?
$mapperKeyParts[1] : NULL;
680 $second = isset($mapperKeyParts[2]) ?
$mapperKeyParts[2] : NULL;
681 if (($first == 'a' && $second == 'b') ||
($first == 'b' && $second == 'a')) {
682 $updateMappingFields->relationship_type_id
= $id;
683 $updateMappingFields->relationship_direction
= "{$first}_{$second}";
684 $updateMappingFields->name
= ucwords(str_replace("_", " ", $mapperKeys[$i][1]));
685 // get phoneType id and provider id separately
686 // before updating mappingFields of phone and IM for related contact, CRM-3140
687 if (CRM_Utils_Array
::value('1', $mapperKeys[$i]) == 'url') {
688 $updateMappingFields->website_type_id
= isset($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
691 if (CRM_Utils_Array
::value('1', $mapperKeys[$i]) == 'phone') {
692 $updateMappingFields->phone_type_id
= isset($mapperKeys[$i][3]) ?
$mapperKeys[$i][3] : NULL;
694 elseif (CRM_Utils_Array
::value('1', $mapperKeys[$i]) == 'im') {
695 $updateMappingFields->im_provider_id
= isset($mapperKeys[$i][3]) ?
$mapperKeys[$i][3] : NULL;
697 $updateMappingFields->location_type_id
= isset($mapperKeys[$i][2]) && is_numeric($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
701 $updateMappingFields->name
= $mapper[$i];
702 $updateMappingFields->relationship_type_id
= 'NULL';
703 $updateMappingFields->relationship_type_direction
= 'NULL';
704 // to store phoneType id and provider id separately
705 // before updating mappingFields for phone and IM, CRM-3140
706 if (CRM_Utils_Array
::value('0', $mapperKeys[$i]) == 'url') {
707 $updateMappingFields->website_type_id
= isset($mapperKeys[$i][1]) ?
$mapperKeys[$i][1] : NULL;
710 if (CRM_Utils_Array
::value('0', $mapperKeys[$i]) == 'phone') {
711 $updateMappingFields->phone_type_id
= isset($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
713 elseif (CRM_Utils_Array
::value('0', $mapperKeys[$i]) == 'im') {
714 $updateMappingFields->im_provider_id
= isset($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
716 $locationTypeID = $parserParameters['mapperLocType'][$i];
717 // location_type_id is NULL for non-location fields, and for Primary location.
718 $updateMappingFields->location_type_id
= is_numeric($locationTypeID) ?
$locationTypeID : 'null';
721 $updateMappingFields->save();
725 //Saving Mapping Details and Records
726 if (!empty($params['saveMapping'])) {
728 'name' => $params['saveMappingName'],
729 'description' => $params['saveMappingDesc'],
730 'mapping_type_id' => 'Import Contact',
733 $saveMapping = civicrm_api3('Mapping', 'create', $mappingParams);
735 $contactType = $this->get('contactType');
736 switch ($contactType) {
737 case CRM_Import_Parser
::CONTACT_INDIVIDUAL
:
738 $cType = 'Individual';
741 case CRM_Import_Parser
::CONTACT_HOUSEHOLD
:
742 $cType = 'Household';
745 case CRM_Import_Parser
::CONTACT_ORGANIZATION
:
746 $cType = 'Organization';
750 for ($i = 0; $i < $this->_columnCount
; $i++
) {
751 $mappingID = $this->saveMappingField($mapperKeys, $saveMapping, $cType, $i, $mapper, $parserParameters);
753 $this->set('savedMapping', $mappingID);
756 $parser = new CRM_Contact_Import_Parser_Contact($mapperKeysMain, $parserParameters['mapperLocType'], $parserParameters['mapperPhoneType'],
757 $parserParameters['mapperImProvider'], $parserParameters['mapperRelated'], $parserParameters['relatedContactType'],
758 $parserParameters['relatedContactDetails'], $parserParameters['relatedContactLocType'],
759 $parserParameters['relatedContactPhoneType'], $parserParameters['relatedContactImProvider'],
760 $parserParameters['mapperWebsiteType'], $parserParameters['relatedContactWebsiteType']
763 $primaryKeyName = $this->get('primaryKeyName');
764 $statusFieldName = $this->get('statusFieldName');
765 $parser->run($this->_importTableName
,
767 CRM_Import_Parser
::MODE_PREVIEW
,
768 $this->get('contactType'),
773 CRM_Contact_Import_Parser
::DEFAULT_TIMEOUT
,
774 $this->get('contactSubType'),
782 * @param array $saveMapping
783 * @param string $cType
785 * @param array $mapper
786 * @param array $parserParameters
790 protected function saveMappingField($mapperKeys, array $saveMapping, string $cType, int $i, array $mapper, array $parserParameters): int {
791 $saveMappingFields = new CRM_Core_DAO_MappingField();
792 $saveMappingFields->mapping_id
= $saveMapping['id'];
793 $saveMappingFields->contact_type
= $cType;
794 $saveMappingFields->column_number
= $i;
796 $mapperKeyParts = explode('_', $mapperKeys[$i][0], 3);
797 $id = isset($mapperKeyParts[0]) ?
$mapperKeyParts[0] : NULL;
798 $first = isset($mapperKeyParts[1]) ?
$mapperKeyParts[1] : NULL;
799 $second = isset($mapperKeyParts[2]) ?
$mapperKeyParts[2] : NULL;
800 if (($first == 'a' && $second == 'b') ||
($first == 'b' && $second == 'a')) {
801 $saveMappingFields->name
= ucwords(str_replace("_", " ", $mapperKeys[$i][1]));
802 $saveMappingFields->relationship_type_id
= $id;
803 $saveMappingFields->relationship_direction
= "{$first}_{$second}";
804 // to get phoneType id and provider id separately
805 // before saving mappingFields of phone and IM for related contact, CRM-3140
806 if (CRM_Utils_Array
::value('1', $mapperKeys[$i]) == 'url') {
807 $saveMappingFields->website_type_id
= isset($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
810 if (CRM_Utils_Array
::value('1', $mapperKeys[$i]) == 'phone') {
811 $saveMappingFields->phone_type_id
= isset($mapperKeys[$i][3]) ?
$mapperKeys[$i][3] : NULL;
813 elseif (CRM_Utils_Array
::value('1', $mapperKeys[$i]) == 'im') {
814 $saveMappingFields->im_provider_id
= isset($mapperKeys[$i][3]) ?
$mapperKeys[$i][3] : NULL;
816 $saveMappingFields->location_type_id
= (isset($mapperKeys[$i][2]) && $mapperKeys[$i][2] !== 'Primary') ?
$mapperKeys[$i][2] : NULL;
820 $saveMappingFields->name
= $mapper[$i];
821 $locationTypeID = $parserParameters['mapperLocType'][$i];
822 // to get phoneType id and provider id separately
823 // before saving mappingFields of phone and IM, CRM-3140
824 if (CRM_Utils_Array
::value('0', $mapperKeys[$i]) == 'url') {
825 $saveMappingFields->website_type_id
= isset($mapperKeys[$i][1]) ?
$mapperKeys[$i][1] : NULL;
828 if (CRM_Utils_Array
::value('0', $mapperKeys[$i]) == 'phone') {
829 $saveMappingFields->phone_type_id
= isset($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
831 elseif (CRM_Utils_Array
::value('0', $mapperKeys[$i]) == 'im') {
832 $saveMappingFields->im_provider_id
= isset($mapperKeys[$i][2]) ?
$mapperKeys[$i][2] : NULL;
834 $saveMappingFields->location_type_id
= is_numeric($locationTypeID) ?
$locationTypeID : NULL;
836 $saveMappingFields->relationship_type_id
= NULL;
838 $saveMappingFields->save();
839 return $saveMappingFields->mapping_id
;
843 * @param \CRM_Import_ImportProcessor $processor
844 * @param $mappingName
846 * @param array $defaults
848 * @param bool $hasColumnNames
851 * @throws \CiviCRM_API3_Exception
853 public function loadSavedMapping($processor, $mappingName, $i, $defaults, $js, $hasColumnNames) {
854 $formName = $processor->getFormName();
855 if (isset($mappingName[$i])) {
856 if ($mappingName[$i] != ts('- do not import -')) {
857 $defaults["mapper[$i]"] = $processor->getSavedQuickformDefaultsForColumn($i);
858 $js .= $processor->getQuickFormJSForField($i);
861 $defaults["mapper[$i]"] = [];
862 for ($k = 1; $k < 4; $k++
) {
863 $js .= "{$formName}['mapper[$i][$k]'].style.display = 'none';\n";
868 // this load section to help mapping if we ran out of saved columns when doing Load Mapping
869 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
871 if ($hasColumnNames) {
872 $defaults["mapper[$i]"] = [$this->defaultFromColumnName($this->_columnNames
[$i])];
875 $defaults["mapper[$i]"] = [$this->defaultFromData($this->getDataPatterns(), $i)];
878 return [$defaults, $js];