Merge pull request #14247 from pradpnayak/ActvityTags
[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 $_contactID;
41 protected $_locationType;
42 protected $_params;
43
44 protected $_entity;
45
46 public function setUp() {
47 $this->_entity = 'Address';
48 parent::setUp();
49
50 $this->_contactID = $this->organizationCreate();
51 $this->_locationType = $this->locationTypeCreate();
52 CRM_Core_PseudoConstant::flush();
53
54 $this->_params = array(
55 'contact_id' => $this->_contactID,
56 'location_type_id' => $this->_locationType->id,
57 'street_name' => 'Ambachtstraat',
58 'street_number' => '23',
59 'street_address' => 'Ambachtstraat 23',
60 'postal_code' => '6971 BN',
61 'country_id' => '1152',
62 'city' => 'Brummen',
63 'is_primary' => 1,
64 );
65 }
66
67 public function tearDown() {
68 $this->locationTypeDelete($this->_locationType->id);
69 $this->contactDelete($this->_contactID);
70 $this->quickCleanup(array('civicrm_address', 'civicrm_relationship'));
71 }
72
73 /**
74 * @param int $version
75 * @dataProvider versionThreeAndFour
76 */
77 public function testCreateAddress($version) {
78 $this->_apiversion = $version;
79 $result = $this->callAPIAndDocument('address', 'create', $this->_params, __FUNCTION__, __FILE__);
80 $this->assertEquals(1, $result['count']);
81 $this->assertNotNull($result['values'][$result['id']]['id']);
82 $this->getAndCheck($this->_params, $result['id'], 'address');
83 }
84
85 /**
86 * @param int $version
87 * @dataProvider versionThreeAndFour
88 */
89 public function testCreateAddressParsing($version) {
90 $this->_apiversion = $version;
91 $params = array(
92 'street_parsing' => 1,
93 'street_address' => '54A Excelsior Ave. Apt 1C',
94 'location_type_id' => $this->_locationType->id,
95 'contact_id' => $this->_contactID,
96 );
97 $subfile = "AddressParse";
98 $description = "Demonstrates Use of address parsing param.";
99 $result = $this->callAPIAndDocument('address', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
100 $this->assertEquals(54, $result['values'][$result['id']]['street_number']);
101 $this->assertEquals('A', $result['values'][$result['id']]['street_number_suffix']);
102 $this->assertEquals('Excelsior Ave.', $result['values'][$result['id']]['street_name']);
103 $this->assertEquals('Apt 1C', $result['values'][$result['id']]['street_unit']);
104 $this->callAPISuccess('address', 'delete', array('id' => $result['id']));
105
106 }
107
108 /**
109 * Is_primary should be set as a default.
110 * @param int $version
111 * @dataProvider versionThreeAndFour
112 */
113 public function testCreateAddressTestDefaults($version) {
114 $this->_apiversion = $version;
115 $params = $this->_params;
116 unset($params['is_primary']);
117 $result = $this->callAPISuccess('address', 'create', $params);
118 $this->assertEquals(1, $result['count']);
119 $this->assertEquals(1, $result['values'][$result['id']]['is_primary']);
120 $this->getAndCheck($this->_params, $result['id'], 'address');
121 }
122
123 /**
124 * FIXME: Api4
125 */
126 public function testCreateAddressTooLongSuffix() {
127 $params = $this->_params;
128 $params['street_number_suffix'] = 'really long string';
129 $this->callAPIFailure('address', 'create', $params);
130 }
131
132 /**
133 * Create an address with a master ID and ensure that a relationship is created.
134 * @param int $version
135 * @dataProvider versionThreeAndFour
136 */
137 public function testCreateAddressWithMasterRelationshipHousehold($version) {
138 $this->_apiversion = $version;
139 $householdID = $this->householdCreate();
140 $address = $this->callAPISuccess('address', 'create', array_merge($this->_params, $this->_params, array('contact_id' => $householdID)));
141 $individualID = $this->individualCreate();
142 $individualParams = array(
143 'contact_id' => $individualID,
144 'master_id' => $address['id'],
145 );
146 $this->callAPISuccess('address', 'create', array_merge($this->_params, $individualParams));
147 $this->callAPISuccess('relationship', 'getcount', array(
148 'contact_id_a' => $individualID,
149 'contact_id_b' => $this->_contactID,
150 ));
151 }
152
153 /**
154 * Create an address with a master ID and ensure that a relationship is created.
155 * @param int $version
156 * @dataProvider versionThreeAndFour
157 */
158 public function testCreateAddressWithMasterRelationshipOrganization($version) {
159 $this->_apiversion = $version;
160 $address = $this->callAPISuccess('address', 'create', $this->_params);
161 $individualID = $this->individualCreate();
162 $individualParams = array(
163 'contact_id' => $individualID,
164 'master_id' => $address['id'],
165 );
166 $this->callAPISuccess('address', 'create', array_merge($this->_params, $individualParams));
167 $this->callAPISuccess('relationship', 'getcount', array(
168 'contact_id_a' => $individualID,
169 'contact_id_b' => $this->_contactID,
170 ), 1);
171 }
172
173 /**
174 * Create an address with a master ID and relationship creation disabled.
175 * @param int $version
176 * @dataProvider versionThreeAndFour
177 */
178 public function testCreateAddressWithoutMasterRelationshipOrganization($version) {
179 $this->_apiversion = $version;
180 $address = $this->callAPISuccess('address', 'create', $this->_params);
181 $individualID = $this->individualCreate();
182 $individualParams = array(
183 'contact_id' => $individualID,
184 'master_id' => $address['id'],
185 'update_current_employer' => 0,
186 );
187 $this->callAPISuccess('address', 'create', array_merge($this->_params, $individualParams));
188 $this->callAPISuccess('relationship', 'getcount', array(
189 'contact_id_a' => $individualID,
190 'contact_id_b' => $this->_contactID,
191 ), 0);
192 }
193
194 /**
195 * Create an address with a master ID and ensure that a relationship is created.
196 * @param int $version
197 * @dataProvider versionThreeAndFour
198 */
199 public function testCreateAddressWithMasterRelationshipChangingOrganization($version) {
200 $this->_apiversion = $version;
201 $address = $this->callAPISuccess('address', 'create', $this->_params);
202 $organisation2ID = $this->organizationCreate();
203 $address2 = $this->callAPISuccess('address', 'create', array_merge($this->_params, array('contact_id' => $organisation2ID)));
204 $individualID = $this->individualCreate();
205 $individualParams = array_merge($this->_params, array(
206 'contact_id' => $individualID,
207 'master_id' => $address['id'],
208 ));
209 $individualAddress = $this->callAPISuccess('address', 'create', $individualParams);
210 $individualParams['master_id'] = $address2['id'];
211 $individualParams['id'] = $individualAddress['id'];
212 $this->callAPISuccess('address', 'create', $individualParams);
213 $this->callAPISuccessGetCount('relationship', array('contact_id_a' => $individualID), 2);
214 $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?');
215 $this->callAPISuccessGetCount('relationship', array('contact_id_a' => $individualID, 'is_active' => FALSE), 1);
216 $this->callAPISuccessGetCount('relationship', array(
217 'contact_id_a' => $individualID,
218 'is_active' => TRUE,
219 'contact_id_b' => $organisation2ID,
220 ), 1);
221
222 }
223
224 /**
225 * Is_primary should be set as a default.
226 *
227 * ie. create the address, unset the params & recreate.
228 * is_primary should be 0 before & after the update. ie - having no other address
229 * is_primary is invalid.
230 * @param int $version
231 * @dataProvider versionThreeAndFour
232 */
233 public function testCreateAddressTestDefaultWithID($version) {
234 $this->_apiversion = $version;
235 $params = $this->_params;
236 $params['is_primary'] = 0;
237 $result = $this->callAPISuccess('address', 'create', $params);
238 unset($params['is_primary']);
239 $params['id'] = $result['id'];
240 $this->callAPISuccess('address', 'create', $params);
241 $result = $this->callAPISuccess('address', 'get', array('contact_id' => $params['contact_id']));
242 $this->assertEquals(1, $result['count']);
243 $this->assertEquals(1, $result['values'][$result['id']]['is_primary']);
244 $this->getAndCheck($params, $result['id'], 'address', __FUNCTION__);
245 }
246
247 /**
248 * test address deletion.
249 * @param int $version
250 * @dataProvider versionThreeAndFour
251 */
252 public function testDeleteAddress($version) {
253 $this->_apiversion = $version;
254 //check there are no address to start with
255 $get = $this->callAPISuccess('address', 'get', array(
256 'location_type_id' => $this->_locationType->id,
257 ));
258 $this->assertEquals(0, $get['count'], 'Contact already exists ');
259
260 //create one
261 $create = $this->callAPISuccess('address', 'create', $this->_params);
262
263 $result = $this->callAPIAndDocument('address', 'delete', array('id' => $create['id']), __FUNCTION__, __FILE__);
264 $this->assertEquals(1, $result['count']);
265 $get = $this->callAPISuccess('address', 'get', array(
266 'location_type_id' => $this->_locationType->id,
267 ));
268 $this->assertEquals(0, $get['count'], 'Contact not successfully deleted In line ' . __LINE__);
269 }
270
271 /**
272 * Test civicrm_address_get - success expected.
273 * @param int $version
274 * @dataProvider versionThreeAndFour
275 */
276 public function testGetAddress($version) {
277 $this->_apiversion = $version;
278 $address = $this->callAPISuccess('address', 'create', $this->_params);
279
280 $params = array(
281 'contact_id' => $this->_contactID,
282 'street_name' => $address['values'][$address['id']]['street_name'],
283 );
284 $result = $this->callAPIAndDocument('Address', 'Get', $params, __FUNCTION__, __FILE__);
285 $this->callAPISuccess('Address', 'delete', array('id' => $result['id']));
286 $this->assertEquals($address['values'][$address['id']]['location_type_id'], $result['values'][$address['id']]['location_type_id']);
287 $this->assertEquals($address['values'][$address['id']]['is_primary'], $result['values'][$address['id']]['is_primary']);
288 $this->assertEquals($address['values'][$address['id']]['street_address'], $result['values'][$address['id']]['street_address']);
289 }
290
291 /**
292 * Test civicrm_address_get - success expected.
293 * @param int $version
294 * @dataProvider versionThreeAndFour
295 */
296 public function testGetSingleAddress($version) {
297 $this->_apiversion = $version;
298 $this->callAPISuccess('address', 'create', $this->_params);
299 $params = array(
300 'contact_id' => $this->_contactID,
301 );
302 $address = $this->callAPISuccess('Address', 'getsingle', ($params));
303 $this->assertEquals($address['location_type_id'], $this->_params['location_type_id']);
304 $this->callAPISuccess('address', 'delete', array('id' => $address['id']));
305 }
306
307 /**
308 * Test civicrm_address_get with sort option- success expected.
309 * @param int $version
310 * @dataProvider versionThreeAndFour
311 */
312 public function testGetAddressSort($version) {
313 $this->_apiversion = $version;
314 $create = $this->callAPISuccess('address', 'create', $this->_params);
315 $this->callAPISuccess('address', 'create', array_merge($this->_params, array('street_address' => 'yzy')));
316 $subfile = "AddressSort";
317 $description = "Demonstrates Use of sort filter.";
318 $params = array(
319 'options' => array(
320 'sort' => 'street_address DESC',
321 'limit' => 2,
322 ),
323 'sequential' => 1,
324 );
325 $result = $this->callAPIAndDocument('Address', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
326 $this->assertEquals(2, $result['count']);
327 $this->assertEquals('Ambachtstraat 23', $result['values'][1]['street_address']);
328 $this->callAPISuccess('address', 'delete', array('id' => $create['id']));
329 }
330
331 /**
332 * Test civicrm_address_get with sort option- success expected.
333 * @param int $version
334 * @dataProvider versionThreeAndFour
335 */
336 public function testGetAddressLikeSuccess($version) {
337 $this->_apiversion = $version;
338 $this->callAPISuccess('address', 'create', $this->_params);
339 $subfile = "AddressLike";
340 $description = "Demonstrates Use of Like.";
341 $params = array(
342 'street_address' => array('LIKE' => '%mb%'),
343 'sequential' => 1,
344 );
345 $result = $this->callAPIAndDocument('Address', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
346 $this->assertEquals(1, $result['count']);
347 $this->assertEquals('Ambachtstraat 23', $result['values'][0]['street_address']);
348 $this->callAPISuccess('address', 'delete', array('id' => $result['id']));
349 }
350
351 /**
352 * Test civicrm_address_get with sort option- success expected.
353 * @param int $version
354 * @dataProvider versionThreeAndFour
355 */
356 public function testGetAddressLikeFail($version) {
357 $this->_apiversion = $version;
358 $create = $this->callAPISuccess('address', 'create', $this->_params);
359 $params = array(
360 'street_address' => array('LIKE' => "'%xy%'"),
361 'sequential' => 1,
362 );
363 $result = $this->callAPISuccess('Address', 'Get', ($params));
364 $this->assertEquals(0, $result['count']);
365 $this->callAPISuccess('address', 'delete', array('id' => $create['id']));
366 }
367
368 /**
369 * FIXME: Api4 custom address fields broken?
370 */
371 public function testGetWithCustom() {
372 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
373
374 $params = $this->_params;
375 $params['custom_' . $ids['custom_field_id']] = "custom string";
376
377 $result = $this->callAPISuccess($this->_entity, 'create', $params);
378
379 $getParams = array('id' => $result['id'], 'return' => array('custom'));
380 $check = $this->callAPISuccess($this->_entity, 'get', $getParams);
381
382 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
383
384 $this->customFieldDelete($ids['custom_field_id']);
385 $this->customGroupDelete($ids['custom_group_id']);
386 $this->callAPISuccess('address', 'delete', array('id' => $result['id']));
387 }
388
389 /**
390 * @param int $version
391 * @dataProvider versionThreeAndFour
392 */
393 public function testCreateAddressPrimaryHandlingChangeToPrimary($version) {
394 $this->_apiversion = $version;
395 $params = $this->_params;
396 unset($params['is_primary']);
397 $address1 = $this->callAPISuccess('address', 'create', $params);
398 $this->assertApiSuccess($address1);
399 //now we check & make sure it has been set to primary
400 $check = $this->callAPISuccess('address', 'getcount', array(
401 'is_primary' => 1,
402 'id' => $address1['id'],
403 ));
404 $this->assertEquals(1, $check);
405 $this->callAPISuccess('address', 'delete', array('id' => $address1['id']));
406 }
407
408 /**
409 * @param int $version
410 * @dataProvider versionThreeAndFour
411 */
412 public function testCreateAddressPrimaryHandlingChangeExisting($version) {
413 $this->_apiversion = $version;
414 $address1 = $this->callAPISuccess('address', 'create', $this->_params);
415 $this->callAPISuccess('address', 'create', $this->_params);
416 $check = $this->callAPISuccess('address', 'getcount', array(
417 'is_primary' => 1,
418 'contact_id' => $this->_contactID,
419 ));
420 $this->assertEquals(1, $check);
421 $this->callAPISuccess('address', 'delete', array('id' => $address1['id']));
422 }
423
424 /**
425 * Test Creating address of same type alreay ind the database
426 * This is legacy API v3 behaviour and not correct behaviour
427 * however we are too far down the path wiwth v3 to fix this
428 * @link https://chat.civicrm.org/civicrm/pl/zcq3jkg69jdt5g4aqze6bbe9pc
429 * FIXME: Api4
430 */
431 public function testCreateDuplicateLocationTypes() {
432 $address1 = $this->callAPISuccess('address', 'create', $this->_params);
433 $address2 = $this->callAPISuccess('address', 'create', array(
434 'location_type_id' => $this->_locationType->id,
435 'street_address' => '1600 Pensilvania Avenue',
436 'city' => 'Washington DC',
437 'is_primary' => 0,
438 'is_billing' => 0,
439 'contact_id' => $this->_contactID,
440 ));
441 $check = $this->callAPISuccess('address', 'getcount', array(
442 'contact_id' => $this->_contactID,
443 'location_type_id' => $this->_locationType->id,
444 ));
445 $this->assertEquals(2, $check);
446 $this->callAPISuccess('address', 'delete', array('id' => $address1['id']));
447 $this->callAPISuccess('address', 'delete', array('id' => $address2['id']));
448 }
449
450 public function testGetWithJoin() {
451 $cid = $this->individualCreate(array(
452 'api.Address.create' => array(
453 'street_address' => __FUNCTION__,
454 'location_type_id' => $this->_locationType->id,
455 ),
456 ));
457 $result = $this->callAPISuccess('address', 'getsingle', array(
458 'check_permissions' => TRUE,
459 'contact_id' => $cid,
460 'street_address' => __FUNCTION__,
461 'return' => 'contact_id.contact_type',
462 ));
463 $this->assertEquals('Individual', $result['contact_id.contact_type']);
464 }
465
466 /**
467 * Test Address create with a state name that at least two countries have, e.g. Maryland, United States vs. Maryland, Liberia
468 *
469 * @see https://lab.civicrm.org/dev/core/issues/725
470 */
471 public function testCreateAddressStateProvinceIDCorrectForCountry() {
472 $params = $this->_params;
473 $params['sequential'] = 1;
474 // United States country id
475 $params['country_id'] = '1228';
476 $params['state_province_id'] = 'Maryland';
477 $params['city'] = 'Baltimore';
478 $params['street_address'] = '600 N Charles St.';
479 $params['postal_code'] = '21201';
480 unset($params['street_name']);
481 unset($params['street_number']);
482 $address1 = $this->callAPISuccess('address', 'create', $params);
483 // should find state_province_id of 1019, Maryland, United States ... NOT 3497, Maryland, Liberia
484 $this->assertEquals('1019', $address1['values'][0]['state_province_id']);
485
486 // Now try it in Liberia
487 $params = $this->_params;
488 $params['sequential'] = 1;
489 // Liberia country id
490 $params['country_id'] = '1122';
491 $params['state_province_id'] = 'Maryland';
492 $address2 = $this->callAPISuccess('address', 'create', $params);
493 $this->assertEquals('3497', $address2['values'][0]['state_province_id']);
494 }
495
496 public function getSymbolicCountryStateExamples() {
497 return [
498 // [mixed $inputCountry, mixed $inputState, int $expectCountry, int $expectState]
499 [1228, 1004, 1228, 1004],
500 //['US', 'CA', 1228, 1004],
501 //['US', 'TX', 1228, 1042],
502 ['US', 'California', 1228, 1004],
503 [1228, 'Texas', 1228, 1042],
504 // Don't think these have been supported?
505 // ['United States', 1004, 1228, 1004] ,
506 // ['United States', 'TX', 1228, 1042],
507 ];
508 }
509
510 /**
511 * @param mixed $inputCountry
512 * Ex: 1228 or 'US'
513 * @param mixed $inputState
514 * Ex: 1004 or 'CA'
515 * @param int $expectCountry
516 * @param int $expectState
517 * @dataProvider getSymbolicCountryStateExamples
518 */
519 public function testCreateAddressSymbolicCountryAndState($inputCountry, $inputState, $expectCountry, $expectState) {
520 $cid = $this->individualCreate();
521 $r = $this->callAPISuccess('Address', 'create', [
522 'contact_id' => $cid,
523 'location_type_id' => 1,
524 'street_address' => '123 Some St',
525 'city' => 'Hereville',
526 //'US',
527 'country_id' => $inputCountry,
528 // 'California',
529 'state_province_id' => $inputState,
530 'postal_code' => '94100',
531 ]);
532 $created = CRM_Utils_Array::first($r['values']);
533 $this->assertEquals($expectCountry, $created['country_id']);
534 $this->assertEquals($expectState, $created['state_province_id']);
535 }
536
537 /**
538 * @param int $version
539 * @dataProvider versionThreeAndFour
540 */
541 public function testBuildStateProvinceOptionsWithDodgyProvinceLimit($version) {
542 $this->_apiversion = $version;
543 $provinceLimit = [1228, "abcd;ef"];
544 $this->callAPISuccess('setting', 'create', [
545 'provinceLimit' => $provinceLimit,
546 ]);
547 $result = $this->callAPIFailure('address', 'getoptions', ['field' => 'state_province_id']);
548 // confirm that we hit our error not a SQLI.
549 $this->assertEquals('Province limit or default country setting is incorrect', $result['error_message']);
550 $this->callAPISuccess('setting', 'create', [
551 'provinceLimit' => [1228],
552 ]);
553 // Now confirm with a correct province setting it works fine
554 $this->callAPISuccess('address', 'getoptions', ['field' => 'state_province_id']);
555 }
556
557 /**
558 * @param int $version
559 * @dataProvider versionThreeAndFour
560 */
561 public function testBuildCountryWithDodgyCountryLimitSetting($version) {
562 $this->_apiversion = $version;
563 $countryLimit = [1228, "abcd;ef"];
564 $this->callAPISuccess('setting', 'create', [
565 'countryLimit' => $countryLimit,
566 ]);
567 $result = $this->callAPIFailure('address', 'getoptions', ['field' => 'country_id']);
568 // confirm that we hit our error not a SQLI.
569 $this->assertEquals('Available Country setting is incorrect', $result['error_message']);
570 $this->callAPISuccess('setting', 'create', [
571 'countryLimit' => [1228],
572 ]);
573 // Now confirm with a correct province setting it works fine
574 $this->callAPISuccess('address', 'getoptions', ['field' => 'country_id']);
575 }
576
577 public function testBuildCountyWithDodgeStateProvinceFiltering() {
578 $result = $this->callAPIFailure('Address', 'getoptions', [
579 'field' => 'county_id',
580 'state_province_id' => "abcd;ef",
581 ]);
582 $this->assertEquals('Can only accept Integers for state_province_id filtering', $result['error_message']);
583 $goodResult = $this->callAPISuccess('Address', 'getoptions', [
584 'field' => 'county_id',
585 'state_province_id' => 1004,
586 ]);
587 $this->assertEquals('San Francisco', $goodResult['values'][4]);
588 }
589
590 }