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