Merge pull request #14432 from civicrm/5.14
[civicrm-core.git] / tests / phpunit / CRM / Contact / Import / Parser / ContactTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 * @file
30 * File for the CRM_Contact_Imports_Parser_ContactTest class.
31 */
32
33 /**
34 * Test contact import parser.
35 *
36 * @package CiviCRM
37 * @group headless
38 */
39 class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
40 protected $_tablesToTruncate = ['civicrm_address', 'civicrm_phone', 'civicrm_email'];
41
42 /**
43 * Setup function.
44 */
45 public function setUp() {
46 parent::setUp();
47 }
48
49 /**
50 * Test that import parser will add contact with employee of relationship.
51 *
52 * @throws \Exception
53 */
54 public function testImportParserWtihEmployeeOfRelationship() {
55 $this->organizationCreate(array(
56 "organization_name" => "Agileware",
57 "legal_name" => "Agileware",
58 ));
59 $contactImportValues = array(
60 "first_name" => "Alok",
61 "last_name" => "Patel",
62 "Employee of" => "Agileware",
63 );
64
65 $fields = array_keys($contactImportValues);
66 $values = array_values($contactImportValues);
67 $parser = new CRM_Contact_Import_Parser_Contact($fields, []);
68 $parser->_contactType = 'Individual';
69 $parser->init();
70 $this->mapRelationshipFields($fields, $parser->getAllFields());
71
72 $parser = new CRM_Contact_Import_Parser_Contact($fields, [], [], [], array(
73 NULL,
74 NULL,
75 $fields[2],
76 ), array(
77 NULL,
78 NULL,
79 "Organization",
80 ), array(
81 NULL,
82 NULL,
83 "organization_name",
84 ), [], [], [], [], []);
85
86 $parser->_contactType = 'Individual';
87 $parser->_onDuplicate = CRM_Import_Parser::DUPLICATE_UPDATE;
88 $parser->init();
89
90 $this->assertEquals(CRM_Import_Parser::VALID, $parser->import(CRM_Import_Parser::DUPLICATE_UPDATE, $values), 'Return code from parser import was not as expected');
91 $this->callAPISuccess("Contact", "get", array(
92 "first_name" => "Alok",
93 "last_name" => "Patel",
94 "organization_name" => "Agileware",
95 ));
96 }
97
98 /**
99 * Test that import parser will not fail when same external_identifier found of deleted contact.
100 *
101 * @throws \Exception
102 */
103 public function testImportParserWtihDeletedContactExternalIdentifier() {
104 $contactId = $this->individualCreate(array(
105 "external_identifier" => "ext-1",
106 ));
107 CRM_Contact_BAO_Contact::deleteContact($contactId);
108 list($originalValues, $result) = $this->setUpBaseContact(array(
109 'external_identifier' => 'ext-1',
110 ));
111 $originalValues['nick_name'] = 'Old Bill';
112 $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
113 $originalValues['id'] = $result['id'];
114 $this->assertEquals('ext-1', $this->callAPISuccessGetValue('Contact', array('id' => $result['id'], 'return' => 'external_identifier')));
115 $this->callAPISuccessGetSingle('Contact', $originalValues);
116 }
117
118 /**
119 * Test import parser will update based on a rule match.
120 *
121 * In this case the contact has no external identifier.
122 *
123 * @throws \Exception
124 */
125 public function testImportParserWithUpdateWithoutExternalIdentifier() {
126 list($originalValues, $result) = $this->setUpBaseContact();
127 $originalValues['nick_name'] = 'Old Bill';
128 $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
129 $originalValues['id'] = $result['id'];
130 $this->assertEquals('Old Bill', $this->callAPISuccessGetValue('Contact', array('id' => $result['id'], 'return' => 'nick_name')));
131 $this->callAPISuccessGetSingle('Contact', $originalValues);
132 }
133
134 /**
135 * Test import parser will update contacts with an external identifier.
136 *
137 * This is the basic test where the identifier matches the import parameters.
138 *
139 * @throws \Exception
140 */
141 public function testImportParserWithUpdateWithExternalIdentifier() {
142 list($originalValues, $result) = $this->setUpBaseContact(array('external_identifier' => 'windows'));
143
144 $this->assertEquals($result['id'], CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', 'windows', 'id', 'external_identifier', TRUE));
145 $this->assertEquals('windows', $result['external_identifier']);
146
147 $originalValues['nick_name'] = 'Old Bill';
148 $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
149 $originalValues['id'] = $result['id'];
150
151 $this->assertEquals('Old Bill', $this->callAPISuccessGetValue('Contact', array('id' => $result['id'], 'return' => 'nick_name')));
152 $this->callAPISuccessGetSingle('Contact', $originalValues);
153 }
154
155 /**
156 * Test import parser will fallback to external identifier.
157 *
158 * In this case no primary match exists (e.g the details are not supplied) so it falls back on external identifier.
159 *
160 * CRM-17275
161 *
162 * @throws \Exception
163 */
164 public function testImportParserWithUpdateWithExternalIdentifierButNoPrimaryMatch() {
165 list($originalValues, $result) = $this->setUpBaseContact([
166 'external_identifier' => 'windows',
167 'email' => NULL,
168 ]);
169
170 $this->assertEquals('windows', $result['external_identifier']);
171
172 $originalValues['nick_name'] = 'Old Bill';
173 $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
174 $originalValues['id'] = $result['id'];
175
176 $this->assertEquals('Old Bill', $this->callAPISuccessGetValue('Contact', array('id' => $result['id'], 'return' => 'nick_name')));
177 $this->callAPISuccessGetSingle('Contact', $originalValues);
178 }
179
180 /**
181 * Test import parser will fallback to external identifier.
182 *
183 * In this case no primary match exists (e.g the details are not supplied) so it falls back on external identifier.
184 *
185 * CRM-17275
186 *
187 * @throws \Exception
188 */
189 public function testImportParserWithUpdateWithContactID() {
190 list($originalValues, $result) = $this->setUpBaseContact(array(
191 'external_identifier' => '',
192 'email' => NULL,
193 ));
194 $updateValues = ['id' => $result['id'], 'email' => 'bill@example.com'];
195 // This is some deep weirdness - this sets a flag for updatingBlankLocinfo - allowing input to be blanked
196 // (which IS a good thing but it's pretty weird & all to do with legacy profile stuff).
197 CRM_Core_Session::singleton()->set('authSrc', CRM_Core_Permission::AUTH_SRC_CHECKSUM);
198 $this->runImport($updateValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, [NULL, 1]);
199 $originalValues['id'] = $result['id'];
200 $this->callAPISuccessGetSingle('Email', ['contact_id' => $originalValues['id'], 'is_primary' => 1]);
201 $this->callAPISuccessGetSingle('Contact', $originalValues);
202 }
203
204 /**
205 * Test that the import parser adds the external identifier where none is set.
206 *
207 * @throws \Exception
208 */
209 public function testImportParserWithUpdateWithNoExternalIdentifier() {
210 list($originalValues, $result) = $this->setUpBaseContact();
211 $originalValues['nick_name'] = 'Old Bill';
212 $originalValues['external_identifier'] = 'windows';
213 $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
214 $originalValues['id'] = $result['id'];
215 $this->assertEquals('Old Bill', $this->callAPISuccessGetValue('Contact', array('id' => $result['id'], 'return' => 'nick_name')));
216 $this->callAPISuccessGetSingle('Contact', $originalValues);
217 }
218
219 /**
220 * Test that the import parser changes the external identifier when there is a dedupe match.
221 *
222 * @throws \Exception
223 */
224 public function testImportParserWithUpdateWithChangedExternalIdentifier() {
225 list($contactValues, $result) = $this->setUpBaseContact(array('external_identifier' => 'windows'));
226 $contact_id = $result['id'];
227 $contactValues['nick_name'] = 'Old Bill';
228 $contactValues['external_identifier'] = 'android';
229 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
230 $contactValues['id'] = $contact_id;
231 $this->assertEquals('Old Bill', $this->callAPISuccessGetValue('Contact', array('id' => $contact_id, 'return' => 'nick_name')));
232 $this->callAPISuccessGetSingle('Contact', $contactValues);
233 }
234
235 /**
236 * Test that the import parser adds the address to the right location.
237 *
238 * @throws \Exception
239 */
240 public function testImportBillingAddress() {
241 list($contactValues) = $this->setUpBaseContact();
242 $contactValues['nick_name'] = 'Old Bill';
243 $contactValues['external_identifier'] = 'android';
244 $contactValues['street_address'] = 'Big Mansion';
245 $contactValues['phone'] = '911';
246 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, array(0 => NULL, 1 => NULL, 2 => NULL, 3 => NULL, 4 => NULL, 5 => 2, 6 => 2));
247 $address = $this->callAPISuccessGetSingle('Address', array('street_address' => 'Big Mansion'));
248 $this->assertEquals(2, $address['location_type_id']);
249
250 $phone = $this->callAPISuccessGetSingle('Phone', array('phone' => '911'));
251 $this->assertEquals(2, $phone['location_type_id']);
252
253 $contact = $this->callAPISuccessGetSingle('Contact', $contactValues);
254 $this->callAPISuccess('Contact', 'delete', array('id' => $contact['id']));
255 }
256
257 /**
258 * Test that the import parser adds the address to the primary location.
259 *
260 * @throws \Exception
261 */
262 public function testImportPrimaryAddress() {
263 list($contactValues) = $this->setUpBaseContact();
264 $contactValues['nick_name'] = 'Old Bill';
265 $contactValues['external_identifier'] = 'android';
266 $contactValues['street_address'] = 'Big Mansion';
267 $contactValues['phone'] = 12334;
268 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, array(0 => NULL, 1 => NULL, 2 => 'Primary', 3 => NULL, 4 => NULL, 5 => 'Primary', 6 => 'Primary'));
269 $address = $this->callAPISuccessGetSingle('Address', array('street_address' => 'Big Mansion'));
270 $this->assertEquals(1, $address['location_type_id']);
271 $this->assertEquals(1, $address['is_primary']);
272
273 $phone = $this->callAPISuccessGetSingle('Phone', array('phone' => '12334'));
274 $this->assertEquals(1, $phone['location_type_id']);
275
276 $this->callAPISuccessGetSingle('Email', array('email' => 'bill.gates@microsoft.com'));
277
278 $contact = $this->callAPISuccessGetSingle('Contact', $contactValues);
279 $this->callAPISuccess('Contact', 'delete', array('id' => $contact['id']));
280 }
281
282 /**
283 * Test that address custom fields can be imported
284 * FIXME: Api4
285 */
286 public function testAddressWithCustomData() {
287 $ids = $this->entityCustomGroupWithSingleFieldCreate('Address', 'AddressTest.php');
288 list($contactValues) = $this->setUpBaseContact();
289 $contactValues['nick_name'] = 'Old Bill';
290 $contactValues['external_identifier'] = 'android';
291 $contactValues['street_address'] = 'Big Mansion';
292 $contactValues['custom_' . $ids['custom_field_id']] = 'Update';
293 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, array(0 => NULL, 1 => NULL, 2 => NULL, 3 => NULL, 4 => NULL, 5 => 'Primary', 6 => 'Primary'));
294 $address = $this->callAPISuccessGetSingle('Address', ['street_address' => 'Big Mansion', 'return' => 'custom_' . $ids['custom_field_id']]);
295 $this->assertEquals('Update', $address['custom_' . $ids['custom_field_id']]);
296 }
297
298 /**
299 * Test that the import parser adds the address to the primary location.
300 *
301 * @throws \Exception
302 */
303 public function testImportDeceased() {
304 list($contactValues) = $this->setUpBaseContact();
305 CRM_Core_Session::singleton()->set("dateTypes", 1);
306 $contactValues['birth_date'] = '1910-12-17';
307 $contactValues['deceased_date'] = '2010-12-17';
308 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
309 $contact = $this->callAPISuccessGetSingle('Contact', $contactValues);
310 $this->assertEquals('1910-12-17', $contact['birth_date']);
311 $this->assertEquals('2010-12-17', $contact['deceased_date']);
312 $this->assertEquals(1, $contact['is_deceased']);
313 $this->callAPISuccess('Contact', 'delete', array('id' => $contact['id']));
314 }
315
316 /**
317 * Test that the import parser adds the address to the primary location.
318 *
319 * @throws \Exception
320 */
321 public function testImportTwoAddressFirstPrimary() {
322 list($contactValues) = $this->setUpBaseContact();
323 $contactValues['nick_name'] = 'Old Bill';
324 $contactValues['external_identifier'] = 'android';
325 $contactValues['street_address'] = 'Big Mansion';
326 $contactValues['phone'] = 12334;
327 $fields = array_keys($contactValues);
328 $contactValues['street_address_2'] = 'Teeny Mansion';
329 $contactValues['phone_2'] = 4444;
330 $fields[] = 'street_address';
331 $fields[] = 'phone';
332 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, array(0 => NULL, 1 => NULL, 2 => NULL, 3 => NULL, 4 => NULL, 5 => 'Primary', 6 => 'Primary', 7 => 3, 8 => 3), $fields);
333 $contact = $this->callAPISuccessGetSingle('Contact', array('external_identifier' => 'android'));
334 $address = $this->callAPISuccess('Address', 'get', array('contact_id' => $contact['id'], 'sequential' => 1));
335
336 $this->assertEquals(3, $address['values'][0]['location_type_id']);
337 $this->assertEquals(0, $address['values'][0]['is_primary']);
338 $this->assertEquals('Teeny Mansion', $address['values'][0]['street_address']);
339
340 $this->assertEquals(1, $address['values'][1]['location_type_id']);
341 $this->assertEquals(1, $address['values'][1]['is_primary']);
342 $this->assertEquals('Big Mansion', $address['values'][1]['street_address']);
343
344 $phone = $this->callAPISuccess('Phone', 'get', array('contact_id' => $contact['id'], 'sequential' => 1));
345 $this->assertEquals(1, $phone['values'][0]['location_type_id']);
346 $this->assertEquals(1, $phone['values'][0]['is_primary']);
347 $this->assertEquals(12334, $phone['values'][0]['phone']);
348 $this->assertEquals(3, $phone['values'][1]['location_type_id']);
349 $this->assertEquals(0, $phone['values'][1]['is_primary']);
350 $this->assertEquals(4444, $phone['values'][1]['phone']);
351
352 $this->callAPISuccess('Contact', 'delete', array('id' => $contact['id']));
353 }
354
355 /**
356 * Test that the import parser adds the address to the primary location.
357 *
358 * @throws \Exception
359 */
360 public function testImportTwoAddressSecondPrimary() {
361 list($contactValues) = $this->setUpBaseContact();
362 $contactValues['nick_name'] = 'Old Bill';
363 $contactValues['external_identifier'] = 'android';
364 $contactValues['street_address'] = 'Big Mansion';
365 $contactValues['phone'] = 12334;
366 $fields = array_keys($contactValues);
367 $contactValues['street_address_2'] = 'Teeny Mansion';
368 $contactValues['phone_2'] = 4444;
369 $fields[] = 'street_address';
370 $fields[] = 'phone';
371 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, array(0 => NULL, 1 => NULL, 2 => NULL, 3 => NULL, 4 => NULL, 5 => 3, 6 => 3, 7 => 'Primary', 8 => 'Primary'), $fields);
372 $contact = $this->callAPISuccessGetSingle('Contact', array('external_identifier' => 'android'));
373 $address = $this->callAPISuccess('Address', 'get', array('contact_id' => $contact['id'], 'sequential' => 1))['values'];
374
375 $this->assertEquals(1, $address[1]['location_type_id']);
376 $this->assertEquals(1, $address[1]['is_primary']);
377 $this->assertEquals('Teeny Mansion', $address[1]['street_address']);
378
379 $this->assertEquals(3, $address[0]['location_type_id']);
380 $this->assertEquals(0, $address[0]['is_primary']);
381 $this->assertEquals('Big Mansion', $address[0]['street_address']);
382
383 $phone = $this->callAPISuccess('Phone', 'get', ['contact_id' => $contact['id'], 'sequential' => 1, 'options' => ['sort' => 'is_primary DESC']])['values'];
384 $this->assertEquals(3, $phone[1]['location_type_id']);
385 $this->assertEquals(0, $phone[1]['is_primary']);
386 $this->assertEquals(12334, $phone[1]['phone']);
387 $this->assertEquals(1, $phone[0]['location_type_id']);
388 $this->assertEquals(1, $phone[0]['is_primary']);
389 $this->assertEquals(4444, $phone[0]['phone']);
390
391 $this->callAPISuccess('Contact', 'delete', array('id' => $contact['id']));
392 }
393
394 /**
395 * Test that the import parser updates the address on the existing primary location.
396 *
397 * @throws \Exception
398 */
399 public function testImportPrimaryAddressUpdate() {
400 list($contactValues) = $this->setUpBaseContact(array('external_identifier' => 'android'));
401 $contactValues['email'] = 'melinda.gates@microsoft.com';
402 $contactValues['phone'] = '98765';
403 $contactValues['external_identifier'] = 'android';
404 $contactValues['street_address'] = 'Big Mansion';
405 $contactValues['city'] = 'Big City';
406 $contactID = $this->callAPISuccessGetValue('Contact', array('external_identifier' => 'android', 'return' => 'id'));
407 $originalAddress = $this->callAPISuccess('Address', 'create', array('location_type_id' => 2, 'street_address' => 'small house', 'contact_id' => $contactID));
408 $originalPhone = $this->callAPISuccess('phone', 'create', array('location_type_id' => 2, 'phone' => '1234', 'contact_id' => $contactID));
409 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, array(0 => NULL, 1 => NULL, 2 => 'Primary', 3 => NULL, 4 => NULL, 5 => 'Primary', 6 => 'Primary', 7 => 'Primary'));
410 $phone = $this->callAPISuccessGetSingle('Phone', ['phone' => '98765']);
411 $this->assertEquals(2, $phone['location_type_id']);
412 $this->assertEquals($originalPhone['id'], $phone['id']);
413 $email = $this->callAPISuccess('Email', 'getsingle', ['contact_id' => $contactID]);
414 $address = $this->callAPISuccessGetSingle('Address', array('street_address' => 'Big Mansion'));
415 $this->assertEquals(2, $address['location_type_id']);
416 $this->assertEquals($originalAddress['id'], $address['id']);
417 $this->assertEquals('Big City', $address['city']);
418 $this->callAPISuccessGetSingle('Contact', $contactValues);
419 }
420
421 /**
422 * Test the determination of whether a custom field is valid.
423 */
424 public function testCustomFieldValidation() {
425 $errorMessage = array();
426 $customGroup = $this->customGroupCreate(array(
427 'extends' => 'Contact',
428 'title' => 'ABC',
429 ));
430 $customField = $this->customFieldOptionValueCreate($customGroup, 'fieldABC', array('html_type' => 'Multi-Select'));
431 $params = array(
432 'custom_' . $customField['id'] => 'Label1|Label2',
433 );
434 CRM_Contact_Import_Parser_Contact::isErrorInCustomData($params, $errorMessage);
435 $this->assertEquals(array(), $errorMessage);
436 }
437
438 /**
439 * Test that setting duplicate action to fill doesn't blow away data
440 * that exists, but does fill in where it's empty.
441 *
442 * @throw \Exception
443 */
444 public function testImportFill() {
445 // Create a custom field group for testing.
446 $custom_group_name = 'importFillGroup';
447 $results = $this->callAPISuccess('customGroup', 'get', array('title' => $custom_group_name));
448 if ($results['count'] == 0) {
449 $api_params = array(
450 'title' => $custom_group_name,
451 'extends' => 'Individual',
452 'is_active' => TRUE,
453 );
454 $customGroup = $this->callAPISuccess('customGroup', 'create', $api_params);
455 }
456
457 // Add two custom fields.
458 $api_params = array(
459 'custom_group_id' => $customGroup['id'],
460 'label' => 'importFillField1',
461 'html_type' => 'Select',
462 'data_type' => 'String',
463 'option_values' => array(
464 'foo' => 'Foo',
465 'bar' => 'Bar',
466 ),
467 );
468 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
469 $customField1 = $result['id'];
470
471 $api_params = array(
472 'custom_group_id' => $customGroup['id'],
473 'label' => 'importFillField2',
474 'html_type' => 'Select',
475 'data_type' => 'String',
476 'option_values' => array(
477 'baz' => 'Baz',
478 'boo' => 'Boo',
479 ),
480 );
481 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
482 $customField2 = $result['id'];
483
484 // Now set up values.
485 $original_gender = 'Male';
486 $original_custom1 = 'foo';
487 $original_job_title = '';
488 $original_custom2 = '';
489 $original_email = 'test-import-fill@example.org';
490
491 $import_gender = 'Female';
492 $import_custom1 = 'bar';
493 $import_job_title = 'Chief data importer';
494 $import_custom2 = 'baz';
495
496 // Create contact with both one known core field and one custom
497 // field filled in.
498 $api_params = array(
499 'contact_type' => 'Individual',
500 'email' => $original_email,
501 'gender' => $original_gender,
502 'custom_' . $customField1 => $original_custom1,
503 );
504 $result = $this->callAPISuccess('contact', 'create', $api_params);
505 $contact_id = $result['id'];
506
507 // Run an import.
508 $import = array(
509 'email' => $original_email,
510 'gender_id' => $import_gender,
511 'custom_' . $customField1 => $import_custom1,
512 'job_title' => $import_job_title,
513 'custom_' . $customField2 => $import_custom2,
514 );
515
516 $this->runImport($import, CRM_Import_Parser::DUPLICATE_FILL, CRM_Import_Parser::VALID);
517
518 $expected = array(
519 'gender' => $original_gender,
520 'custom_' . $customField1 => $original_custom1,
521 'job_title' => $import_job_title,
522 'custom_' . $customField2 => $import_custom2,
523 );
524
525 $params = array(
526 'id' => $contact_id,
527 'return' => array(
528 'gender',
529 'custom_' . $customField1,
530 'job_title',
531 'custom_' . $customField2,
532 ),
533 );
534 $result = civicrm_api3('Contact', 'get', $params);
535 $values = array_pop($result['values']);
536 foreach ($expected as $field => $expected_value) {
537 if (!isset($values[$field])) {
538 $given_value = NULL;
539 }
540 else {
541 $given_value = $values[$field];
542 }
543 // We expect:
544 // gender: Male
545 // job_title: Chief Data Importer
546 // importFillField1: foo
547 // importFillField2: baz
548 $this->assertEquals($expected_value, $given_value, "$field properly handled during Fill import");
549 }
550 }
551
552 /**
553 * CRM-19888 default country should be used if ambigous.
554 */
555 public function testImportAmbiguousStateCountry() {
556 $this->callAPISuccess('Setting', 'create', ['defaultContactCountry' => 1228]);
557 $countries = CRM_Core_PseudoConstant::country(FALSE, FALSE);
558 $this->callAPISuccess('Setting', 'create', array('countryLimit' => array(array_search('United States', $countries), array_search('Guyana', $countries), array_search('Netherlands', $countries))));
559 $this->callAPISuccess('Setting', 'create', array('provinceLimit' => array(array_search('United States', $countries), array_search('Guyana', $countries), array_search('Netherlands', $countries))));
560 $mapper = array(0 => NULL, 1 => NULL, 2 => 'Primary', 3 => NULL);
561 list($contactValues) = $this->setUpBaseContact();
562 $fields = array_keys($contactValues);
563 $addressValues = array(
564 'street_address' => 'PO Box 2716',
565 'city' => 'Midway',
566 'state_province' => 'UT',
567 'postal_code' => 84049,
568 'country' => 'United States',
569 );
570 $locationTypes = $this->callAPISuccess('Address', 'getoptions', array('field' => 'location_type_id'));
571 $locationTypes = $locationTypes['values'];
572 foreach ($addressValues as $field => $value) {
573 $contactValues['home_' . $field] = $value;
574 $mapper[] = array_search('Home', $locationTypes);
575 $contactValues['work_' . $field] = $value;
576 $mapper[] = array_search('Work', $locationTypes);
577 $fields[] = $field;
578 $fields[] = $field;
579 }
580 $contactValues['work_country'] = '';
581
582 $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, $mapper, $fields);
583 $addresses = $this->callAPISuccess('Address', 'get', array('contact_id' => array('>' => 2), 'sequential' => 1));
584 $this->assertEquals(2, $addresses['count']);
585 $this->assertEquals(array_search('United States', $countries), $addresses['values'][0]['country_id']);
586 $this->assertEquals(array_search('United States', $countries), $addresses['values'][1]['country_id']);
587 }
588
589 /**
590 * Run the import parser.
591 *
592 * @param array $originalValues
593 *
594 * @param int $onDuplicateAction
595 * @param int $expectedResult
596 * @param array|null $mapperLocType
597 * Array of location types that map to the input arrays.
598 * @param array|null $fields
599 * Array of field names. Will be calculated from $originalValues if not passed in, but
600 * that method does not cope with duplicates.
601 */
602 protected function runImport($originalValues, $onDuplicateAction, $expectedResult, $mapperLocType = [], $fields = NULL) {
603 if (!$fields) {
604 $fields = array_keys($originalValues);
605 }
606 $values = array_values($originalValues);
607 $parser = new CRM_Contact_Import_Parser_Contact($fields, $mapperLocType);
608 $parser->_contactType = 'Individual';
609 $parser->_onDuplicate = $onDuplicateAction;
610 $parser->init();
611 $this->assertEquals($expectedResult, $parser->import($onDuplicateAction, $values), 'Return code from parser import was not as expected');
612 }
613
614 /**
615 * @param array $fields Array of fields to be imported
616 * @param array $allfields Array of all fields which can be part of import
617 */
618 private function mapRelationshipFields(&$fields, $allfields) {
619 foreach ($allfields as $key => $fieldtocheck) {
620 $elementIndex = array_search($fieldtocheck->_title, $fields);
621 if ($elementIndex !== FALSE) {
622 $fields[$elementIndex] = $key;
623 }
624 }
625 }
626
627 /**
628 * Set up the underlying contact.
629 *
630 * @param array $params
631 * Optional extra parameters to set.
632 *
633 * @return array
634 * @throws \Exception
635 */
636 protected function setUpBaseContact($params = array()) {
637 $originalValues = array_merge(array(
638 'first_name' => 'Bill',
639 'last_name' => 'Gates',
640 'email' => 'bill.gates@microsoft.com',
641 'nick_name' => 'Billy-boy',
642 ), $params);
643 $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
644 $result = $this->callAPISuccessGetSingle('Contact', $originalValues);
645 return array($originalValues, $result);
646 }
647
648 }