[REF] [Import] Remove last instance of passing fieldTypes through get->set
[civicrm-core.git] / CRM / Contact / Import / Form / MapField.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
259dd586
EM
18use Civi\Api4\MappingField;
19
6a488035 20/**
f12c6f7d 21 * This class gets the name of the file to upload.
6a488035 22 */
b26295b8 23class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {
6a488035 24
a2ca56ec 25 use CRM_Contact_Import_MetadataTrait;
6a488035
TO
26
27 /**
100fef9d 28 * An array of all contact fields with
6a488035
TO
29 * formatted custom field names.
30 *
31 * @var array
6a488035 32 */
d4c8a770 33 protected $_formattedFieldNames;
6a488035 34
6a488035
TO
35 protected $_dedupeFields;
36
37 /**
fe482240 38 * Attempt to match header labels with our mapper fields.
2b4bc760 39 *
b26295b8 40 * FIXME: This is essentially the same function as parent::defaultFromHeader
6a488035 41 *
2b4bc760 42 * @param string $columnName name of column header
6a488035
TO
43 *
44 * @return string
6a488035 45 */
0c7dc463 46 public function defaultFromColumnName($columnName) {
6a488035
TO
47
48 if (!preg_match('/^[a-z0-9 ]$/i', $columnName)) {
e119ba7d 49 if ($columnKey = array_search($columnName, $this->getFieldTitles())) {
6a488035
TO
50 $this->_fieldUsed[$columnKey] = TRUE;
51 return $columnKey;
52 }
53 }
54
0c7dc463 55 foreach ($this->getHeaderPatterns() as $key => $re) {
6a488035
TO
56 // Skip empty key/patterns
57 if (!$key || !$re || strlen("$re") < 5) {
58 continue;
59 }
60
61 if (preg_match($re, $columnName)) {
62 $this->_fieldUsed[$key] = TRUE;
63 return $key;
64 }
65 }
66 return '';
67 }
68
6a488035 69 /**
fe482240 70 * Set variables up before form is built.
4a01628c
EM
71 *
72 * @throws \API_Exception
73 * @throws \CRM_Core_Exception
74 * @throws \Civi\API\Exception\UnauthorizedException
6a488035
TO
75 */
76 public function preProcess() {
52bd01f5 77 $this->_mapperFields = $this->getAvailableFields();
80cb71bb 78 $this->_contactSubType = $this->getSubmittedValue('contactSubType');
6a488035 79 //format custom field names, CRM-2676
6e78138c 80 $contactType = $this->getContactType();
09594ee8 81
6a488035 82 $this->_contactType = $contactType;
6a488035 83
971e67cf 84 if ($this->isIgnoreDuplicates()) {
6a488035 85 //Mark Dedupe Rule Fields as required, since it's used in matching contact
2d35bc78 86 foreach (CRM_Contact_BAO_ContactType::basicTypes() as $cType) {
c16da28a 87 $ruleParams = [
6a488035 88 'contact_type' => $cType,
353ffa53 89 'used' => 'Unsupervised',
c16da28a 90 ];
61194d45 91 $this->_dedupeFields[$cType] = CRM_Dedupe_BAO_DedupeRule::dedupeRuleFields($ruleParams);
6a488035
TO
92 }
93
94 //Modify mapper fields title if fields are present in dedupe rule
95 if (is_array($this->_dedupeFields[$contactType])) {
96 foreach ($this->_dedupeFields[$contactType] as $val) {
97 if ($valTitle = CRM_Utils_Array::value($val, $this->_mapperFields)) {
98 $this->_mapperFields[$val] = $valTitle . ' (match to contact)';
99 }
100 }
101 }
102 }
7b00a95d 103 // retrieve and highlight required custom fields
817cf27c 104 $formattedFieldNames = $this->formatCustomFieldName($this->_mapperFields);
09594ee8
EM
105
106 $this->assign('highlightedFields', $this->getHighlightedFields());
817cf27c 107 $this->_formattedFieldNames[$contactType] = $this->_mapperFields = array_merge($this->_mapperFields, $formattedFieldNames);
6a488035 108
4a01628c 109 $columnNames = $this->getColumnHeaders();
6a488035 110
4a01628c 111 $this->_columnCount = $this->getNumberOfColumns();
6a488035 112 $this->_columnNames = $columnNames;
4a01628c 113 $this->assign('columnNames', $this->getColumnHeaders());
6a488035 114 $this->assign('columnCount', $this->_columnCount);
99e3c5f7 115 $this->_dataValues = array_values($this->getDataRows([], 2));
6a488035 116 $this->assign('dataValues', $this->_dataValues);
6a488035
TO
117 }
118
119 /**
fe482240 120 * Build the form object.
a2ca56ec 121 *
122 * @throws \CiviCRM_API3_Exception
f5f34a57 123 * @throws \CRM_Core_Exception
6a488035
TO
124 */
125 public function buildQuickForm() {
f5f34a57 126 $savedMappingID = (int) $this->getSubmittedValue('savedMapping');
27a00f6b 127 $this->buildSavedMappingFields($savedMappingID);
6a488035 128
c16da28a 129 $this->addFormRule(['CRM_Contact_Import_Form_MapField', 'formRule']);
6a488035
TO
130
131 //-------- end of saved mapping stuff ---------
132
c16da28a 133 $defaults = [];
353ffa53
TO
134 $mapperKeys = array_keys($this->_mapperFields);
135 $hasColumnNames = !empty($this->_columnNames);
6a488035 136
c16da28a 137 $this->_location_types = ['Primary' => ts('Primary')] + CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
6a488035 138 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
45a50743
EM
139 $this->assign('defaultLocationType', $defaultLocationType->id);
140 $this->assign('defaultLocationTypeLabel', $this->_location_types[$defaultLocationType->id]);
6a488035
TO
141
142 /* Initialize all field usages to false */
6a488035
TO
143 foreach ($mapperKeys as $key) {
144 $this->_fieldUsed[$key] = FALSE;
145 }
146
147 $sel1 = $this->_mapperFields;
148 $sel2[''] = NULL;
149
353ffa53
TO
150 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
151 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
cbf48754 152 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
6a488035
TO
153
154 foreach ($this->_location_types as $key => $value) {
155 $sel3['phone'][$key] = &$phoneTypes;
006f8d5b 156 $sel3['phone_ext'][$key] = &$phoneTypes;
6a488035
TO
157 //build array for IM service provider type for contact
158 $sel3['im'][$key] = &$imProviders;
159 }
160
161 $sel4 = NULL;
162
163 // store and cache all relationship types
164 $contactRelation = new CRM_Contact_DAO_RelationshipType();
165 $contactRelation->find();
166 while ($contactRelation->fetch()) {
c16da28a 167 $contactRelationCache[$contactRelation->id] = [];
6a488035
TO
168 $contactRelationCache[$contactRelation->id]['contact_type_a'] = $contactRelation->contact_type_a;
169 $contactRelationCache[$contactRelation->id]['contact_sub_type_a'] = $contactRelation->contact_sub_type_a;
170 $contactRelationCache[$contactRelation->id]['contact_type_b'] = $contactRelation->contact_type_b;
171 $contactRelationCache[$contactRelation->id]['contact_sub_type_b'] = $contactRelation->contact_sub_type_b;
172 }
c16da28a 173 $highlightedFields = $highlightedRelFields = [];
6a488035
TO
174
175 $highlightedFields['email'] = 'All';
176 $highlightedFields['external_identifier'] = 'All';
177 $highlightedFields['first_name'] = 'Individual';
178 $highlightedFields['last_name'] = 'Individual';
179 $highlightedFields['household_name'] = 'Household';
180 $highlightedFields['organization_name'] = 'Organization';
181
182 foreach ($mapperKeys as $key) {
183 // check if there is a _a_b or _b_a in the key
184 if (strpos($key, '_a_b') || strpos($key, '_b_a')) {
4a01628c 185 [$id, $first, $second] = explode('_', $key);
6a488035
TO
186 }
187 else {
188 $id = $first = $second = NULL;
189 }
4009859d 190 if (($first === 'a' && $second === 'b') || ($first === 'b' && $second === 'a')) {
6a488035
TO
191 $cType = $contactRelationCache[$id]["contact_type_{$second}"];
192
193 //CRM-5125 for contact subtype specific relationshiptypes
194 $cSubType = NULL;
a7488080 195 if (!empty($contactRelationCache[$id]["contact_sub_type_{$second}"])) {
6a488035
TO
196 $cSubType = $contactRelationCache[$id]["contact_sub_type_{$second}"];
197 }
198
199 if (!$cType) {
200 $cType = 'All';
201 }
202
6a488035
TO
203 $relatedFields = CRM_Contact_BAO_Contact::importableFields($cType);
204 unset($relatedFields['']);
c16da28a 205 $values = [];
6a488035
TO
206 foreach ($relatedFields as $name => $field) {
207 $values[$name] = $field['title'];
79d21b5b 208 if ($this->isLocationTypeRequired($name)) {
6a488035
TO
209 $sel3[$key][$name] = $this->_location_types;
210 }
4009859d 211 elseif ($name === 'url') {
6a488035
TO
212 $sel3[$key][$name] = $websiteTypes;
213 }
214 else {
215 $sel3[$name] = NULL;
216 }
217 }
218
219 //fix to append custom group name to field name, CRM-2676
a7488080 220 if (empty($this->_formattedFieldNames[$cType]) || $cType == $this->_contactType) {
6a488035
TO
221 $this->_formattedFieldNames[$cType] = $this->formatCustomFieldName($values);
222 }
223
224 $this->_formattedFieldNames[$cType] = array_merge($values, $this->_formattedFieldNames[$cType]);
225
226 //Modified the Relationship fields if the fields are
227 //present in dedupe rule
971e67cf 228 if ($this->isIgnoreDuplicates() && !empty($this->_dedupeFields[$cType]) &&
6a488035
TO
229 is_array($this->_dedupeFields[$cType])
230 ) {
c16da28a 231 static $cTypeArray = [];
6a488035
TO
232 if ($cType != $this->_contactType && !in_array($cType, $cTypeArray)) {
233 foreach ($this->_dedupeFields[$cType] as $val) {
234 if ($valTitle = CRM_Utils_Array::value($val, $this->_formattedFieldNames[$cType])) {
235 $this->_formattedFieldNames[$cType][$val] = $valTitle . ' (match to contact)';
236 }
237 }
238 $cTypeArray[] = $cType;
239 }
240 }
241
242 foreach ($highlightedFields as $k => $v) {
4009859d 243 if ($v == $cType || $v === 'All') {
6a488035
TO
244 $highlightedRelFields[$key][] = $k;
245 }
246 }
247 $this->assign('highlightedRelFields', $highlightedRelFields);
248 $sel2[$key] = $this->_formattedFieldNames[$cType];
249
250 if (!empty($cSubType)) {
251 //custom fields for sub type
252 $subTypeFields = CRM_Core_BAO_CustomField::getFieldsForImport($cSubType);
253
254 if (!empty($subTypeFields)) {
255 $subType = NULL;
256 foreach ($subTypeFields as $customSubTypeField => $details) {
257 $subType[$customSubTypeField] = $details['title'];
258 $sel2[$key] = array_merge($sel2[$key], $this->formatCustomFieldName($subType));
259 }
260 }
261 }
262
263 foreach ($this->_location_types as $k => $value) {
264 $sel4[$key]['phone'][$k] = &$phoneTypes;
006f8d5b 265 $sel4[$key]['phone_ext'][$k] = &$phoneTypes;
6a488035
TO
266 //build array of IM service provider for related contact
267 $sel4[$key]['im'][$k] = &$imProviders;
268 }
269 }
270 else {
271 $options = NULL;
79d21b5b 272 if ($this->isLocationTypeRequired($key)) {
6a488035
TO
273 $options = $this->_location_types;
274 }
4009859d 275 elseif ($key === 'url') {
6a488035
TO
276 $options = $websiteTypes;
277 }
278 $sel2[$key] = $options;
279 }
280 }
281
282 $js = "<script type='text/javascript'>\n";
283 $formName = 'document.forms.' . $this->_name;
284 //used to warn for mismatch column count or mismatch mapping
0b786e49 285 CRM_Core_Session::singleton()->setStatus(NULL);
a2ca56ec 286 $processor = new CRM_Import_ImportProcessor();
287 $processor->setMappingID($savedMappingID);
288 $processor->setFormName($formName);
289 $processor->setMetadata($this->getContactImportMetadata());
f5f34a57 290 $processor->setContactTypeByConstant($this->getSubmittedValue('contactType'));
80cb71bb 291 $processor->setContactSubType($this->getSubmittedValue('contactSubType'));
0b786e49 292
6a488035 293 for ($i = 0; $i < $this->_columnCount; $i++) {
c16da28a 294 $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL);
6a488035 295
f5f34a57 296 if ($this->getSubmittedValue('savedMapping') && $processor->getFieldName($i)) {
a5eb54c5 297 $defaults["mapper[$i]"] = $processor->getSavedQuickformDefaultsForColumn($i);
298 $js .= $processor->getQuickFormJSForField($i);
6a488035
TO
299 }
300 else {
301 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
302 if ($hasColumnNames) {
303 // do array search first to see if has mapped key
0c7dc463 304 $columnKey = array_search($this->_columnNames[$i], $this->getFieldTitles());
6a488035
TO
305 if (isset($this->_fieldUsed[$columnKey])) {
306 $defaults["mapper[$i]"] = $columnKey;
307 $this->_fieldUsed[$key] = TRUE;
308 }
309 else {
310 // Infer the default from the column names if we have them
c16da28a 311 $defaults["mapper[$i]"] = [
0c7dc463 312 $this->defaultFromColumnName($this->_columnNames[$i]),
6a488035 313 0,
c16da28a 314 ];
6a488035
TO
315 }
316 }
317 else {
318 // Otherwise guess the default from the form of the data
c16da28a 319 $defaults["mapper[$i]"] = [
5d9b686f 320 $this->defaultFromData($this->getDataPatterns(), $i),
6a488035
TO
321 // $defaultLocationType->id
322 0,
c16da28a 323 ];
6a488035
TO
324 }
325 }
c16da28a 326 $sel->setOptions([$sel1, $sel2, $sel3, $sel4]);
6a488035
TO
327 }
328
329 $js .= "</script>\n";
330 $this->assign('initHideBoxes', $js);
331
6a488035
TO
332 $this->setDefaults($defaults);
333
c16da28a 334 $this->addButtons([
335 [
336 'type' => 'back',
337 'name' => ts('Previous'),
338 ],
339 [
340 'type' => 'next',
341 'name' => ts('Continue'),
342 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
343 'isDefault' => TRUE,
344 ],
345 [
346 'type' => 'cancel',
347 'name' => ts('Cancel'),
348 ],
349 ]);
6a488035
TO
350 }
351
352 /**
fe482240 353 * Global validation rules for the form.
6a488035 354 *
77c5b619
TO
355 * @param array $fields
356 * Posted values of the form.
6a488035 357 *
d51e2d1f 358 * @return array|true
a6c01b45 359 * list of errors to be posted back to the form
6a488035 360 */
00be9182 361 public static function formRule($fields) {
c16da28a 362 $errors = [];
a7488080 363 if (!empty($fields['saveMapping'])) {
9c1bc317 364 $nameField = $fields['saveMappingName'] ?? NULL;
6a488035
TO
365 if (empty($nameField)) {
366 $errors['saveMappingName'] = ts('Name is required to save Import Mapping');
367 }
368 else {
c0a760fc 369 $mappingTypeId = CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', 'Import Contact');
6a488035
TO
370 if (CRM_Core_BAO_Mapping::checkMapping($nameField, $mappingTypeId)) {
371 $errors['saveMappingName'] = ts('Duplicate Import Mapping Name');
372 }
373 }
374 }
375 $template = CRM_Core_Smarty::singleton();
a7488080 376 if (!empty($fields['saveMapping'])) {
6a488035
TO
377 $template->assign('isCheked', TRUE);
378 }
d51e2d1f 379 return empty($errors) ? TRUE : $errors;
6a488035
TO
380 }
381
382 /**
f12c6f7d 383 * Process the mapped fields and map it into the uploaded file.
6a488035
TO
384 */
385 public function postProcess() {
386 $params = $this->controller->exportValues('MapField');
387
388 //reload the mapfield if load mapping is pressed
389 if (!empty($params['savedMapping'])) {
390 $this->set('savedMapping', $params['savedMapping']);
391 $this->controller->resetPage($this->_name);
392 return;
393 }
4473c68d
EM
394 $this->updateUserJobMetadata('submitted_values', $this->getSubmittedValues());
395 $parser = $this->submit($params);
52356383 396
397 // add all the necessary variables to the form
398 $parser->set($this);
399 }
400
401 /**
402 * Format custom field name.
403 *
404 * Combine group and field name to avoid conflict.
405 *
406 * @param array $fields
407 *
408 * @return array
409 */
56dd62a0 410 public function formatCustomFieldName($fields) {
52356383 411 //CRM-2676, replacing the conflict for same custom field name from different custom group.
c16da28a 412 $fieldIds = $formattedFieldNames = [];
52356383 413 foreach ($fields as $key => $value) {
414 if ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($key)) {
415 $fieldIds[] = $customFieldId;
416 }
417 }
418
419 if (!empty($fieldIds) && is_array($fieldIds)) {
420 $groupTitles = CRM_Core_BAO_CustomGroup::getGroupTitles($fieldIds);
421
422 if (!empty($groupTitles)) {
423 foreach ($groupTitles as $fId => $values) {
424 $key = "custom_{$fId}";
425 $groupTitle = $values['groupTitle'];
426 $formattedFieldNames[$key] = $fields[$key] . ' :: ' . $groupTitle;
427 }
428 }
429 }
430
431 return $formattedFieldNames;
432 }
433
434 /**
435 * Main submit function.
436 *
437 * Extracted to add testing & start refactoring.
438 *
439 * @param $params
440 * @param $mapperKeys
441 *
442 * @return \CRM_Contact_Import_Parser_Contact
449fda1c 443 * @throws \CiviCRM_API3_Exception
971e67cf 444 * @throws \CRM_Core_Exception
52356383 445 */
4473c68d
EM
446 public function submit($params) {
447 $mapperKeys = $this->getSubmittedValue('mapper');
c16da28a 448 $mapper = $mapperKeysMain = $locations = [];
1881b7b0 449 $parserParameters = CRM_Contact_Import_Parser_Contact::getParameterForParser($this->_columnCount);
6a488035 450
353ffa53
TO
451 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
452 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
453 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
b2b0530a 454 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
6ebecfea 455 $locationTypes['Primary'] = ts('Primary');
6a488035 456
6a488035 457 for ($i = 0; $i < $this->_columnCount; $i++) {
6a488035 458
9c1bc317
CW
459 $fldName = $mapperKeys[$i][0] ?? NULL;
460 $selOne = $mapperKeys[$i][1] ?? NULL;
461 $selTwo = $mapperKeys[$i][2] ?? NULL;
462 $selThree = $mapperKeys[$i][3] ?? NULL;
353ffa53 463 $mapper[$i] = $this->_mapperFields[$mapperKeys[$i][0]];
6a488035
TO
464 $mapperKeysMain[$i] = $fldName;
465
466 //need to differentiate non location elements.
6ebecfea 467 if ($selOne && (is_numeric($selOne) || $selOne === 'Primary')) {
4009859d 468 if ($fldName === 'url') {
1881b7b0 469 $parserParameters['mapperWebsiteType'][$i] = $websiteTypes[$selOne];
6a488035
TO
470 }
471 else {
1881b7b0 472 $locations[$i] = $locationTypes[$selOne];
473 $parserParameters['mapperLocType'][$i] = $selOne;
6a488035 474 if ($selTwo && is_numeric($selTwo)) {
3aca1423 475 if ($fldName === 'phone' || $fldName === 'phone_ext') {
1881b7b0 476 $parserParameters['mapperPhoneType'][$i] = $phoneTypes[$selTwo];
6a488035 477 }
4009859d 478 elseif ($fldName === 'im') {
1881b7b0 479 $parserParameters['mapperImProvider'][$i] = $imProviders[$selTwo];
6a488035
TO
480 }
481 }
482 }
483 }
484
485 //relationship contact mapper info.
4a01628c 486 [$id, $first, $second] = CRM_Utils_System::explode('_', $fldName, 3);
4009859d 487 if (($first === 'a' && $second === 'b') ||
488 ($first === 'b' && $second === 'a')
6a488035 489 ) {
1881b7b0 490 $parserParameters['mapperRelated'][$i] = $this->_mapperFields[$fldName];
6a488035 491 if ($selOne) {
4009859d 492 if ($selOne === 'url') {
1881b7b0 493 $parserParameters['relatedContactWebsiteType'][$i] = $websiteTypes[$selTwo];
6a488035
TO
494 }
495 else {
9c1bc317 496 $parserParameters['relatedContactLocType'][$i] = $locationTypes[$selTwo] ?? NULL;
6a488035 497 if ($selThree) {
006f8d5b 498 if ($selOne === 'phone' || $selOne === 'phone_ext') {
1881b7b0 499 $parserParameters['relatedContactPhoneType'][$i] = $phoneTypes[$selThree];
6a488035 500 }
4009859d 501 elseif ($selOne === 'im') {
1881b7b0 502 $parserParameters['relatedContactImProvider'][$i] = $imProviders[$selThree];
6a488035
TO
503 }
504 }
505 }
506
507 //get the related contact type.
508 $relationType = new CRM_Contact_DAO_RelationshipType();
509 $relationType->id = $id;
510 $relationType->find(TRUE);
1881b7b0 511 $parserParameters['relatedContactType'][$i] = $relationType->{"contact_type_$second"};
512 $parserParameters['relatedContactDetails'][$i] = $this->_formattedFieldNames[$parserParameters['relatedContactType'][$i]][$selOne];
6a488035
TO
513 }
514 }
6a488035
TO
515 }
516
517 $this->set('columnNames', $this->_columnNames);
6a488035
TO
518
519 // store mapping Id to display it in the preview page
520 $this->set('loadMappingId', CRM_Utils_Array::value('mappingId', $params));
521
522 //Updating Mapping Records
a7488080 523 if (!empty($params['updateMapping'])) {
6a488035 524 for ($i = 0; $i < $this->_columnCount; $i++) {
259dd586 525 $this->saveMappingField($params['mappingId'], $i, TRUE);
6a488035
TO
526 }
527 }
528
529 //Saving Mapping Details and Records
a7488080 530 if (!empty($params['saveMapping'])) {
c16da28a 531 $mappingParams = [
6a488035
TO
532 'name' => $params['saveMappingName'],
533 'description' => $params['saveMappingDesc'],
37353970 534 'mapping_type_id' => 'Import Contact',
c16da28a 535 ];
6a488035 536
37353970 537 $saveMapping = civicrm_api3('Mapping', 'create', $mappingParams);
6a488035 538
4a01628c 539 foreach (array_keys($this->getColumnHeaders()) as $i) {
259dd586 540 $this->saveMappingField($saveMapping['id'], $i);
6a488035 541 }
259dd586 542 $this->set('savedMapping', $saveMapping['id']);
6a488035
TO
543 }
544
1881b7b0 545 $parser = new CRM_Contact_Import_Parser_Contact($mapperKeysMain, $parserParameters['mapperLocType'], $parserParameters['mapperPhoneType'],
546 $parserParameters['mapperImProvider'], $parserParameters['mapperRelated'], $parserParameters['relatedContactType'],
547 $parserParameters['relatedContactDetails'], $parserParameters['relatedContactLocType'],
548 $parserParameters['relatedContactPhoneType'], $parserParameters['relatedContactImProvider'],
549 $parserParameters['mapperWebsiteType'], $parserParameters['relatedContactWebsiteType']
6a488035 550 );
4a01628c 551 $parser->setUserJobID($this->getUserJobID());
6a488035 552
0d1d27fd 553 $parser->run(
bd0e7045 554 [],
c169525f 555 CRM_Import_Parser::MODE_PREVIEW
6a488035 556 );
52356383 557 return $parser;
6a488035 558 }
96025800 559
449fda1c 560 /**
259dd586 561 * Save the mapping field.
449fda1c 562 *
259dd586
EM
563 * @param int $mappingID
564 * @param int $columnNumber
565 * @param bool $isUpdate
449fda1c 566 *
259dd586
EM
567 * @throws \API_Exception
568 * @throws \CRM_Core_Exception
449fda1c 569 */
259dd586
EM
570 protected function saveMappingField(int $mappingID, int $columnNumber, bool $isUpdate = FALSE): void {
571 $fieldMapping = (array) $this->getSubmittedValue('mapper')[$columnNumber];
572 $mappedField = $this->getMappedField($fieldMapping, $mappingID, $columnNumber);
573 if ($isUpdate) {
574 MappingField::update(FALSE)
575 ->setValues($mappedField)
576 ->addWhere('column_number', '=', $columnNumber)
577 ->addWhere('mapping_id', '=', $mappingID)
578 ->execute();
449fda1c 579 }
580 else {
259dd586
EM
581 MappingField::create(FALSE)
582 ->setValues($mappedField)->execute();
449fda1c 583 }
259dd586
EM
584 }
585
586 /**
587 * Get the field mapped to the savable format.
588 *
589 * @param array $fieldMapping
590 * @param int $mappingID
591 * @param int $columnNumber
592 *
593 * @return array
0d46885c 594 * @throws \CRM_Core_Exception
259dd586
EM
595 */
596 protected function getMappedField(array $fieldMapping, int $mappingID, int $columnNumber): array {
0d46885c 597 return (new CRM_Contact_Import_Parser_Contact())->setContactType($this->getContactType())->getMappingFieldFromMapperInput($fieldMapping, $mappingID, $columnNumber);
449fda1c 598 }
599
971e67cf
EM
600 /**
601 * Did the user specify duplicates matching should not be attempted.
602 *
603 * @return bool
604 * @throws \CRM_Core_Exception
605 */
606 private function isIgnoreDuplicates(): bool {
607 return ((int) $this->getSubmittedValue('onDuplicate')) === CRM_Import_Parser::DUPLICATE_NOCHECK;
608 }
609
610 /**
611 * Did the user specify duplicates should be skipped and not imported.
612 *
613 * @return bool
614 *
615 * @throws \CRM_Core_Exception
616 */
617 private function isSkipDuplicates(): bool {
618 return ((int) $this->getSubmittedValue('onDuplicate')) === CRM_Import_Parser::DUPLICATE_SKIP;
619 }
620
09594ee8
EM
621 /**
622 * Get the fields to be highlighted in the UI.
623 *
624 * The highlighted fields are those used to match
625 * to an existing contact.
626 *
627 * @return array
628 *
629 * @throws \CRM_Core_Exception
630 */
631 private function getHighlightedFields(): array {
632 $entityFields = [
633 'Individual' => ['first_name', 'last_name'],
634 'Organization' => ['organization_name'],
635 'Household' => ['household_name'],
636 ];
637 $highlightedFields = $entityFields[$this->getContactType()];
638 $highlightedFields[] = 'email';
639 $highlightedFields[] = 'external_identifier';
640 if (!$this->isSkipDuplicates()) {
641 $highlightedFields[] = 'id';
642 }
643 $customFields = CRM_Core_BAO_CustomField::getFields($this->getContactType());
644 foreach ($customFields as $key => $attr) {
645 if (!empty($attr['is_required'])) {
646 $highlightedFields[] = "custom_$key";
647 }
648 }
649 return $highlightedFields;
650 }
651
79d21b5b
EM
652 /**
653 * Get an array of fields with TRUE or FALSE to reflect need for location type.
654 *
655 * e.g ['first_name' => FALSE, 'email' => TRUE, 'street_address' => TRUE']
656 *
657 * @return bool
658 */
659 private function isLocationTypeRequired($name): bool {
660 if (!isset(Civi::$statics[__CLASS__]['location_fields'])) {
661 Civi::$statics[__CLASS__]['location_fields'] = (new CRM_Contact_Import_Parser_Contact())->setUserJobID($this->getUserJobID())->getSelectTypes();
662 }
663 return (bool) (Civi::$statics[__CLASS__]['location_fields'][$name] ?? FALSE);
664 }
665
6a488035 666}