Ian province abbreviation patch - issue 724
[civicrm-core.git] / CRM / Contact / Import / Form / MapField.php
... / ...
CommitLineData
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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 +--------------------------------------------------------------------+
26 */
27
28/**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2015
32 */
33
34/**
35 * This class gets the name of the file to upload.
36 */
37class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {
38
39
40 /**
41 * An array of all contact fields with
42 * formatted custom field names.
43 *
44 * @var array
45 */
46 protected $_formattedFieldNames;
47
48 /**
49 * On duplicate.
50 *
51 * @var int
52 */
53 public $_onDuplicate;
54
55 protected $_dedupeFields;
56
57 protected static $customFields;
58
59 /**
60 * Attempt to match header labels with our mapper fields.
61 * FIXME: This is essentially the same function as parent::defaultFromHeader
62 *
63 * @param $columnName name of column header
64 * @param $patterns pattern to match for the column
65 *
66 * @return string
67 */
68 public function defaultFromColumnName($columnName, &$patterns) {
69
70 if (!preg_match('/^[a-z0-9 ]$/i', $columnName)) {
71 if ($columnKey = array_search($columnName, $this->_mapperFields)) {
72 $this->_fieldUsed[$columnKey] = TRUE;
73 return $columnKey;
74 }
75 }
76
77 foreach ($patterns as $key => $re) {
78 // Skip empty key/patterns
79 if (!$key || !$re || strlen("$re") < 5) {
80 continue;
81 }
82
83 if (preg_match($re, $columnName)) {
84 $this->_fieldUsed[$key] = TRUE;
85 return $key;
86 }
87 }
88 return '';
89 }
90
91 /**
92 * Set variables up before form is built.
93 */
94 public function preProcess() {
95 $dataSource = $this->get('dataSource');
96 $skipColumnHeader = $this->get('skipColumnHeader');
97 $this->_mapperFields = $this->get('fields');
98 $this->_importTableName = $this->get('importTableName');
99 $this->_onDuplicate = $this->get('onDuplicate');
100 $highlightedFields = array();
101 $highlightedFields[] = 'email';
102 $highlightedFields[] = 'external_identifier';
103 //format custom field names, CRM-2676
104 switch ($this->get('contactType')) {
105 case CRM_Import_Parser::CONTACT_INDIVIDUAL:
106 $contactType = 'Individual';
107 $highlightedFields[] = 'first_name';
108 $highlightedFields[] = 'last_name';
109 break;
110
111 case CRM_Import_Parser::CONTACT_HOUSEHOLD:
112 $contactType = 'Household';
113 $highlightedFields[] = 'household_name';
114 break;
115
116 case CRM_Import_Parser::CONTACT_ORGANIZATION:
117 $contactType = 'Organization';
118 $highlightedFields[] = 'organization_name';
119 break;
120 }
121 $this->_contactType = $contactType;
122 if ($this->_onDuplicate == CRM_Import_Parser::DUPLICATE_SKIP) {
123 unset($this->_mapperFields['id']);
124 }
125 else {
126 $highlightedFields[] = 'id';
127 }
128
129 if ($this->_onDuplicate != CRM_Import_Parser::DUPLICATE_NOCHECK) {
130 //Mark Dedupe Rule Fields as required, since it's used in matching contact
131 foreach (array(
132 'Individual',
133 'Household',
134 'Organization',
135 ) as $cType) {
136 $ruleParams = array(
137 'contact_type' => $cType,
138 'used' => 'Unsupervised',
139 );
140 $this->_dedupeFields[$cType] = CRM_Dedupe_BAO_Rule::dedupeRuleFields($ruleParams);
141 }
142
143 //Modify mapper fields title if fields are present in dedupe rule
144 if (is_array($this->_dedupeFields[$contactType])) {
145 foreach ($this->_dedupeFields[$contactType] as $val) {
146 if ($valTitle = CRM_Utils_Array::value($val, $this->_mapperFields)) {
147 $this->_mapperFields[$val] = $valTitle . ' (match to contact)';
148 }
149 }
150 }
151 }
152 // retrieve and highlight required custom fields
153 $formattedFieldNames = $this->formatCustomFieldName($this->_mapperFields);
154 self::$customFields = CRM_Core_BAO_CustomField::getFields($this->_contactType);
155 foreach (self::$customFields as $key => $attr) {
156 if (!empty($attr['is_required'])) {
157 $highlightedFields[] = "custom_$key";
158 }
159 }
160 $this->assign('highlightedFields', $highlightedFields);
161 $this->_formattedFieldNames[$contactType] = $this->_mapperFields = array_merge($this->_mapperFields, $formattedFieldNames);
162
163 $columnNames = array();
164 //get original col headers from csv if present.
165 if ($dataSource == 'CRM_Import_DataSource_CSV' && $skipColumnHeader) {
166 $columnNames = $this->get('originalColHeader');
167 }
168 else {
169 // get the field names from the temp. DB table
170 $dao = new CRM_Core_DAO();
171 $db = $dao->getDatabaseConnection();
172
173 $columnsQuery = "SHOW FIELDS FROM $this->_importTableName
174 WHERE Field NOT LIKE '\_%'";
175 $columnsResult = $db->query($columnsQuery);
176 while ($row = $columnsResult->fetchRow(DB_FETCHMODE_ASSOC)) {
177 $columnNames[] = $row['Field'];
178 }
179 }
180
181 $showColNames = TRUE;
182 if ($dataSource == 'CRM_Import_DataSource_CSV' && !$skipColumnHeader) {
183 $showColNames = FALSE;
184 }
185 $this->assign('showColNames', $showColNames);
186
187 $this->_columnCount = count($columnNames);
188 $this->_columnNames = $columnNames;
189 $this->assign('columnNames', $columnNames);
190 //$this->_columnCount = $this->get( 'columnCount' );
191 $this->assign('columnCount', $this->_columnCount);
192 $this->_dataValues = $this->get('dataValues');
193 $this->assign('dataValues', $this->_dataValues);
194 $this->assign('rowDisplayCount', 2);
195 }
196
197 /**
198 * Build the form object.
199 */
200 public function buildQuickForm() {
201 //to save the current mappings
202 if (!$this->get('savedMapping')) {
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'));
207 }
208 else {
209 $savedMapping = $this->get('savedMapping');
210
211 list($mappingName, $mappingContactType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $mappingRelation, $mappingOperator, $mappingValue, $mappingWebsiteType) = CRM_Core_BAO_Mapping::getMappingFields($savedMapping);
212
213 //get loaded Mapping Fields
214 $mappingName = CRM_Utils_Array::value(1, $mappingName);
215 $mappingContactType = CRM_Utils_Array::value(1, $mappingContactType);
216 $mappingLocation = CRM_Utils_Array::value(1, $mappingLocation);
217 $mappingPhoneType = CRM_Utils_Array::value(1, $mappingPhoneType);
218 $mappingImProvider = CRM_Utils_Array::value(1, $mappingImProvider);
219 $mappingRelation = CRM_Utils_Array::value(1, $mappingRelation);
220 $mappingWebsiteType = CRM_Utils_Array::value(1, $mappingWebsiteType);
221
222 $this->assign('loadedMapping', $savedMapping);
223 $this->set('loadedMapping', $savedMapping);
224
225 $params = array('id' => $savedMapping);
226 $temp = array();
227 $mappingDetails = CRM_Core_BAO_Mapping::retrieve($params, $temp);
228
229 $this->assign('savedName', $mappingDetails->name);
230
231 $this->add('hidden', 'mappingId', $savedMapping);
232
233 $this->addElement('checkbox', 'updateMapping', ts('Update this field mapping'), NULL);
234 $saveDetailsName = ts('Save as a new field mapping');
235 $this->add('text', 'saveMappingName', ts('Name'));
236 $this->add('text', 'saveMappingDesc', ts('Description'));
237 }
238
239 $this->addElement('checkbox', 'saveMapping', $saveDetailsName, NULL, array('onclick' => "showSaveDetails(this)"));
240
241 $this->addFormRule(array('CRM_Contact_Import_Form_MapField', 'formRule'));
242
243 //-------- end of saved mapping stuff ---------
244
245 $defaults = array();
246 $mapperKeys = array_keys($this->_mapperFields);
247 $hasColumnNames = !empty($this->_columnNames);
248 $columnPatterns = $this->get('columnPatterns');
249 $dataPatterns = $this->get('dataPatterns');
250 $hasLocationTypes = $this->get('fieldTypes');
251
252 $this->_location_types = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
253
254 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
255
256 // Pass default location to js
257 if ($defaultLocationType) {
258 $this->assign('defaultLocationType', $defaultLocationType->id);
259 $this->assign('defaultLocationTypeLabel', $this->_location_types[$defaultLocationType->id]);
260 }
261
262 /* Initialize all field usages to false */
263 foreach ($mapperKeys as $key) {
264 $this->_fieldUsed[$key] = FALSE;
265 }
266
267 $sel1 = $this->_mapperFields;
268 $sel2[''] = NULL;
269
270 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
271 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
272 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
273
274 foreach ($this->_location_types as $key => $value) {
275 $sel3['phone'][$key] = &$phoneTypes;
276 //build array for IM service provider type for contact
277 $sel3['im'][$key] = &$imProviders;
278 }
279
280 $sel4 = NULL;
281
282 // store and cache all relationship types
283 $contactRelation = new CRM_Contact_DAO_RelationshipType();
284 $contactRelation->find();
285 while ($contactRelation->fetch()) {
286 $contactRelationCache[$contactRelation->id] = array();
287 $contactRelationCache[$contactRelation->id]['contact_type_a'] = $contactRelation->contact_type_a;
288 $contactRelationCache[$contactRelation->id]['contact_sub_type_a'] = $contactRelation->contact_sub_type_a;
289 $contactRelationCache[$contactRelation->id]['contact_type_b'] = $contactRelation->contact_type_b;
290 $contactRelationCache[$contactRelation->id]['contact_sub_type_b'] = $contactRelation->contact_sub_type_b;
291 }
292 $highlightedFields = $highlightedRelFields = array();
293
294 $highlightedFields['email'] = 'All';
295 $highlightedFields['external_identifier'] = 'All';
296 $highlightedFields['first_name'] = 'Individual';
297 $highlightedFields['last_name'] = 'Individual';
298 $highlightedFields['household_name'] = 'Household';
299 $highlightedFields['organization_name'] = 'Organization';
300
301 foreach ($mapperKeys as $key) {
302 // check if there is a _a_b or _b_a in the key
303 if (strpos($key, '_a_b') || strpos($key, '_b_a')) {
304 list($id, $first, $second) = explode('_', $key);
305 }
306 else {
307 $id = $first = $second = NULL;
308 }
309 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
310 $cType = $contactRelationCache[$id]["contact_type_{$second}"];
311
312 //CRM-5125 for contact subtype specific relationshiptypes
313 $cSubType = NULL;
314 if (!empty($contactRelationCache[$id]["contact_sub_type_{$second}"])) {
315 $cSubType = $contactRelationCache[$id]["contact_sub_type_{$second}"];
316 }
317
318 if (!$cType) {
319 $cType = 'All';
320 }
321
322 $relatedFields = array();
323 $relatedFields = CRM_Contact_BAO_Contact::importableFields($cType);
324 unset($relatedFields['']);
325 $values = array();
326 foreach ($relatedFields as $name => $field) {
327 $values[$name] = $field['title'];
328 if (isset($hasLocationTypes[$name])) {
329 $sel3[$key][$name] = $this->_location_types;
330 }
331 elseif ($name == 'url') {
332 $sel3[$key][$name] = $websiteTypes;
333 }
334 else {
335 $sel3[$name] = NULL;
336 }
337 }
338
339 //fix to append custom group name to field name, CRM-2676
340 if (empty($this->_formattedFieldNames[$cType]) || $cType == $this->_contactType) {
341 $this->_formattedFieldNames[$cType] = $this->formatCustomFieldName($values);
342 }
343
344 $this->_formattedFieldNames[$cType] = array_merge($values, $this->_formattedFieldNames[$cType]);
345
346 //Modified the Relationship fields if the fields are
347 //present in dedupe rule
348 if ($this->_onDuplicate != CRM_Import_Parser::DUPLICATE_NOCHECK && !empty($this->_dedupeFields[$cType]) &&
349 is_array($this->_dedupeFields[$cType])
350 ) {
351 static $cTypeArray = array();
352 if ($cType != $this->_contactType && !in_array($cType, $cTypeArray)) {
353 foreach ($this->_dedupeFields[$cType] as $val) {
354 if ($valTitle = CRM_Utils_Array::value($val, $this->_formattedFieldNames[$cType])) {
355 $this->_formattedFieldNames[$cType][$val] = $valTitle . ' (match to contact)';
356 }
357 }
358 $cTypeArray[] = $cType;
359 }
360 }
361
362 foreach ($highlightedFields as $k => $v) {
363 if ($v == $cType || $v == 'All') {
364 $highlightedRelFields[$key][] = $k;
365 }
366 }
367 $this->assign('highlightedRelFields', $highlightedRelFields);
368 $sel2[$key] = $this->_formattedFieldNames[$cType];
369
370 if (!empty($cSubType)) {
371 //custom fields for sub type
372 $subTypeFields = CRM_Core_BAO_CustomField::getFieldsForImport($cSubType);
373
374 if (!empty($subTypeFields)) {
375 $subType = NULL;
376 foreach ($subTypeFields as $customSubTypeField => $details) {
377 $subType[$customSubTypeField] = $details['title'];
378 $sel2[$key] = array_merge($sel2[$key], $this->formatCustomFieldName($subType));
379 }
380 }
381 }
382
383 foreach ($this->_location_types as $k => $value) {
384 $sel4[$key]['phone'][$k] = &$phoneTypes;
385 //build array of IM service provider for related contact
386 $sel4[$key]['im'][$k] = &$imProviders;
387 }
388 }
389 else {
390 $options = NULL;
391 if (!empty($hasLocationTypes[$key])) {
392 $options = $this->_location_types;
393 }
394 elseif ($key == 'url') {
395 $options = $websiteTypes;
396 }
397 $sel2[$key] = $options;
398 }
399 }
400
401 $js = "<script type='text/javascript'>\n";
402 $formName = 'document.forms.' . $this->_name;
403 //used to warn for mismatch column count or mismatch mapping
404 $warning = 0;
405 for ($i = 0; $i < $this->_columnCount; $i++) {
406 $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', array(1 => $i)), NULL);
407 $jsSet = FALSE;
408 if ($this->get('savedMapping')) {
409 if (isset($mappingName[$i])) {
410 if ($mappingName[$i] != ts('- do not import -')) {
411
412 if (isset($mappingRelation[$i])) {
413 // relationship mapping
414 switch ($this->get('contactType')) {
415 case CRM_Import_Parser::CONTACT_INDIVIDUAL:
416 $contactType = 'Individual';
417 break;
418
419 case CRM_Import_Parser::CONTACT_HOUSEHOLD:
420 $contactType = 'Household';
421 break;
422
423 case CRM_Import_Parser::CONTACT_ORGANIZATION:
424 $contactType = 'Organization';
425 }
426 //CRM-5125
427 $contactSubType = NULL;
428 if ($this->get('contactSubType')) {
429 $contactSubType = $this->get('contactSubType');
430 }
431
432 $relations = CRM_Contact_BAO_Relationship::getContactRelationshipType(NULL, NULL, NULL, $contactType,
433 FALSE, 'label', TRUE, $contactSubType
434 );
435
436 foreach ($relations as $key => $var) {
437 if ($key == $mappingRelation[$i]) {
438 $relation = $key;
439 break;
440 }
441 }
442
443 $contactDetails = strtolower(str_replace(" ", "_", $mappingName[$i]));
444 $websiteTypeId = isset($mappingWebsiteType[$i]) ? $mappingWebsiteType[$i] : NULL;
445 $locationId = isset($mappingLocation[$i]) ? $mappingLocation[$i] : 0;
446 $phoneType = isset($mappingPhoneType[$i]) ? $mappingPhoneType[$i] : NULL;
447 //get provider id from saved mappings
448 $imProvider = isset($mappingImProvider[$i]) ? $mappingImProvider[$i] : NULL;
449
450 if ($websiteTypeId) {
451 $defaults["mapper[$i]"] = array($relation, $contactDetails, $websiteTypeId);
452 if (!$websiteTypeId) {
453 $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
454 }
455 }
456 else {
457 // default for IM/phone when mapping with relation is true
458 $typeId = NULL;
459 if (isset($phoneType)) {
460 $typeId = $phoneType;
461 }
462 elseif (isset($imProvider)) {
463 $typeId = $imProvider;
464 }
465 $defaults["mapper[$i]"] = array($relation, $contactDetails, $locationId, $typeId);
466 if (!$locationId) {
467 $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
468 }
469 }
470 // fix for edge cases, CRM-4954
471 if ($contactDetails == 'image_url') {
472 $contactDetails = str_replace('url', 'URL', $contactDetails);
473 }
474
475 if (!$contactDetails) {
476 $js .= "{$formName}['mapper[$i][1]'].style.display = 'none';\n";
477 }
478
479 if ((!$phoneType) && (!$imProvider)) {
480 $js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
481 }
482 //$js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
483 $jsSet = TRUE;
484 }
485 else {
486 $mappingHeader = array_keys($this->_mapperFields, $mappingName[$i]);
487 $websiteTypeId = isset($mappingWebsiteType[$i]) ? $mappingWebsiteType[$i] : NULL;
488 $locationId = isset($mappingLocation[$i]) ? $mappingLocation[$i] : 0;
489 $phoneType = isset($mappingPhoneType[$i]) ? $mappingPhoneType[$i] : NULL;
490 // get IM service provider id
491 $imProvider = isset($mappingImProvider[$i]) ? $mappingImProvider[$i] : NULL;
492
493 if ($websiteTypeId) {
494 if (!$websiteTypeId) {
495 $js .= "{$formName}['mapper[$i][1]'].style.display = 'none';\n";
496 }
497 $defaults["mapper[$i]"] = array($mappingHeader[0], $websiteTypeId);
498 }
499 else {
500 if (!$locationId) {
501 $js .= "{$formName}['mapper[$i][1]'].style.display = 'none';\n";
502 }
503 //default for IM/phone without related contact
504 $typeId = NULL;
505 if (isset($phoneType)) {
506 $typeId = $phoneType;
507 }
508 elseif (isset($imProvider)) {
509 $typeId = $imProvider;
510 }
511 $defaults["mapper[$i]"] = array($mappingHeader[0], $locationId, $typeId);
512 }
513
514 if ((!$phoneType) && (!$imProvider)) {
515 $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
516 }
517
518 $js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
519
520 $jsSet = TRUE;
521 }
522 }
523 else {
524 $defaults["mapper[$i]"] = array();
525 }
526 if (!$jsSet) {
527 for ($k = 1; $k < 4; $k++) {
528 $js .= "{$formName}['mapper[$i][$k]'].style.display = 'none';\n";
529 }
530 }
531 }
532 else {
533 // this load section to help mapping if we ran out of saved columns when doing Load Mapping
534 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
535
536 if ($hasColumnNames) {
537 $defaults["mapper[$i]"] = array($this->defaultFromColumnName($this->_columnNames[$i], $columnPatterns));
538 }
539 else {
540 $defaults["mapper[$i]"] = array($this->defaultFromData($dataPatterns, $i));
541 }
542 }
543 //end of load mapping
544 }
545 else {
546 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
547 if ($hasColumnNames) {
548 // do array search first to see if has mapped key
549 $columnKey = '';
550 $columnKey = array_search($this->_columnNames[$i], $this->_mapperFields);
551 if (isset($this->_fieldUsed[$columnKey])) {
552 $defaults["mapper[$i]"] = $columnKey;
553 $this->_fieldUsed[$key] = TRUE;
554 }
555 else {
556 // Infer the default from the column names if we have them
557 $defaults["mapper[$i]"] = array(
558 $this->defaultFromColumnName($this->_columnNames[$i],
559 $columnPatterns
560 ),
561 0,
562 );
563 }
564 }
565 else {
566 // Otherwise guess the default from the form of the data
567 $defaults["mapper[$i]"] = array(
568 $this->defaultFromData($dataPatterns, $i),
569 // $defaultLocationType->id
570 0,
571 );
572 }
573 }
574 $sel->setOptions(array($sel1, $sel2, $sel3, $sel4));
575 }
576
577 $js .= "</script>\n";
578 $this->assign('initHideBoxes', $js);
579
580 //set warning if mismatch in more than
581 if (isset($mappingName) &&
582 ($this->_columnCount != count($mappingName))
583 ) {
584 $warning++;
585 }
586
587 if ($warning != 0 && $this->get('savedMapping')) {
588 $session = CRM_Core_Session::singleton();
589 $session->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.'));
590 }
591 else {
592 $session = CRM_Core_Session::singleton();
593 $session->setStatus(NULL);
594 }
595
596 $this->setDefaults($defaults);
597
598 $this->addButtons(array(
599 array(
600 'type' => 'back',
601 'name' => ts('Previous'),
602 ),
603 array(
604 'type' => 'next',
605 'name' => ts('Continue'),
606 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
607 'isDefault' => TRUE,
608 ),
609 array(
610 'type' => 'cancel',
611 'name' => ts('Cancel'),
612 ),
613 )
614 );
615 }
616
617 /**
618 * Global validation rules for the form.
619 *
620 * @param array $fields
621 * Posted values of the form.
622 *
623 * @return array
624 * list of errors to be posted back to the form
625 */
626 public static function formRule($fields) {
627 $errors = array();
628 if (!empty($fields['saveMapping'])) {
629 $nameField = CRM_Utils_Array::value('saveMappingName', $fields);
630 if (empty($nameField)) {
631 $errors['saveMappingName'] = ts('Name is required to save Import Mapping');
632 }
633 else {
634 $mappingTypeId = CRM_Core_OptionGroup::getValue('mapping_type', 'Import Contact', 'name');
635 if (CRM_Core_BAO_Mapping::checkMapping($nameField, $mappingTypeId)) {
636 $errors['saveMappingName'] = ts('Duplicate Import Mapping Name');
637 }
638 }
639 }
640 $template = CRM_Core_Smarty::singleton();
641 if (!empty($fields['saveMapping'])) {
642 $template->assign('isCheked', TRUE);
643 }
644
645 if (!empty($errors)) {
646 $_flag = 1;
647 $assignError = new CRM_Core_Page();
648 $assignError->assign('mappingDetailsError', $_flag);
649 return $errors;
650 }
651 else {
652 return TRUE;
653 }
654 }
655
656 /**
657 * Process the mapped fields and map it into the uploaded file.
658 */
659 public function postProcess() {
660 $params = $this->controller->exportValues('MapField');
661
662 //reload the mapfield if load mapping is pressed
663 if (!empty($params['savedMapping'])) {
664 $this->set('savedMapping', $params['savedMapping']);
665 $this->controller->resetPage($this->_name);
666 return;
667 }
668
669 $mapper = array();
670 $mapperKeys = array();
671 $mapperKeys = $this->controller->exportValue($this->_name, 'mapper');
672 $mapperKeysMain = array();
673
674 $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
675 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
676 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
677 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
678
679 //these mapper params need to set key as array and val as null.
680 $mapperParams = array(
681 'related' => 'relatedVal',
682 'locations' => 'locationsVal',
683 'mapperLocType' => 'mapperLocTypeVal',
684 'mapperPhoneType' => 'mapperPhoneTypeVal',
685 'mapperImProvider' => 'mapperImProviderVal',
686 'mapperWebsiteType' => 'mapperWebsiteTypeVal',
687 'relatedContactType' => 'relatedContactTypeVal',
688 'relatedContactDetails' => 'relatedContactDetailsVal',
689 'relatedContactLocType' => 'relatedContactLocTypeVal',
690 'relatedContactPhoneType' => 'relatedContactPhoneTypeVal',
691 'relatedContactImProvider' => 'relatedContactImProviderVal',
692 'relatedContactWebsiteType' => 'relatedContactWebsiteTypeVal',
693 );
694
695 //set respective mapper params to array.
696 foreach (array_keys($mapperParams) as $mapperParam) {
697 $$mapperParam = array();
698 }
699
700 for ($i = 0; $i < $this->_columnCount; $i++) {
701 //set respective mapper value to null
702 foreach (array_values($mapperParams) as $mapperParam) {
703 $$mapperParam = NULL;
704 }
705
706 $fldName = CRM_Utils_Array::value(0, $mapperKeys[$i]);
707 $selOne = CRM_Utils_Array::value(1, $mapperKeys[$i]);
708 $selTwo = CRM_Utils_Array::value(2, $mapperKeys[$i]);
709 $selThree = CRM_Utils_Array::value(3, $mapperKeys[$i]);
710 $mapper[$i] = $this->_mapperFields[$mapperKeys[$i][0]];
711 $mapperKeysMain[$i] = $fldName;
712
713 //need to differentiate non location elements.
714 if ($selOne && is_numeric($selOne)) {
715 if ($fldName == 'url') {
716 $mapperWebsiteTypeVal = $websiteTypes[$selOne];
717 }
718 else {
719 $locationsVal = $locationTypes[$selOne];
720 $mapperLocTypeVal = $selOne;
721 if ($selTwo && is_numeric($selTwo)) {
722 if ($fldName == 'phone') {
723 $mapperPhoneTypeVal = $phoneTypes[$selTwo];
724 }
725 elseif ($fldName == 'im') {
726 $mapperImProviderVal = $imProviders[$selTwo];
727 }
728 }
729 }
730 }
731
732 //relationship contact mapper info.
733 list($id, $first, $second) = CRM_Utils_System::explode('_', $fldName, 3);
734 if (($first == 'a' && $second == 'b') ||
735 ($first == 'b' && $second == 'a')
736 ) {
737 $relatedVal = $this->_mapperFields[$fldName];
738 if ($selOne) {
739 if ($selOne == 'url') {
740 $relatedContactWebsiteTypeVal = $websiteTypes[$selTwo];
741 }
742 else {
743 $relatedContactLocTypeVal = CRM_Utils_Array::value($selTwo, $locationTypes);
744 if ($selThree) {
745 if ($selOne == 'phone') {
746 $relatedContactPhoneTypeVal = $phoneTypes[$selThree];
747 }
748 elseif ($selOne == 'im') {
749 $relatedContactImProviderVal = $imProviders[$selThree];
750 }
751 }
752 }
753
754 //get the related contact type.
755 $relationType = new CRM_Contact_DAO_RelationshipType();
756 $relationType->id = $id;
757 $relationType->find(TRUE);
758 $relatedContactTypeVal = $relationType->{"contact_type_$second"};
759 $relatedContactDetailsVal = $this->_formattedFieldNames[$relatedContactTypeVal][$selOne];
760 }
761 }
762
763 //set the respective mapper param array values.
764 foreach ($mapperParams as $mapperParamKey => $mapperParamVal) {
765 ${$mapperParamKey}[$i] = $$mapperParamVal;
766 }
767 }
768
769 $this->set('columnNames', $this->_columnNames);
770
771 //set main contact properties.
772 $properties = array(
773 'ims' => 'mapperImProvider',
774 'mapper' => 'mapper',
775 'phones' => 'mapperPhoneType',
776 'websites' => 'mapperWebsiteType',
777 'locations' => 'locations',
778 );
779 foreach ($properties as $propertyName => $propertyVal) {
780 $this->set($propertyName, $$propertyVal);
781 }
782
783 //set related contact propeties.
784 $relProperties = array(
785 'related',
786 'relatedContactType',
787 'relatedContactDetails',
788 'relatedContactLocType',
789 'relatedContactPhoneType',
790 'relatedContactImProvider',
791 'relatedContactWebsiteType',
792 );
793 foreach ($relProperties as $relProperty) {
794 $this->set($relProperty, $$relProperty);
795 }
796
797 // store mapping Id to display it in the preview page
798 $this->set('loadMappingId', CRM_Utils_Array::value('mappingId', $params));
799
800 //Updating Mapping Records
801 if (!empty($params['updateMapping'])) {
802
803 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
804
805 $mappingFields = new CRM_Core_DAO_MappingField();
806 $mappingFields->mapping_id = $params['mappingId'];
807 $mappingFields->find();
808
809 $mappingFieldsId = array();
810 while ($mappingFields->fetch()) {
811 if ($mappingFields->id) {
812 $mappingFieldsId[$mappingFields->column_number] = $mappingFields->id;
813 }
814 }
815
816 for ($i = 0; $i < $this->_columnCount; $i++) {
817 $updateMappingFields = new CRM_Core_DAO_MappingField();
818 $updateMappingFields->id = CRM_Utils_Array::value($i, $mappingFieldsId);
819 $updateMappingFields->mapping_id = $params['mappingId'];
820 $updateMappingFields->column_number = $i;
821
822 $mapperKeyParts = explode('_', $mapperKeys[$i][0], 3);
823 $id = isset($mapperKeyParts[0]) ? $mapperKeyParts[0] : NULL;
824 $first = isset($mapperKeyParts[1]) ? $mapperKeyParts[1] : NULL;
825 $second = isset($mapperKeyParts[2]) ? $mapperKeyParts[2] : NULL;
826 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
827 $updateMappingFields->relationship_type_id = $id;
828 $updateMappingFields->relationship_direction = "{$first}_{$second}";
829 $updateMappingFields->name = ucwords(str_replace("_", " ", $mapperKeys[$i][1]));
830 // get phoneType id and provider id separately
831 // before updating mappingFields of phone and IM for related contact, CRM-3140
832 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'url') {
833 $updateMappingFields->website_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
834 }
835 else {
836 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'phone') {
837 $updateMappingFields->phone_type_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
838 }
839 elseif (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'im') {
840 $updateMappingFields->im_provider_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
841 }
842 $updateMappingFields->location_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
843 }
844 }
845 else {
846 $updateMappingFields->name = $mapper[$i];
847 $updateMappingFields->relationship_type_id = 'NULL';
848 $updateMappingFields->relationship_type_direction = 'NULL';
849 // to store phoneType id and provider id separately
850 // before updating mappingFields for phone and IM, CRM-3140
851 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'url') {
852 $updateMappingFields->website_type_id = isset($mapperKeys[$i][1]) ? $mapperKeys[$i][1] : NULL;
853 }
854 else {
855 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'phone') {
856 $updateMappingFields->phone_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
857 }
858 elseif (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'im') {
859 $updateMappingFields->im_provider_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
860 }
861 $location = array_keys($locationTypes, $locations[$i]);
862 $updateMappingFields->location_type_id = (isset($location) && isset($location[0])) ? $location[0] : NULL;
863 }
864 }
865 $updateMappingFields->save();
866 }
867 }
868
869 //Saving Mapping Details and Records
870 if (!empty($params['saveMapping'])) {
871 $mappingParams = array(
872 'name' => $params['saveMappingName'],
873 'description' => $params['saveMappingDesc'],
874 'mapping_type_id' => CRM_Core_OptionGroup::getValue('mapping_type',
875 'Import Contact',
876 'name'
877 ),
878 );
879
880 $saveMapping = CRM_Core_BAO_Mapping::add($mappingParams);
881
882 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
883 $contactType = $this->get('contactType');
884 switch ($contactType) {
885 case CRM_Import_Parser::CONTACT_INDIVIDUAL:
886 $cType = 'Individual';
887 break;
888
889 case CRM_Import_Parser::CONTACT_HOUSEHOLD:
890 $cType = 'Household';
891 break;
892
893 case CRM_Import_Parser::CONTACT_ORGANIZATION:
894 $cType = 'Organization';
895 }
896
897 for ($i = 0; $i < $this->_columnCount; $i++) {
898 $saveMappingFields = new CRM_Core_DAO_MappingField();
899 $saveMappingFields->mapping_id = $saveMapping->id;
900 $saveMappingFields->contact_type = $cType;
901 $saveMappingFields->column_number = $i;
902
903 $mapperKeyParts = explode('_', $mapperKeys[$i][0], 3);
904 $id = isset($mapperKeyParts[0]) ? $mapperKeyParts[0] : NULL;
905 $first = isset($mapperKeyParts[1]) ? $mapperKeyParts[1] : NULL;
906 $second = isset($mapperKeyParts[2]) ? $mapperKeyParts[2] : NULL;
907 if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
908 $saveMappingFields->name = ucwords(str_replace("_", " ", $mapperKeys[$i][1]));
909 $saveMappingFields->relationship_type_id = $id;
910 $saveMappingFields->relationship_direction = "{$first}_{$second}";
911 // to get phoneType id and provider id separately
912 // before saving mappingFields of phone and IM for related contact, CRM-3140
913 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'url') {
914 $saveMappingFields->website_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
915 }
916 else {
917 if (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'phone') {
918 $saveMappingFields->phone_type_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
919 }
920 elseif (CRM_Utils_Array::value('1', $mapperKeys[$i]) == 'im') {
921 $saveMappingFields->im_provider_id = isset($mapperKeys[$i][3]) ? $mapperKeys[$i][3] : NULL;
922 }
923 $saveMappingFields->location_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
924 }
925 }
926 else {
927 $saveMappingFields->name = $mapper[$i];
928 $location_id = array_keys($locationTypes, $locations[$i]);
929 // to get phoneType id and provider id separately
930 // before saving mappingFields of phone and IM, CRM-3140
931 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'url') {
932 $saveMappingFields->website_type_id = isset($mapperKeys[$i][1]) ? $mapperKeys[$i][1] : NULL;
933 }
934 else {
935 if (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'phone') {
936 $saveMappingFields->phone_type_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
937 }
938 elseif (CRM_Utils_Array::value('0', $mapperKeys[$i]) == 'im') {
939 $saveMappingFields->im_provider_id = isset($mapperKeys[$i][2]) ? $mapperKeys[$i][2] : NULL;
940 }
941 $saveMappingFields->location_type_id = isset($location_id[0]) ? $location_id[0] : NULL;
942 }
943 $saveMappingFields->relationship_type_id = NULL;
944 }
945 $saveMappingFields->save();
946 }
947 $this->set('savedMapping', $saveMappingFields->mapping_id);
948 }
949
950 $parser = new CRM_Contact_Import_Parser_Contact($mapperKeysMain, $mapperLocType, $mapperPhoneType,
951 $mapperImProvider, $related, $relatedContactType,
952 $relatedContactDetails, $relatedContactLocType,
953 $relatedContactPhoneType, $relatedContactImProvider,
954 $mapperWebsiteType, $relatedContactWebsiteType
955 );
956
957 $primaryKeyName = $this->get('primaryKeyName');
958 $statusFieldName = $this->get('statusFieldName');
959 $parser->run($this->_importTableName,
960 $mapper,
961 CRM_Import_Parser::MODE_PREVIEW,
962 $this->get('contactType'),
963 $primaryKeyName,
964 $statusFieldName,
965 $this->_onDuplicate,
966 NULL, NULL, FALSE,
967 CRM_Contact_Import_Parser::DEFAULT_TIMEOUT,
968 $this->get('contactSubType'),
969 $this->get('dedupe')
970 );
971
972 // add all the necessary variables to the form
973 $parser->set($this);
974 }
975
976 /**
977 * Format custom field name.
978 *
979 * Combine group and field name to avoid conflict.
980 *
981 * @param array $fields
982 *
983 * @return array
984 */
985 public function formatCustomFieldName(&$fields) {
986 //CRM-2676, replacing the conflict for same custom field name from different custom group.
987 $fieldIds = $formattedFieldNames = array();
988 foreach ($fields as $key => $value) {
989 if ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($key)) {
990 $fieldIds[] = $customFieldId;
991 }
992 }
993
994 if (!empty($fieldIds) && is_array($fieldIds)) {
995 $groupTitles = CRM_Core_BAO_CustomGroup::getGroupTitles($fieldIds);
996
997 if (!empty($groupTitles)) {
998 foreach ($groupTitles as $fId => $values) {
999 $key = "custom_{$fId}";
1000 $groupTitle = $values['groupTitle'];
1001 $formattedFieldNames[$key] = $fields[$key] . ' :: ' . $groupTitle;
1002 }
1003 }
1004 }
1005
1006 return $formattedFieldNames;
1007 }
1008
1009}