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