Merge pull request #1 from civicrm/master
[civicrm-core.git] / tests / phpunit / api / v3 / AddressTest.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 * Test APIv3 civicrm_activity_* functions
30 *
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contact
33 */
34
35 /**
36 * Class api_v3_AddressTest
37 * @group headless
38 */
39 class api_v3_AddressTest extends CiviUnitTestCase {
40 protected $_apiversion = 3;
41 protected $_contactID;
42 protected $_locationType;
43 protected $_params;
44
45 protected $_entity;
46
47 public function setUp() {
48 $this->_entity = 'Address';
49 parent::setUp();
50
51 $this->_contactID = $this->organizationCreate();
52 $this->_locationType = $this->locationTypeCreate();
53 CRM_Core_PseudoConstant::flush();
54
55 $this->_params = array(
56 'contact_id' => $this->_contactID,
57 'location_type_id' => $this->_locationType->id,
58 'street_name' => 'Ambachtstraat',
59 'street_number' => '23',
60 'street_address' => 'Ambachtstraat 23',
61 'postal_code' => '6971 BN',
62 'country_id' => '1152',
63 'city' => 'Brummen',
64 'is_primary' => 1,
65 );
66 }
67
68 public function tearDown() {
69 $this->locationTypeDelete($this->_locationType->id);
70 $this->contactDelete($this->_contactID);
71 $this->quickCleanup(array('civicrm_address', 'civicrm_relationship'));
72 }
73
74 public function testCreateAddress() {
75 $result = $this->callAPIAndDocument('address', 'create', $this->_params, __FUNCTION__, __FILE__);
76 $this->assertEquals(1, $result['count']);
77 $this->assertNotNull($result['values'][$result['id']]['id']);
78 $this->getAndCheck($this->_params, $result['id'], 'address');
79 }
80
81 public function testCreateAddressParsing() {
82 $params = array(
83 'street_parsing' => 1,
84 'street_address' => '54A Excelsior Ave. Apt 1C',
85 'location_type_id' => $this->_locationType->id,
86 'contact_id' => $this->_contactID,
87 );
88 $subfile = "AddressParse";
89 $description = "Demonstrates Use of address parsing param.";
90 $result = $this->callAPIAndDocument('address', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
91 $this->assertEquals(54, $result['values'][$result['id']]['street_number']);
92 $this->assertEquals('A', $result['values'][$result['id']]['street_number_suffix']);
93 $this->assertEquals('Excelsior Ave.', $result['values'][$result['id']]['street_name']);
94 $this->assertEquals('Apt 1C', $result['values'][$result['id']]['street_unit']);
95 $this->callAPISuccess('address', 'delete', array('id' => $result['id']));
96
97 }
98
99 /**
100 * Is_primary should be set as a default.
101 */
102 public function testCreateAddressTestDefaults() {
103 $params = $this->_params;
104 unset($params['is_primary']);
105 $result = $this->callAPISuccess('address', 'create', $params);
106 $this->assertEquals(1, $result['count']);
107 $this->assertEquals(1, $result['values'][$result['id']]['is_primary']);
108 $this->getAndCheck($this->_params, $result['id'], 'address');
109 }
110
111 public function testCreateAddressTooLongSuffix() {
112 $params = $this->_params;
113 $params['street_number_suffix'] = 'really long string';
114 $this->callAPIFailure('address', 'create', $params);
115 }
116
117 /**
118 * Create an address with a master ID and ensure that a relationship is created.
119 */
120 public function testCreateAddressWithMasterRelationshipHousehold() {
121 $householdID = $this->householdCreate();
122 $address = $this->callAPISuccess('address', 'create', array_merge($this->_params, $this->_params, array('contact_id' => $householdID)));
123 $individualID = $this->individualCreate();
124 $individualParams = array(
125 'contact_id' => $individualID,
126 'master_id' => $address['id'],
127 );
128 $this->callAPISuccess('address', 'create', array_merge($this->_params, $individualParams));
129 $this->callAPISuccess('relationship', 'getcount', array(
130 'contact_id_a' => $individualID,
131 'contact_id_b' => $this->_contactID,
132 ));
133 }
134
135 /**
136 * Create an address with a master ID and ensure that a relationship is created.
137 */
138 public function testCreateAddressWithMasterRelationshipOrganization() {
139 $address = $this->callAPISuccess('address', 'create', $this->_params);
140 $individualID = $this->individualCreate();
141 $individualParams = array(
142 'contact_id' => $individualID,
143 'master_id' => $address['id'],
144 );
145 $this->callAPISuccess('address', 'create', array_merge($this->_params, $individualParams));
146 $this->callAPISuccess('relationship', 'getcount', array(
147 'contact_id_a' => $individualID,
148 'contact_id_b' => $this->_contactID,
149 ), 1);
150 }
151
152 /**
153 * Create an address with a master ID and relationship creation disabled.
154 */
155 public function testCreateAddressWithoutMasterRelationshipOrganization() {
156 $address = $this->callAPISuccess('address', 'create', $this->_params);
157 $individualID = $this->individualCreate();
158 $individualParams = array(
159 'contact_id' => $individualID,
160 'master_id' => $address['id'],
161 'update_current_employer' => 0,
162 );
163 $this->callAPISuccess('address', 'create', array_merge($this->_params, $individualParams));
164 $this->callAPISuccess('relationship', 'getcount', array(
165 'contact_id_a' => $individualID,
166 'contact_id_b' => $this->_contactID,
167 ), 0);
168 }
169
170 /**
171 * Create an address with a master ID and ensure that a relationship is created.
172 */
173 public function testCreateAddressWithMasterRelationshipChangingOrganization() {
174 $address = $this->callAPISuccess('address', 'create', $this->_params);
175 $organisation2ID = $this->organizationCreate();
176 $address2 = $this->callAPISuccess('address', 'create', array_merge($this->_params, array('contact_id' => $organisation2ID)));
177 $individualID = $this->individualCreate();
178 $individualParams = array_merge($this->_params, array(
179 'contact_id' => $individualID,
180 'master_id' => $address['id'],
181 ));
182 $individualAddress = $this->callAPISuccess('address', 'create', $individualParams);
183 $individualParams['master_id'] = $address2['id'];
184 $individualParams['id'] = $individualAddress['id'];
185 $this->callAPISuccess('address', 'create', $individualParams);
186 $this->callAPISuccessGetCount('relationship', array('contact_id_a' => $individualID), 2);
187 $this->markTestIncomplete('Remainder of test checks that employer relationship is disabled when new one is created but turns out to be not happening - by design?');
188 $this->callAPISuccessGetCount('relationship', array('contact_id_a' => $individualID, 'is_active' => FALSE), 1);
189 $this->callAPISuccessGetCount('relationship', array(
190 'contact_id_a' => $individualID,
191 'is_active' => TRUE,
192 'contact_id_b' => $organisation2ID,
193 ), 1);
194
195 }
196
197 /**
198 * Is_primary should be set as a default.
199 *
200 * ie. create the address, unset the params & recreate.
201 * is_primary should be 0 before & after the update. ie - having no other address
202 * is_primary is invalid.
203 */
204 public function testCreateAddressTestDefaultWithID() {
205 $params = $this->_params;
206 $params['is_primary'] = 0;
207 $result = $this->callAPISuccess('address', 'create', $params);
208 unset($params['is_primary']);
209 $params['id'] = $result['id'];
210 $result = $this->callAPISuccess('address', 'create', $params);
211 $this->callAPISuccess('address', 'get', array('contact_id' => $params['contact_id']));
212 $this->assertEquals(1, $result['count']);
213 $this->assertEquals(1, $result['values'][$result['id']]['is_primary']);
214 $this->getAndCheck($params, $result['id'], 'address', __FUNCTION__);
215 }
216
217 /**
218 * test address deletion.
219 */
220 public function testDeleteAddress() {
221 //check there are no address to start with
222 $get = $this->callAPISuccess('address', 'get', array(
223 'location_type_id' => $this->_locationType->id,
224 ));
225 $this->assertEquals(0, $get['count'], 'Contact already exists ');
226
227 //create one
228 $create = $this->callAPISuccess('address', 'create', $this->_params);
229
230 $result = $this->callAPIAndDocument('address', 'delete', array('id' => $create['id']), __FUNCTION__, __FILE__);
231 $this->assertEquals(1, $result['count']);
232 $get = $this->callAPISuccess('address', 'get', array(
233 'location_type_id' => $this->_locationType->id,
234 ));
235 $this->assertEquals(0, $get['count'], 'Contact not successfully deleted In line ' . __LINE__);
236 }
237
238 /**
239 * Test civicrm_address_get - success expected.
240 */
241 public function testGetAddress() {
242 $address = $this->callAPISuccess('address', 'create', $this->_params);
243
244 $params = array(
245 'contact_id' => $this->_contactID,
246 'street_name' => $address['values'][$address['id']]['street_name'],
247 );
248 $result = $this->callAPIAndDocument('Address', 'Get', $params, __FUNCTION__, __FILE__);
249 $this->callAPISuccess('Address', 'delete', array('id' => $result['id']));
250 $this->assertEquals($address['values'][$address['id']]['location_type_id'], $result['values'][$address['id']]['location_type_id']);
251 $this->assertEquals($address['values'][$address['id']]['is_primary'], $result['values'][$address['id']]['is_primary']);
252 $this->assertEquals($address['values'][$address['id']]['street_address'], $result['values'][$address['id']]['street_address']);
253 }
254
255 /**
256 * Test civicrm_address_get - success expected.
257 */
258 public function testGetSingleAddress() {
259 $this->callAPISuccess('address', 'create', $this->_params);
260 $params = array(
261 'contact_id' => $this->_contactID,
262 );
263 $address = $this->callAPISuccess('Address', 'getsingle', ($params));
264 $this->assertEquals($address['location_type_id'], $this->_params['location_type_id']);
265 $this->callAPISuccess('address', 'delete', array('id' => $address['id']));
266 }
267
268 /**
269 * Test civicrm_address_get with sort option- success expected.
270 */
271 public function testGetAddressSort() {
272 $create = $this->callAPISuccess('address', 'create', $this->_params);
273 $this->callAPISuccess('address', 'create', array_merge($this->_params, array('street_address' => 'yzy')));
274 $subfile = "AddressSort";
275 $description = "Demonstrates Use of sort filter.";
276 $params = array(
277 'options' => array(
278 'sort' => 'street_address DESC',
279 'limit' => 2,
280 ),
281 'sequential' => 1,
282 );
283 $result = $this->callAPIAndDocument('Address', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
284 $this->assertEquals(2, $result['count']);
285 $this->assertEquals('Ambachtstraat 23', $result['values'][1]['street_address']);
286 $this->callAPISuccess('address', 'delete', array('id' => $create['id']));
287 }
288
289 /**
290 * Test civicrm_address_get with sort option- success expected.
291 */
292 public function testGetAddressLikeSuccess() {
293 $this->callAPISuccess('address', 'create', $this->_params);
294 $subfile = "AddressLike";
295 $description = "Demonstrates Use of Like.";
296 $params = array(
297 'street_address' => array('LIKE' => '%mb%'),
298 'sequential' => 1,
299 );
300 $result = $this->callAPIAndDocument('Address', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
301 $this->assertEquals(1, $result['count']);
302 $this->assertEquals('Ambachtstraat 23', $result['values'][0]['street_address']);
303 $this->callAPISuccess('address', 'delete', array('id' => $result['id']));
304 }
305
306 /**
307 * Test civicrm_address_get with sort option- success expected.
308 */
309 public function testGetAddressLikeFail() {
310 $create = $this->callAPISuccess('address', 'create', $this->_params);
311 $params = array(
312 'street_address' => array('LIKE' => "'%xy%'"),
313 'sequential' => 1,
314 );
315 $result = $this->callAPISuccess('Address', 'Get', ($params));
316 $this->assertEquals(0, $result['count']);
317 $this->callAPISuccess('address', 'delete', array('id' => $create['id']));
318 }
319
320 /**
321 */
322 public function testGetWithCustom() {
323 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
324
325 $params = $this->_params;
326 $params['custom_' . $ids['custom_field_id']] = "custom string";
327
328 $result = $this->callAPISuccess($this->_entity, 'create', $params);
329
330 $getParams = array('id' => $result['id'], 'return' => array('custom'));
331 $check = $this->callAPISuccess($this->_entity, 'get', $getParams);
332
333 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
334
335 $this->customFieldDelete($ids['custom_field_id']);
336 $this->customGroupDelete($ids['custom_group_id']);
337 $this->callAPISuccess('address', 'delete', array('id' => $result['id']));
338 }
339
340 /**
341 */
342 public function testCreateAddressPrimaryHandlingChangeToPrimary() {
343 $params = $this->_params;
344 unset($params['is_primary']);
345 $address1 = $this->callAPISuccess('address', 'create', $params);
346 $this->assertApiSuccess($address1);
347 //now we check & make sure it has been set to primary
348 $check = $this->callAPISuccess('address', 'getcount', array(
349 'is_primary' => 1,
350 'id' => $address1['id'],
351 ));
352 $this->assertEquals(1, $check);
353 $this->callAPISuccess('address', 'delete', array('id' => $address1['id']));
354 }
355
356 /**
357 */
358 public function testCreateAddressPrimaryHandlingChangeExisting() {
359 $address1 = $this->callAPISuccess('address', 'create', $this->_params);
360 $this->callAPISuccess('address', 'create', $this->_params);
361 $check = $this->callAPISuccess('address', 'getcount', array(
362 'is_primary' => 1,
363 'contact_id' => $this->_contactID,
364 ));
365 $this->assertEquals(1, $check);
366 $this->callAPISuccess('address', 'delete', array('id' => $address1['id']));
367 }
368
369 /**
370 * Test Creating address of same type alreay ind the database
371 * This is legacy API v3 behaviour and not correct behaviour
372 * however we are too far down the path wiwth v3 to fix this
373 * @link https://chat.civicrm.org/civicrm/pl/zcq3jkg69jdt5g4aqze6bbe9pc
374 * @todo vis this in v4 api
375 */
376 public function testCreateDuplicateLocationTypes() {
377 $address1 = $this->callAPISuccess('address', 'create', $this->_params);
378 $address2 = $this->callAPISuccess('address', 'create', array(
379 'location_type_id' => $this->_locationType->id,
380 'street_address' => '1600 Pensilvania Avenue',
381 'city' => 'Washington DC',
382 'is_primary' => 0,
383 'is_billing' => 0,
384 'contact_id' => $this->_contactID,
385 ));
386 $check = $this->callAPISuccess('address', 'getcount', array(
387 'contact_id' => $this->_contactID,
388 'location_type_id' => $this->_locationType->id,
389 ));
390 $this->assertEquals(2, $check);
391 $this->callAPISuccess('address', 'delete', array('id' => $address1['id']));
392 $this->callAPISuccess('address', 'delete', array('id' => $address2['id']));
393 }
394
395 public function testGetWithJoin() {
396 $cid = $this->individualCreate(array(
397 'api.Address.create' => array(
398 'street_address' => __FUNCTION__,
399 'location_type_id' => $this->_locationType->id,
400 ),
401 ));
402 $result = $this->callAPISuccess('address', 'getsingle', array(
403 'check_permissions' => TRUE,
404 'contact_id' => $cid,
405 'street_address' => __FUNCTION__,
406 'return' => 'contact_id.contact_type',
407 ));
408 $this->assertEquals('Individual', $result['contact_id.contact_type']);
409 }
410
411 /**
412 * Test Address create with a state name that at least two countries have, e.g. Maryland, United States vs. Maryland, Liberia
413 *
414 * @see https://lab.civicrm.org/dev/core/issues/725
415 */
416 public function testCreateAddressStateProvinceIDCorrectForCountry() {
417 $params = $this->_params;
418 $params['sequential'] = 1;
419 // United States country id
420 $params['country_id'] = '1228';
421 $params['state_province_id'] = 'Maryland';
422 $params['city'] = 'Baltimore';
423 $params['street_address'] = '600 N Charles St.';
424 $params['postal_code'] = '21201';
425 unset($params['street_name']);
426 unset($params['street_number']);
427 $address1 = $this->callAPISuccess('address', 'create', $params);
428 // should find state_province_id of 1019, Maryland, United States ... NOT 3497, Maryland, Liberia
429 $this->assertEquals('1019', $address1['values'][0]['state_province_id']);
430
431 // Now try it in Liberia
432 $params = $this->_params;
433 $params['sequential'] = 1;
434 // Liberia country id
435 $params['country_id'] = '1122';
436 $params['state_province_id'] = 'Maryland';
437 $address2 = $this->callAPISuccess('address', 'create', $params);
438 $this->assertEquals('3497', $address2['values'][0]['state_province_id']);
439 }
440
441 public function getSymbolicCountryStateExamples() {
442 return [
443 // [mixed $inputCountry, mixed $inputState, int $expectCountry, int $expectState]
444 [1228, 1004, 1228, 1004],
445 //['US', 'CA', 1228, 1004],
446 //['US', 'TX', 1228, 1042],
447 ['US', 'California', 1228, 1004],
448 [1228, 'Texas', 1228, 1042],
449 // Don't think these have been supported?
450 // ['United States', 1004, 1228, 1004] ,
451 // ['United States', 'TX', 1228, 1042],
452 ];
453 }
454
455 /**
456 * @param mixed $inputCountry
457 * Ex: 1228 or 'US'
458 * @param mixed $inputState
459 * Ex: 1004 or 'CA'
460 * @param int $expectCountry
461 * @param int $expectState
462 * @dataProvider getSymbolicCountryStateExamples
463 */
464 public function testCreateAddressSymbolicCountryAndState($inputCountry, $inputState, $expectCountry, $expectState) {
465 $cid = $this->individualCreate();
466 $r = $this->callAPISuccess('Address', 'create', [
467 'contact_id' => $cid,
468 'location_type_id' => 1,
469 'street_address' => '123 Some St',
470 'city' => 'Hereville',
471 //'US',
472 'country_id' => $inputCountry,
473 // 'California',
474 'state_province_id' => $inputState,
475 'postal_code' => '94100',
476 ]);
477 $created = CRM_Utils_Array::first($r['values']);
478 $this->assertEquals($expectCountry, $created['country_id']);
479 $this->assertEquals($expectState, $created['state_province_id']);
480 }
481
482 }