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