(NFC) (dev/core#878) Simplify copyright header (templates/*)
[civicrm-core.git] / CRM / Contact / Import / Form / MapField.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
f299f7db 6 | Copyright CiviCRM LLC (c) 2004-2020 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
ca5cec67 31 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
32 */
33
34/**
f12c6f7d 35 * This class gets the name of the file to upload.
6a488035 36 */
b26295b8 37class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {
6a488035 38
a2ca56ec 39 use CRM_Contact_Import_MetadataTrait;
6a488035
TO
40
41 /**
100fef9d 42 * An array of all contact fields with
6a488035
TO
43 * formatted custom field names.
44 *
45 * @var array
6a488035 46 */
d4c8a770 47 protected $_formattedFieldNames;
6a488035
TO
48
49 /**
fe482240 50 * On duplicate.
6a488035
TO
51 *
52 * @var int
53 */
54 public $_onDuplicate;
55
56 protected $_dedupeFields;
57
817cf27c 58 protected static $customFields;
59
6a488035 60 /**
fe482240 61 * Attempt to match header labels with our mapper fields.
2b4bc760 62 *
b26295b8 63 * FIXME: This is essentially the same function as parent::defaultFromHeader
6a488035 64 *
2b4bc760 65 * @param string $columnName name of column header
6a488035
TO
66 *
67 * @return string
6a488035 68 */
0c7dc463 69 public function defaultFromColumnName($columnName) {
6a488035
TO
70
71 if (!preg_match('/^[a-z0-9 ]$/i', $columnName)) {
e119ba7d 72 if ($columnKey = array_search($columnName, $this->getFieldTitles())) {
6a488035
TO
73 $this->_fieldUsed[$columnKey] = TRUE;
74 return $columnKey;
75 }
76 }
77
0c7dc463 78 foreach ($this->getHeaderPatterns() as $key => $re) {
6a488035
TO
79 // Skip empty key/patterns
80 if (!$key || !$re || strlen("$re") < 5) {
81 continue;
82 }
83
84 if (preg_match($re, $columnName)) {
85 $this->_fieldUsed[$key] = TRUE;
86 return $key;
87 }
88 }
89 return '';
90 }
91
6a488035 92 /**
fe482240 93 * Set variables up before form is built.
6a488035
TO
94 */
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');
c16da28a 101 $highlightedFields = [];
6a488035
TO
102 $highlightedFields[] = 'email';
103 $highlightedFields[] = 'external_identifier';
104 //format custom field names, CRM-2676
105 switch ($this->get('contactType')) {
a05662ef 106 case CRM_Import_Parser::CONTACT_INDIVIDUAL:
353ffa53 107 $contactType = 'Individual';
6a488035
TO
108 $highlightedFields[] = 'first_name';
109 $highlightedFields[] = 'last_name';
110 break;
111
a05662ef 112 case CRM_Import_Parser::CONTACT_HOUSEHOLD:
6a488035
TO
113 $contactType = 'Household';
114 $highlightedFields[] = 'household_name';
115 break;
116
a05662ef 117 case CRM_Import_Parser::CONTACT_ORGANIZATION:
6a488035
TO
118 $contactType = 'Organization';
119 $highlightedFields[] = 'organization_name';
120 break;
121 }
122 $this->_contactType = $contactType;
a05662ef 123 if ($this->_onDuplicate == CRM_Import_Parser::DUPLICATE_SKIP) {
6a488035
TO
124 unset($this->_mapperFields['id']);
125 }
126 else {
127 $highlightedFields[] = 'id';
128 }
129
a05662ef 130 if ($this->_onDuplicate != CRM_Import_Parser::DUPLICATE_NOCHECK) {
6a488035 131 //Mark Dedupe Rule Fields as required, since it's used in matching contact
c16da28a 132 foreach (['Individual', 'Household', 'Organization'] as $cType) {
133 $ruleParams = [
6a488035 134 'contact_type' => $cType,
353ffa53 135 'used' => 'Unsupervised',
c16da28a 136 ];
6a488035
TO
137 $this->_dedupeFields[$cType] = CRM_Dedupe_BAO_Rule::dedupeRuleFields($ruleParams);
138 }
139
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)';
145 }
146 }
147 }
148 }
7b00a95d 149 // retrieve and highlight required custom fields
817cf27c 150 $formattedFieldNames = $this->formatCustomFieldName($this->_mapperFields);
151 self::$customFields = CRM_Core_BAO_CustomField::getFields($this->_contactType);
22e263ad 152 foreach (self::$customFields as $key => $attr) {
817cf27c 153 if (!empty($attr['is_required'])) {
154 $highlightedFields[] = "custom_$key";
155 }
156 }
6a488035 157 $this->assign('highlightedFields', $highlightedFields);
817cf27c 158 $this->_formattedFieldNames[$contactType] = $this->_mapperFields = array_merge($this->_mapperFields, $formattedFieldNames);
6a488035 159
c16da28a 160 $columnNames = [];
6a488035
TO
161 //get original col headers from csv if present.
162 if ($dataSource == 'CRM_Import_DataSource_CSV' && $skipColumnHeader) {
163 $columnNames = $this->get('originalColHeader');
164 }
165 else {
166 // get the field names from the temp. DB table
167 $dao = new CRM_Core_DAO();
168 $db = $dao->getDatabaseConnection();
169
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'];
175 }
176 }
177
178 $showColNames = TRUE;
4009859d 179 if ($dataSource === 'CRM_Import_DataSource_CSV' && !$skipColumnHeader) {
6a488035
TO
180 $showColNames = FALSE;
181 }
182 $this->assign('showColNames', $showColNames);
183
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);
192 }
193
194 /**
fe482240 195 * Build the form object.
a2ca56ec 196 *
197 * @throws \CiviCRM_API3_Exception
6a488035
TO
198 */
199 public function buildQuickForm() {
a2ca56ec 200 $savedMappingID = (int) $this->get('savedMapping');
27a00f6b 201 $this->buildSavedMappingFields($savedMappingID);
6a488035 202
c16da28a 203 $this->addFormRule(['CRM_Contact_Import_Form_MapField', 'formRule']);
6a488035
TO
204
205 //-------- end of saved mapping stuff ---------
206
c16da28a 207 $defaults = [];
353ffa53
TO
208 $mapperKeys = array_keys($this->_mapperFields);
209 $hasColumnNames = !empty($this->_columnNames);
6a488035
TO
210 $hasLocationTypes = $this->get('fieldTypes');
211
c16da28a 212 $this->_location_types = ['Primary' => ts('Primary')] + CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
6a488035
TO
213 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
214
31b8ac82 215 // Pass default location to js
6a488035 216 if ($defaultLocationType) {
31b8ac82
CW
217 $this->assign('defaultLocationType', $defaultLocationType->id);
218 $this->assign('defaultLocationTypeLabel', $this->_location_types[$defaultLocationType->id]);
6a488035
TO
219 }
220
221 /* Initialize all field usages to false */
6a488035
TO
222 foreach ($mapperKeys as $key) {
223 $this->_fieldUsed[$key] = FALSE;
224 }
225
226 $sel1 = $this->_mapperFields;
227 $sel2[''] = NULL;
228
353ffa53
TO
229 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
230 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
cbf48754 231 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
6a488035
TO
232
233 foreach ($this->_location_types as $key => $value) {
234 $sel3['phone'][$key] = &$phoneTypes;
235 //build array for IM service provider type for contact
236 $sel3['im'][$key] = &$imProviders;
237 }
238
239 $sel4 = NULL;
240
241 // store and cache all relationship types
242 $contactRelation = new CRM_Contact_DAO_RelationshipType();
243 $contactRelation->find();
244 while ($contactRelation->fetch()) {
c16da28a 245 $contactRelationCache[$contactRelation->id] = [];
6a488035
TO
246 $contactRelationCache[$contactRelation->id]['contact_type_a'] = $contactRelation->contact_type_a;
247 $contactRelationCache[$contactRelation->id]['contact_sub_type_a'] = $contactRelation->contact_sub_type_a;
248 $contactRelationCache[$contactRelation->id]['contact_type_b'] = $contactRelation->contact_type_b;
249 $contactRelationCache[$contactRelation->id]['contact_sub_type_b'] = $contactRelation->contact_sub_type_b;
250 }
c16da28a 251 $highlightedFields = $highlightedRelFields = [];
6a488035
TO
252
253 $highlightedFields['email'] = 'All';
254 $highlightedFields['external_identifier'] = 'All';
255 $highlightedFields['first_name'] = 'Individual';
256 $highlightedFields['last_name'] = 'Individual';
257 $highlightedFields['household_name'] = 'Household';
258 $highlightedFields['organization_name'] = 'Organization';
259
260 foreach ($mapperKeys as $key) {
261 // check if there is a _a_b or _b_a in the key
262 if (strpos($key, '_a_b') || strpos($key, '_b_a')) {
263 list($id, $first, $second) = explode('_', $key);
264 }
265 else {
266 $id = $first = $second = NULL;
267 }
4009859d 268 if (($first === 'a' && $second === 'b') || ($first === 'b' && $second === 'a')) {
6a488035
TO
269 $cType = $contactRelationCache[$id]["contact_type_{$second}"];
270
271 //CRM-5125 for contact subtype specific relationshiptypes
272 $cSubType = NULL;
a7488080 273 if (!empty($contactRelationCache[$id]["contact_sub_type_{$second}"])) {
6a488035
TO
274 $cSubType = $contactRelationCache[$id]["contact_sub_type_{$second}"];
275 }
276
277 if (!$cType) {
278 $cType = 'All';
279 }
280
6a488035
TO
281 $relatedFields = CRM_Contact_BAO_Contact::importableFields($cType);
282 unset($relatedFields['']);
c16da28a 283 $values = [];
6a488035
TO
284 foreach ($relatedFields as $name => $field) {
285 $values[$name] = $field['title'];
286 if (isset($hasLocationTypes[$name])) {
287 $sel3[$key][$name] = $this->_location_types;
288 }
4009859d 289 elseif ($name === 'url') {
6a488035
TO
290 $sel3[$key][$name] = $websiteTypes;
291 }
292 else {
293 $sel3[$name] = NULL;
294 }
295 }
296
297 //fix to append custom group name to field name, CRM-2676
a7488080 298 if (empty($this->_formattedFieldNames[$cType]) || $cType == $this->_contactType) {
6a488035
TO
299 $this->_formattedFieldNames[$cType] = $this->formatCustomFieldName($values);
300 }
301
302 $this->_formattedFieldNames[$cType] = array_merge($values, $this->_formattedFieldNames[$cType]);
303
304 //Modified the Relationship fields if the fields are
305 //present in dedupe rule
8cc574cf 306 if ($this->_onDuplicate != CRM_Import_Parser::DUPLICATE_NOCHECK && !empty($this->_dedupeFields[$cType]) &&
6a488035
TO
307 is_array($this->_dedupeFields[$cType])
308 ) {
c16da28a 309 static $cTypeArray = [];
6a488035
TO
310 if ($cType != $this->_contactType && !in_array($cType, $cTypeArray)) {
311 foreach ($this->_dedupeFields[$cType] as $val) {
312 if ($valTitle = CRM_Utils_Array::value($val, $this->_formattedFieldNames[$cType])) {
313 $this->_formattedFieldNames[$cType][$val] = $valTitle . ' (match to contact)';
314 }
315 }
316 $cTypeArray[] = $cType;
317 }
318 }
319
320 foreach ($highlightedFields as $k => $v) {
4009859d 321 if ($v == $cType || $v === 'All') {
6a488035
TO
322 $highlightedRelFields[$key][] = $k;
323 }
324 }
325 $this->assign('highlightedRelFields', $highlightedRelFields);
326 $sel2[$key] = $this->_formattedFieldNames[$cType];
327
328 if (!empty($cSubType)) {
329 //custom fields for sub type
330 $subTypeFields = CRM_Core_BAO_CustomField::getFieldsForImport($cSubType);
331
332 if (!empty($subTypeFields)) {
333 $subType = NULL;
334 foreach ($subTypeFields as $customSubTypeField => $details) {
335 $subType[$customSubTypeField] = $details['title'];
336 $sel2[$key] = array_merge($sel2[$key], $this->formatCustomFieldName($subType));
337 }
338 }
339 }
340
341 foreach ($this->_location_types as $k => $value) {
342 $sel4[$key]['phone'][$k] = &$phoneTypes;
343 //build array of IM service provider for related contact
344 $sel4[$key]['im'][$k] = &$imProviders;
345 }
346 }
347 else {
348 $options = NULL;
d454582f 349 if (!empty($hasLocationTypes[$key])) {
6a488035
TO
350 $options = $this->_location_types;
351 }
4009859d 352 elseif ($key === 'url') {
6a488035
TO
353 $options = $websiteTypes;
354 }
355 $sel2[$key] = $options;
356 }
357 }
358
359 $js = "<script type='text/javascript'>\n";
360 $formName = 'document.forms.' . $this->_name;
361 //used to warn for mismatch column count or mismatch mapping
0b786e49 362 CRM_Core_Session::singleton()->setStatus(NULL);
a2ca56ec 363 $processor = new CRM_Import_ImportProcessor();
364 $processor->setMappingID($savedMappingID);
365 $processor->setFormName($formName);
366 $processor->setMetadata($this->getContactImportMetadata());
b1498fda 367 $processor->setContactTypeByConstant($this->get('contactType'));
4b9648c2 368 $processor->setContactSubType($this->get('contactSubType'));
0b786e49 369
6a488035 370 for ($i = 0; $i < $this->_columnCount; $i++) {
c16da28a 371 $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL);
6a488035 372
a5eb54c5 373 if ($this->get('savedMapping') && $processor->getFieldName($i)) {
374 $defaults["mapper[$i]"] = $processor->getSavedQuickformDefaultsForColumn($i);
375 $js .= $processor->getQuickFormJSForField($i);
6a488035
TO
376 }
377 else {
378 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
379 if ($hasColumnNames) {
380 // do array search first to see if has mapped key
0c7dc463 381 $columnKey = array_search($this->_columnNames[$i], $this->getFieldTitles());
6a488035
TO
382 if (isset($this->_fieldUsed[$columnKey])) {
383 $defaults["mapper[$i]"] = $columnKey;
384 $this->_fieldUsed[$key] = TRUE;
385 }
386 else {
387 // Infer the default from the column names if we have them
c16da28a 388 $defaults["mapper[$i]"] = [
0c7dc463 389 $this->defaultFromColumnName($this->_columnNames[$i]),
6a488035 390 0,
c16da28a 391 ];
6a488035
TO
392 }
393 }
394 else {
395 // Otherwise guess the default from the form of the data
c16da28a 396 $defaults["mapper[$i]"] = [
5d9b686f 397 $this->defaultFromData($this->getDataPatterns(), $i),
6a488035
TO
398 // $defaultLocationType->id
399 0,
c16da28a 400 ];
6a488035
TO
401 }
402 }
c16da28a 403 $sel->setOptions([$sel1, $sel2, $sel3, $sel4]);
6a488035
TO
404 }
405
406 $js .= "</script>\n";
407 $this->assign('initHideBoxes', $js);
408
409 //set warning if mismatch in more than
410 if (isset($mappingName) &&
411 ($this->_columnCount != count($mappingName))
412 ) {
0b786e49 413 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.'));
6a488035
TO
414 }
415
416 $this->setDefaults($defaults);
417
c16da28a 418 $this->addButtons([
419 [
420 'type' => 'back',
421 'name' => ts('Previous'),
422 ],
423 [
424 'type' => 'next',
425 'name' => ts('Continue'),
426 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
427 'isDefault' => TRUE,
428 ],
429 [
430 'type' => 'cancel',
431 'name' => ts('Cancel'),
432 ],
433 ]);
6a488035
TO
434 }
435
436 /**
fe482240 437 * Global validation rules for the form.
6a488035 438 *
77c5b619
TO
439 * @param array $fields
440 * Posted values of the form.
6a488035 441 *
a6c01b45
CW
442 * @return array
443 * list of errors to be posted back to the form
6a488035 444 */
00be9182 445 public static function formRule($fields) {
c16da28a 446 $errors = [];
a7488080 447 if (!empty($fields['saveMapping'])) {
6a488035
TO
448 $nameField = CRM_Utils_Array::value('saveMappingName', $fields);
449 if (empty($nameField)) {
450 $errors['saveMappingName'] = ts('Name is required to save Import Mapping');
451 }
452 else {
c0a760fc 453 $mappingTypeId = CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', 'Import Contact');
6a488035
TO
454 if (CRM_Core_BAO_Mapping::checkMapping($nameField, $mappingTypeId)) {
455 $errors['saveMappingName'] = ts('Duplicate Import Mapping Name');
456 }
457 }
458 }
459 $template = CRM_Core_Smarty::singleton();
a7488080 460 if (!empty($fields['saveMapping'])) {
6a488035
TO
461 $template->assign('isCheked', TRUE);
462 }
463
464 if (!empty($errors)) {
465 $_flag = 1;
466 $assignError = new CRM_Core_Page();
467 $assignError->assign('mappingDetailsError', $_flag);
468 return $errors;
469 }
470 else {
471 return TRUE;
472 }
473 }
474
475 /**
f12c6f7d 476 * Process the mapped fields and map it into the uploaded file.
6a488035
TO
477 */
478 public function postProcess() {
479 $params = $this->controller->exportValues('MapField');
480
481 //reload the mapfield if load mapping is pressed
482 if (!empty($params['savedMapping'])) {
483 $this->set('savedMapping', $params['savedMapping']);
484 $this->controller->resetPage($this->_name);
485 return;
486 }
353ffa53 487 $mapperKeys = $this->controller->exportValue($this->_name, 'mapper');
52356383 488
489 $parser = $this->submit($params, $mapperKeys);
490
491 // add all the necessary variables to the form
492 $parser->set($this);
493 }
494
495 /**
496 * Format custom field name.
497 *
498 * Combine group and field name to avoid conflict.
499 *
500 * @param array $fields
501 *
502 * @return array
503 */
56dd62a0 504 public function formatCustomFieldName($fields) {
52356383 505 //CRM-2676, replacing the conflict for same custom field name from different custom group.
c16da28a 506 $fieldIds = $formattedFieldNames = [];
52356383 507 foreach ($fields as $key => $value) {
508 if ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($key)) {
509 $fieldIds[] = $customFieldId;
510 }
511 }
512
513 if (!empty($fieldIds) && is_array($fieldIds)) {
514 $groupTitles = CRM_Core_BAO_CustomGroup::getGroupTitles($fieldIds);
515
516 if (!empty($groupTitles)) {
517 foreach ($groupTitles as $fId => $values) {
518 $key = "custom_{$fId}";
519 $groupTitle = $values['groupTitle'];
520 $formattedFieldNames[$key] = $fields[$key] . ' :: ' . $groupTitle;
521 }
522 }
523 }
524
525 return $formattedFieldNames;
526 }
527
528 /**
529 * Main submit function.
530 *
531 * Extracted to add testing & start refactoring.
532 *
533 * @param $params
534 * @param $mapperKeys
535 *
536 * @return \CRM_Contact_Import_Parser_Contact
449fda1c 537 * @throws \CiviCRM_API3_Exception
52356383 538 */
539 public function submit($params, $mapperKeys) {
c16da28a 540 $mapper = $mapperKeysMain = $locations = [];
1881b7b0 541 $parserParameters = CRM_Contact_Import_Parser_Contact::getParameterForParser($this->_columnCount);
6a488035 542
353ffa53
TO
543 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
544 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
545 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
b2b0530a 546 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
6ebecfea 547 $locationTypes['Primary'] = ts('Primary');
6a488035 548
6a488035 549 for ($i = 0; $i < $this->_columnCount; $i++) {
6a488035 550
353ffa53
TO
551 $fldName = CRM_Utils_Array::value(0, $mapperKeys[$i]);
552 $selOne = CRM_Utils_Array::value(1, $mapperKeys[$i]);
553 $selTwo = CRM_Utils_Array::value(2, $mapperKeys[$i]);
554 $selThree = CRM_Utils_Array::value(3, $mapperKeys[$i]);
555 $mapper[$i] = $this->_mapperFields[$mapperKeys[$i][0]];
6a488035
TO
556 $mapperKeysMain[$i] = $fldName;
557
558 //need to differentiate non location elements.
6ebecfea 559 if ($selOne && (is_numeric($selOne) || $selOne === 'Primary')) {
4009859d 560 if ($fldName === 'url') {
1881b7b0 561 $parserParameters['mapperWebsiteType'][$i] = $websiteTypes[$selOne];
6a488035
TO
562 }
563 else {
1881b7b0 564 $locations[$i] = $locationTypes[$selOne];
565 $parserParameters['mapperLocType'][$i] = $selOne;
6a488035 566 if ($selTwo && is_numeric($selTwo)) {
4009859d 567 if ($fldName === 'phone') {
1881b7b0 568 $parserParameters['mapperPhoneType'][$i] = $phoneTypes[$selTwo];
6a488035 569 }
4009859d 570 elseif ($fldName === 'im') {
1881b7b0 571 $parserParameters['mapperImProvider'][$i] = $imProviders[$selTwo];
6a488035
TO
572 }
573 }
574 }
575 }
576
577 //relationship contact mapper info.
578 list($id, $first, $second) = CRM_Utils_System::explode('_', $fldName, 3);
4009859d 579 if (($first === 'a' && $second === 'b') ||
580 ($first === 'b' && $second === 'a')
6a488035 581 ) {
1881b7b0 582 $parserParameters['mapperRelated'][$i] = $this->_mapperFields[$fldName];
6a488035 583 if ($selOne) {
4009859d 584 if ($selOne === 'url') {
1881b7b0 585 $parserParameters['relatedContactWebsiteType'][$i] = $websiteTypes[$selTwo];
6a488035
TO
586 }
587 else {
1881b7b0 588 $parserParameters['relatedContactLocType'][$i] = CRM_Utils_Array::value($selTwo, $locationTypes);
6a488035 589 if ($selThree) {
4009859d 590 if ($selOne === 'phone') {
1881b7b0 591 $parserParameters['relatedContactPhoneType'][$i] = $phoneTypes[$selThree];
6a488035 592 }
4009859d 593 elseif ($selOne === 'im') {
1881b7b0 594 $parserParameters['relatedContactImProvider'][$i] = $imProviders[$selThree];
6a488035
TO
595 }
596 }
597 }
598
599 //get the related contact type.
600 $relationType = new CRM_Contact_DAO_RelationshipType();
601 $relationType->id = $id;
602 $relationType->find(TRUE);
1881b7b0 603 $parserParameters['relatedContactType'][$i] = $relationType->{"contact_type_$second"};
604 $parserParameters['relatedContactDetails'][$i] = $this->_formattedFieldNames[$parserParameters['relatedContactType'][$i]][$selOne];
6a488035
TO
605 }
606 }
6a488035
TO
607 }
608
609 $this->set('columnNames', $this->_columnNames);
1881b7b0 610 $this->set('websites', $parserParameters['mapperWebsiteType']);
611 $this->set('locations', $locations);
612 $this->set('phones', $parserParameters['mapperPhoneType']);
613 $this->set('ims', $parserParameters['mapperImProvider']);
614 $this->set('related', $parserParameters['mapperRelated']);
615 $this->set('relatedContactType', $parserParameters['relatedContactType']);
616 $this->set('relatedContactDetails', $parserParameters['relatedContactDetails']);
617 $this->set('relatedContactLocType', $parserParameters['relatedContactLocType']);
618 $this->set('relatedContactPhoneType', $parserParameters['relatedContactPhoneType']);
619 $this->set('relatedContactImProvider', $parserParameters['relatedContactImProvider']);
620 $this->set('relatedContactWebsiteType', $parserParameters['relatedContactWebsiteType']);
621 $this->set('mapper', $mapper);
6a488035
TO
622
623 // store mapping Id to display it in the preview page
624 $this->set('loadMappingId', CRM_Utils_Array::value('mappingId', $params));
625
626 //Updating Mapping Records
a7488080 627 if (!empty($params['updateMapping'])) {
6a488035 628
6a488035
TO
629 $mappingFields = new CRM_Core_DAO_MappingField();
630 $mappingFields->mapping_id = $params['mappingId'];
631 $mappingFields->find();
632
c16da28a 633 $mappingFieldsId = [];
6a488035
TO
634 while ($mappingFields->fetch()) {
635 if ($mappingFields->id) {
636 $mappingFieldsId[$mappingFields->column_number] = $mappingFields->id;
637 }
638 }
639
640 for ($i = 0; $i < $this->_columnCount; $i++) {
641 $updateMappingFields = new CRM_Core_DAO_MappingField();
ce80b209 642 $updateMappingFields->id = CRM_Utils_Array::value($i, $mappingFieldsId);
6a488035
TO
643 $updateMappingFields->mapping_id = $params['mappingId'];
644 $updateMappingFields->column_number = $i;
645
646 $mapperKeyParts = explode('_', $mapperKeys[$i][0], 3);
353ffa53
TO
647 $id = isset($mapperKeyParts[0]) ? $mapperKeyParts[0] : NULL;
648 $first = isset($mapperKeyParts[1]) ? $mapperKeyParts[1] : NULL;
649 $second = isset($mapperKeyParts[2]) ? $mapperKeyParts[2] : NULL;
6a488035
TO
650 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
651 $updateMappingFields->relationship_type_id = $id;
652 $updateMappingFields->relationship_direction = "{$first}_{$second}";
653 $updateMappingFields->name = ucwords(str_replace("_", " ", $mapperKeys[$i][1]));
654 // get phoneType id and provider id separately
655 // before updating mappingFields of phone and IM for related contact, CRM-3140
656 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'url') {
657 $updateMappingFields->website_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
658 }
659 else {
660 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'phone') {
661 $updateMappingFields->phone_type_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
662 }
663 elseif (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'im') {
664 $updateMappingFields->im_provider_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
665 }
af88ad41 666 $updateMappingFields->location_type_id = isset($mapperKeys[$i][2]) && is_numeric($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
6a488035
TO
667 }
668 }
669 else {
670 $updateMappingFields->name = $mapper[$i];
671 $updateMappingFields->relationship_type_id = 'NULL';
672 $updateMappingFields->relationship_type_direction = 'NULL';
b44e3f84 673 // to store phoneType id and provider id separately
6a488035
TO
674 // before updating mappingFields for phone and IM, CRM-3140
675 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'url') {
676 $updateMappingFields->website_type_id = isset($mapperKeys[$i][1]) ? $mapperKeys[$i][1] : NULL;
677 }
678 else {
679 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'phone') {
680 $updateMappingFields->phone_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
681 }
682 elseif (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'im') {
683 $updateMappingFields->im_provider_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
684 }
6ebecfea 685 $locationTypeID = $parserParameters['mapperLocType'][$i];
686 // location_type_id is NULL for non-location fields, and for Primary location.
687 $updateMappingFields->location_type_id = is_numeric($locationTypeID) ? $locationTypeID : 'null';
6a488035
TO
688 }
689 }
690 $updateMappingFields->save();
691 }
692 }
693
694 //Saving Mapping Details and Records
a7488080 695 if (!empty($params['saveMapping'])) {
c16da28a 696 $mappingParams = [
6a488035
TO
697 'name' => $params['saveMappingName'],
698 'description' => $params['saveMappingDesc'],
37353970 699 'mapping_type_id' => 'Import Contact',
c16da28a 700 ];
6a488035 701
37353970 702 $saveMapping = civicrm_api3('Mapping', 'create', $mappingParams);
6a488035 703
6a488035
TO
704 $contactType = $this->get('contactType');
705 switch ($contactType) {
a05662ef 706 case CRM_Import_Parser::CONTACT_INDIVIDUAL:
6a488035
TO
707 $cType = 'Individual';
708 break;
709
a05662ef 710 case CRM_Import_Parser::CONTACT_HOUSEHOLD:
6a488035
TO
711 $cType = 'Household';
712 break;
713
a05662ef 714 case CRM_Import_Parser::CONTACT_ORGANIZATION:
6a488035
TO
715 $cType = 'Organization';
716 }
717
449fda1c 718 $mappingID = NULL;
6a488035 719 for ($i = 0; $i < $this->_columnCount; $i++) {
449fda1c 720 $mappingID = $this->saveMappingField($mapperKeys, $saveMapping, $cType, $i, $mapper, $parserParameters);
6a488035 721 }
449fda1c 722 $this->set('savedMapping', $mappingID);
6a488035
TO
723 }
724
1881b7b0 725 $parser = new CRM_Contact_Import_Parser_Contact($mapperKeysMain, $parserParameters['mapperLocType'], $parserParameters['mapperPhoneType'],
726 $parserParameters['mapperImProvider'], $parserParameters['mapperRelated'], $parserParameters['relatedContactType'],
727 $parserParameters['relatedContactDetails'], $parserParameters['relatedContactLocType'],
728 $parserParameters['relatedContactPhoneType'], $parserParameters['relatedContactImProvider'],
729 $parserParameters['mapperWebsiteType'], $parserParameters['relatedContactWebsiteType']
6a488035
TO
730 );
731
732 $primaryKeyName = $this->get('primaryKeyName');
733 $statusFieldName = $this->get('statusFieldName');
734 $parser->run($this->_importTableName,
735 $mapper,
a05662ef 736 CRM_Import_Parser::MODE_PREVIEW,
6a488035
TO
737 $this->get('contactType'),
738 $primaryKeyName,
739 $statusFieldName,
740 $this->_onDuplicate,
741 NULL, NULL, FALSE,
719a6fec 742 CRM_Contact_Import_Parser::DEFAULT_TIMEOUT,
6a488035
TO
743 $this->get('contactSubType'),
744 $this->get('dedupe')
745 );
52356383 746 return $parser;
6a488035 747 }
96025800 748
449fda1c 749 /**
750 * @param $mapperKeys
751 * @param array $saveMapping
752 * @param string $cType
753 * @param int $i
754 * @param array $mapper
755 * @param array $parserParameters
756 *
757 * @return int
758 */
759 protected function saveMappingField($mapperKeys, array $saveMapping, string $cType, int $i, array $mapper, array $parserParameters): int {
760 $saveMappingFields = new CRM_Core_DAO_MappingField();
761 $saveMappingFields->mapping_id = $saveMapping['id'];
762 $saveMappingFields->contact_type = $cType;
763 $saveMappingFields->column_number = $i;
764
765 $mapperKeyParts = explode('_', $mapperKeys[$i][0], 3);
766 $id = isset($mapperKeyParts[0]) ? $mapperKeyParts[0] : NULL;
767 $first = isset($mapperKeyParts[1]) ? $mapperKeyParts[1] : NULL;
768 $second = isset($mapperKeyParts[2]) ? $mapperKeyParts[2] : NULL;
769 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
770 $saveMappingFields->name = ucwords(str_replace("_", " ", $mapperKeys[$i][1]));
771 $saveMappingFields->relationship_type_id = $id;
772 $saveMappingFields->relationship_direction = "{$first}_{$second}";
773 // to get phoneType id and provider id separately
774 // before saving mappingFields of phone and IM for related contact, CRM-3140
775 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'url') {
776 $saveMappingFields->website_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
777 }
778 else {
779 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'phone') {
780 $saveMappingFields->phone_type_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
781 }
782 elseif (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'im') {
783 $saveMappingFields->im_provider_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
784 }
785 $saveMappingFields->location_type_id = (isset($mapperKeys[$i][2]) && $mapperKeys[$i][2] !== 'Primary') ? $mapperKeys[$i][2] : NULL;
786 }
787 }
788 else {
789 $saveMappingFields->name = $mapper[$i];
790 $locationTypeID = $parserParameters['mapperLocType'][$i];
791 // to get phoneType id and provider id separately
792 // before saving mappingFields of phone and IM, CRM-3140
793 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'url') {
794 $saveMappingFields->website_type_id = isset($mapperKeys[$i][1]) ? $mapperKeys[$i][1] : NULL;
795 }
796 else {
797 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'phone') {
798 $saveMappingFields->phone_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
799 }
800 elseif (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'im') {
801 $saveMappingFields->im_provider_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
802 }
803 $saveMappingFields->location_type_id = is_numeric($locationTypeID) ? $locationTypeID : NULL;
804 }
805 $saveMappingFields->relationship_type_id = NULL;
806 }
807 $saveMappingFields->save();
808 return $saveMappingFields->mapping_id;
809 }
810
6a488035 811}