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