Merge pull request #14488 from seamuslee001/test_dev_core_889
[civicrm-core.git] / tests / phpunit / api / v3 / ContactTest.php
CommitLineData
6a488035
TO
1<?php
2/**
381fa321 3 * @file
4 * File for the TestContact class.
6a488035
TO
5 *
6 * (PHP 5)
7 *
6c6e6187
TO
8 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
9 * @copyright Copyright CiviCRM LLC (C) 2009
10 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
6a488035 11 * GNU Affero General Public License version 3
6c6e6187
TO
12 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
13 * @package CiviCRM
6a488035
TO
14 *
15 * This file is part of CiviCRM
16 *
17 * CiviCRM is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Affero General Public License
19 * as published by the Free Software Foundation; either version 3 of
20 * the License, or (at your option) any later version.
21 *
22 * CiviCRM is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
26 *
27 * You should have received a copy of the GNU Affero General Public
28 * License along with this program. If not, see
29 * <http://www.gnu.org/licenses/>.
30 */
31
6a488035
TO
32/**
33 * Test APIv3 civicrm_contact* functions
34 *
6c6e6187
TO
35 * @package CiviCRM_APIv3
36 * @subpackage API_Contact
acb109b7 37 * @group headless
6a488035 38 */
6a488035 39class api_v3_ContactTest extends CiviUnitTestCase {
119664d6 40 use CRMTraits_Custom_CustomDataTrait;
41
6a488035
TO
42 public $DBResetRequired = FALSE;
43 protected $_apiversion;
44 protected $_entity;
45 protected $_params;
b7c9bc4c 46
f6722559 47 protected $_contactID;
6c6e6187 48 protected $_financialTypeId = 1;
6a488035 49
119664d6 50
51 /**
52 * Entity to be extended.
53 *
54 * @var string
55 */
56 protected $entity = 'Contact';
57
6a488035 58 /**
381fa321 59 * Test setup for every test.
6a488035 60 *
d177a2a6
EM
61 * Connect to the database, truncate the tables that will be used
62 * and redirect stdin to a temporary file
6a488035
TO
63 */
64 public function setUp() {
381fa321 65 // Connect to the database.
6a488035 66 parent::setUp();
f6722559 67 $this->_entity = 'contact';
68 $this->_params = array(
6a488035
TO
69 'first_name' => 'abc1',
70 'contact_type' => 'Individual',
71 'last_name' => 'xyz1',
6a488035 72 );
6a488035
TO
73 }
74
701a69da 75 /**
76 * Restore the DB for the next test.
77 *
78 * @throws \Exception
79 */
00be9182 80 public function tearDown() {
2d932085 81 $this->_apiversion = 3;
1ca22999 82 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
6a488035
TO
83 // truncate a few tables
84 $tablesToTruncate = array(
6a488035
TO
85 'civicrm_email',
86 'civicrm_contribution',
87 'civicrm_line_item',
88 'civicrm_website',
e635f9d4
TO
89 'civicrm_relationship',
90 'civicrm_uf_match',
405f289b 91 'civicrm_phone',
e9e27a80 92 'civicrm_address',
1ca22999 93 'civicrm_acl_contact_cache',
5ea06a7b 94 'civicrm_activity_contact',
95 'civicrm_activity',
0626851e 96 'civicrm_group',
97 'civicrm_group_contact',
98 'civicrm_saved_search',
99 'civicrm_group_contact_cache',
e13fa54b 100 'civicrm_prevnext_cache',
6a488035
TO
101 );
102
f6722559 103 $this->quickCleanup($tablesToTruncate, TRUE);
1ca22999 104 parent::tearDown();
6a488035
TO
105 }
106
107 /**
381fa321 108 * Test civicrm_contact_create.
6a488035 109 *
381fa321 110 * Verify that attempt to create individual contact with only
111 * first and last names succeeds
2d932085
CW
112 *
113 * @param int $version
114 * @dataProvider versionThreeAndFour
6a488035 115 */
2d932085
CW
116 public function testAddCreateIndividual($version) {
117 $this->_apiversion = $version;
6a488035
TO
118 $oldCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
119 $params = array(
120 'first_name' => 'abc1',
121 'contact_type' => 'Individual',
122 'last_name' => 'xyz1',
6a488035
TO
123 );
124
f6722559 125 $contact = $this->callAPISuccess('contact', 'create', $params);
fe482240
EM
126 $this->assertTrue(is_numeric($contact['id']));
127 $this->assertTrue($contact['id'] > 0);
6a488035 128 $newCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
6c6e6187 129 $this->assertEquals($oldCount + 1, $newCount);
6a488035 130
6a488035
TO
131 $this->assertDBState('CRM_Contact_DAO_Contact',
132 $contact['id'],
133 $params
134 );
135 }
136
ec52a65a 137 /**
138 * Test that it is possible to prevent cache clearing via option.
139 *
140 * Cache clearing is bypassed if 'options' => array('do_not_reset_cache' => 1 is used.
141 */
142 public function testCreateIndividualNoCacheClear() {
143
144 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
145 $groupID = $this->groupCreate();
146
147 $this->putGroupContactCacheInClearableState($groupID, $contact);
148
149 $this->callAPISuccess('contact', 'create', array('id' => $contact['id']));
150 $this->assertEquals(0, CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
151
152 // Rinse & repeat, but with the option.
153 $this->putGroupContactCacheInClearableState($groupID, $contact);
0626851e 154 CRM_Core_Config::setPermitCacheFlushMode(FALSE);
155 $this->callAPISuccess('contact', 'create', array('id' => $contact['id']));
ec52a65a 156 $this->assertEquals(1, CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
0626851e 157 CRM_Core_Config::setPermitCacheFlushMode(TRUE);
ec52a65a 158 }
159
3a15378c 160 /**
161 * Test for international string acceptance (CRM-10210).
828cd10c 162 * Requires the databsase to be in utf8.
3a15378c 163 *
164 * @dataProvider getInternationalStrings
165 *
166 * @param string $string
167 * String to be tested.
2fc64082 168 *
828cd10c 169 * Bool to see if we should check charset.
3a15378c 170 *
171 * @throws \Exception
172 */
2fc64082 173 public function testInternationalStrings($string) {
3a15378c 174 $this->callAPISuccess('Contact', 'create', array_merge(
175 $this->_params,
176 array('first_name' => $string)
177 ));
2fc64082 178
3a15378c 179 $result = $this->callAPISuccessGetSingle('Contact', array('first_name' => $string));
180 $this->assertEquals($string, $result['first_name']);
181
182 $organizationParams = array(
183 'organization_name' => $string,
184 'contact_type' => 'Organization',
185 );
186
187 $this->callAPISuccess('Contact', 'create', $organizationParams);
188 $result = $this->callAPISuccessGetSingle('Contact', $organizationParams);
189 $this->assertEquals($string, $result['organization_name']);
190 }
191
192 /**
193 * Get international string data for testing against api calls.
194 */
195 public function getInternationalStrings() {
196 $invocations = array();
2fc64082 197 $invocations[] = array('Scarabée');
198 $invocations[] = array('Iñtërnâtiônàlizætiøn');
3a15378c 199 $invocations[] = array('これは日本語のテキストです。読めますか');
200 $invocations[] = array('देखें हिन्दी कैसी नजर आती है। अरे वाह ये तो नजर आती है।');
201 return $invocations;
202 }
203
b99f9616 204 /**
205 * Test civicrm_contact_create.
206 *
207 * Verify that preferred language can be set.
2d932085
CW
208 * @param int $version
209 * @dataProvider versionThreeAndFour
b99f9616 210 */
2d932085
CW
211 public function testAddCreateIndividualWithPreferredLanguage($version) {
212 $this->_apiversion = $version;
b99f9616 213 $params = array(
214 'first_name' => 'abc1',
215 'contact_type' => 'Individual',
216 'last_name' => 'xyz1',
217 'preferred_language' => 'es_ES',
218 );
219
220 $contact = $this->callAPISuccess('contact', 'create', $params);
221 $this->getAndCheck($params, $contact['id'], 'Contact');
222 }
223
6a488035 224 /**
381fa321 225 * Test civicrm_contact_create with sub-types.
6a488035 226 *
381fa321 227 * Verify that sub-types are created successfully and not deleted by subsequent updates.
2d932085
CW
228 *
229 * v3 only - uses nonstandard syntax
6a488035 230 */
00be9182 231 public function testIndividualSubType() {
6a488035
TO
232 $params = array(
233 'first_name' => 'test abc',
234 'contact_type' => 'Individual',
235 'last_name' => 'test xyz',
236 'contact_sub_type' => array('Student', 'Staff'),
5896d037 237 );
f6722559 238 $contact = $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
239 $cid = $contact['id'];
240
241 $params = array(
242 'id' => $cid,
243 'middle_name' => 'foo',
6a488035 244 );
f6722559 245 $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
246 unset($params['middle_name']);
247
f6722559 248 $contact = $this->callAPISuccess('contact', 'get', $params);
6a488035 249
fe482240 250 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
6a488035
TO
251 }
252
35fbf8a2
MM
253 /**
254 * Verify that we can retreive contacts of different sub types
2d932085
CW
255 * @param int $version
256 * @dataProvider versionThreeAndFour
35fbf8a2 257 */
2d932085
CW
258 public function testGetMultipleContactSubTypes($version) {
259 $this->_apiversion = $version;
35fbf8a2
MM
260
261 // This test presumes that there are no parents or students in the dataset
262
263 // create a student
264 $student = $this->callAPISuccess('contact', 'create', array(
265 'email' => 'student@example.com',
266 'contact_type' => 'Individual',
267 'contact_sub_type' => 'Student',
268 ));
269
270 // create a parent
271 $parent = $this->callAPISuccess('contact', 'create', array(
272 'email' => 'parent@example.com',
273 'contact_type' => 'Individual',
274 'contact_sub_type' => 'Parent',
275 ));
276
277 // create a parent
734cd0d5 278 $this->callAPISuccess('contact', 'create', array(
35fbf8a2
MM
279 'email' => 'parent@example.com',
280 'contact_type' => 'Individual',
281 ));
282
283 // get all students and parents
284 $getParams = array('contact_sub_type' => array('IN' => array('Parent', 'Student')));
285 $result = civicrm_api3('contact', 'get', $getParams);
286
287 // check that we retrieved the student and the parent
288 $this->assertArrayHasKey($student['id'], $result['values']);
289 $this->assertArrayHasKey($parent['id'], $result['values']);
290 $this->assertEquals(2, $result['count']);
291
292 }
293
6a488035 294 /**
381fa321 295 * Verify that attempt to create contact with empty params fails.
6a488035 296 */
00be9182 297 public function testCreateEmptyContact() {
f6722559 298 $this->callAPIFailure('contact', 'create', array());
6a488035
TO
299 }
300
301 /**
381fa321 302 * Verify that attempt to create contact with bad contact type fails.
6a488035 303 */
00be9182 304 public function testCreateBadTypeContact() {
6a488035
TO
305 $params = array(
306 'email' => 'man1@yahoo.com',
307 'contact_type' => 'Does not Exist',
6a488035 308 );
6c6e6187 309 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
6a488035
TO
310 }
311
312 /**
381fa321 313 * Verify that attempt to create individual contact without required fields fails.
6a488035 314 */
00be9182 315 public function testCreateBadRequiredFieldsIndividual() {
6a488035
TO
316 $params = array(
317 'middle_name' => 'This field is not required',
318 'contact_type' => 'Individual',
319 );
4b58ed3b 320 $this->callAPIFailure('contact', 'create', $params);
6a488035
TO
321 }
322
323 /**
381fa321 324 * Verify that attempt to create household contact without required fields fails.
6a488035 325 */
00be9182 326 public function testCreateBadRequiredFieldsHousehold() {
6a488035
TO
327 $params = array(
328 'middle_name' => 'This field is not required',
329 'contact_type' => 'Household',
330 );
4b58ed3b 331 $this->callAPIFailure('contact', 'create', $params);
6a488035
TO
332 }
333
334 /**
381fa321 335 * Test required field check.
336 *
337 * Verify that attempt to create organization contact without required fields fails.
6a488035 338 */
00be9182 339 public function testCreateBadRequiredFieldsOrganization() {
6a488035
TO
340 $params = array(
341 'middle_name' => 'This field is not required',
342 'contact_type' => 'Organization',
343 );
344
4b58ed3b 345 $this->callAPIFailure('contact', 'create', $params);
6a488035
TO
346 }
347
348 /**
381fa321 349 * Verify that attempt to create individual contact with only an email succeeds.
6a488035 350 */
00be9182 351 public function testCreateEmailIndividual() {
57f8e7f0 352 $primaryEmail = 'man3@yahoo.com';
353 $notPrimaryEmail = 'man4@yahoo.com';
6a488035 354 $params = array(
57f8e7f0 355 'email' => $primaryEmail,
6a488035
TO
356 'contact_type' => 'Individual',
357 'location_type_id' => 1,
6a488035
TO
358 );
359
57f8e7f0 360 $contact1 = $this->callAPISuccess('contact', 'create', $params);
361
362 $this->assertEquals(3, $contact1['id']);
363 $email1 = $this->callAPISuccess('email', 'get', array('contact_id' => $contact1['id']));
364 $this->assertEquals(1, $email1['count']);
365 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
366
367 $email2 = $this->callAPISuccess('email', 'create', array('contact_id' => $contact1['id'], 'is_primary' => 0, 'email' => $notPrimaryEmail));
368
369 // Case 1: Check with criteria primary 'email' => array('IS NOT NULL' => 1)
370 $result = $this->callAPISuccess('contact', 'get', array('email' => array('IS NOT NULL' => 1)));
371 $primaryEmailContactIds = array_keys($result['values']);
372 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
373
374 // Case 2: Check with criteria primary 'email' => array('<>' => '')
375 $result = $this->callAPISuccess('contact', 'get', array('email' => array('<>' => '')));
376 $primaryEmailContactIds = array_keys($result['values']);
377 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
f6722559 378
57f8e7f0 379 // Case 3: Check with email_id='primary email id'
380 $result = $this->callAPISuccess('contact', 'get', array('email_id' => $email1['id']));
381 $this->assertEquals(1, $result['count']);
382 $this->assertEquals($contact1['id'], $result['id']);
6a488035 383
57f8e7f0 384 $this->callAPISuccess('contact', 'delete', $contact1);
6a488035
TO
385 }
386
387 /**
381fa321 388 * Test creating individual by name.
389 *
390 * Verify create individual contact with only first and last names succeeds.
2d932085
CW
391 * @param int $version
392 * @dataProvider versionThreeAndFour
6a488035 393 */
2d932085
CW
394 public function testCreateNameIndividual($version) {
395 $this->_apiversion = $version;
6a488035
TO
396 $params = array(
397 'first_name' => 'abc1',
398 'contact_type' => 'Individual',
399 'last_name' => 'xyz1',
6a488035 400 );
6a488035 401
c8747697 402 $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
403 }
404
c10e7177 405 /**
406 * Test creating individual by display_name.
407 *
408 * Display name & sort name should be set.
2d932085
CW
409 * @param int $version
410 * @dataProvider versionThreeAndFour
c10e7177 411 */
2d932085
CW
412 public function testCreateDisplayNameIndividual($version) {
413 $this->_apiversion = $version;
c10e7177 414 $params = array(
415 'display_name' => 'abc1',
416 'contact_type' => 'Individual',
417 );
418
419 $contact = $this->callAPISuccess('contact', 'create', $params);
420 $params['sort_name'] = 'abc1';
421 $this->getAndCheck($params, $contact['id'], 'contact');
422 }
423
9436d5d5 424 /**
425 * Test that name searches are case insensitive.
2d932085
CW
426 * @param int $version
427 * @dataProvider versionThreeAndFour
9436d5d5 428 */
2d932085
CW
429 public function testGetNameVariantsCaseInsensitive($version) {
430 $this->_apiversion = $version;
9436d5d5 431 $this->callAPISuccess('contact', 'create', [
432 'display_name' => 'Abc1',
433 'contact_type' => 'Individual',
434 ]);
435 $this->callAPISuccessGetSingle('Contact', ['display_name' => 'aBc1']);
436 $this->callAPISuccessGetSingle('Contact', ['sort_name' => 'aBc1']);
437 Civi::settings()->set('includeNickNameInName', TRUE);
2d932085 438 $result = $this->callAPISuccessGetSingle('Contact', ['display_name' => 'aBc1']);
9436d5d5 439 $this->callAPISuccessGetSingle('Contact', ['sort_name' => 'aBc1']);
440 Civi::settings()->set('includeNickNameInName', FALSE);
441 }
442
6a488035 443 /**
381fa321 444 * Test old keys still work.
445 *
446 * Verify that attempt to create individual contact with
d177a2a6 447 * first and last names and old key values works
6a488035 448 */
00be9182 449 public function testCreateNameIndividualOldKeys() {
6a488035
TO
450 $params = array(
451 'individual_prefix' => 'Dr.',
452 'first_name' => 'abc1',
453 'contact_type' => 'Individual',
454 'last_name' => 'xyz1',
455 'individual_suffix' => 'Jr.',
6a488035
TO
456 );
457
f6722559 458 $contact = $this->callAPISuccess('contact', 'create', $params);
6ecbca5b 459 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
fd651abc 460
a1255c80
CW
461 $this->assertArrayKeyExists('prefix_id', $result);
462 $this->assertArrayKeyExists('suffix_id', $result);
463 $this->assertArrayKeyExists('gender_id', $result);
464 $this->assertEquals(4, $result['prefix_id']);
465 $this->assertEquals(1, $result['suffix_id']);
6a488035
TO
466 }
467
468 /**
381fa321 469 * Test preferred keys work.
470 *
471 * Verify that attempt to create individual contact with
d177a2a6 472 * first and last names and old key values works
6a488035 473 */
381fa321 474 public function testCreateNameIndividualRecommendedKeys2() {
6a488035
TO
475 $params = array(
476 'prefix_id' => 'Dr.',
477 'first_name' => 'abc1',
478 'contact_type' => 'Individual',
479 'last_name' => 'xyz1',
480 'suffix_id' => 'Jr.',
481 'gender_id' => 'Male',
6a488035
TO
482 );
483
f6722559 484 $contact = $this->callAPISuccess('contact', 'create', $params);
6ecbca5b 485 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
fd651abc 486
a1255c80
CW
487 $this->assertArrayKeyExists('prefix_id', $result);
488 $this->assertArrayKeyExists('suffix_id', $result);
489 $this->assertArrayKeyExists('gender_id', $result);
490 $this->assertEquals(4, $result['prefix_id']);
491 $this->assertEquals(1, $result['suffix_id']);
6a488035
TO
492 }
493
494 /**
381fa321 495 * Test household name is sufficient for create.
496 *
497 * Verify that attempt to create household contact with only
d177a2a6 498 * household name succeeds
2d932085
CW
499 * @param int $version
500 * @dataProvider versionThreeAndFour
6a488035 501 */
2d932085
CW
502 public function testCreateNameHousehold($version) {
503 $this->_apiversion = $version;
6a488035
TO
504 $params = array(
505 'household_name' => 'The abc Household',
506 'contact_type' => 'Household',
6a488035 507 );
c8747697 508 $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
509 }
510
511 /**
381fa321 512 * Test organization name is sufficient for create.
513 *
514 * Verify that attempt to create organization contact with only
d177a2a6 515 * organization name succeeds.
2d932085
CW
516 * @param int $version
517 * @dataProvider versionThreeAndFour
6a488035 518 */
2d932085
CW
519 public function testCreateNameOrganization($version) {
520 $this->_apiversion = $version;
6a488035
TO
521 $params = array(
522 'organization_name' => 'The abc Organization',
523 'contact_type' => 'Organization',
6a488035 524 );
c8747697 525 $this->callAPISuccess('contact', 'create', $params);
6a488035 526 }
5896d037 527
6a488035 528 /**
381fa321 529 * Verify that attempt to create organization contact without organization name fails.
6a488035 530 */
00be9182 531 public function testCreateNoNameOrganization() {
6a488035
TO
532 $params = array(
533 'first_name' => 'The abc Organization',
534 'contact_type' => 'Organization',
6a488035 535 );
4b58ed3b 536 $this->callAPIFailure('contact', 'create', $params);
6a488035 537 }
5896d037 538
ea33395c
TO
539 /**
540 * Check that permissions on API key are restricted (CRM-18112).
2d932085
CW
541 *
542 * @param int $version
543 * @dataProvider versionThreeAndFour
ea33395c 544 */
2d932085
CW
545 public function testCreateApiKey($version) {
546 $this->_apiversion = $version;
ea33395c
TO
547 $config = CRM_Core_Config::singleton();
548 $contactId = $this->individualCreate(array(
549 'first_name' => 'A',
550 'last_name' => 'B',
551 ));
552
553 // Allow edit -- because permissions aren't being checked
554 $config->userPermissionClass->permissions = array();
555 $result = $this->callAPISuccess('Contact', 'create', array(
556 'id' => $contactId,
557 'api_key' => 'original',
558 ));
559 $this->assertEquals('original', $result['values'][$contactId]['api_key']);
560
561 // Allow edit -- because we have adequate permission
562 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts', 'edit api keys');
563 $result = $this->callAPISuccess('Contact', 'create', array(
564 'check_permissions' => 1,
565 'id' => $contactId,
566 'api_key' => 'abcd1234',
567 ));
568 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
569
570 // Disallow edit -- because we don't have permission
571 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts');
572 $result = $this->callAPIFailure('Contact', 'create', array(
573 'check_permissions' => 1,
574 'id' => $contactId,
575 'api_key' => 'defg4321',
576 ));
577 $this->assertRegExp(';Permission denied to modify api key;', $result['error_message']);
578
579 // Return everything -- because permissions are not being checked
580 $config->userPermissionClass->permissions = array();
581 $result = $this->callAPISuccess('Contact', 'create', array(
582 'id' => $contactId,
583 'first_name' => 'A2',
584 ));
585 $this->assertEquals('A2', $result['values'][$contactId]['first_name']);
586 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
587 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
588
589 // Return everything -- because we have adequate permission
590 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts', 'edit api keys');
591 $result = $this->callAPISuccess('Contact', 'create', array(
592 'check_permissions' => 1,
593 'id' => $contactId,
594 'first_name' => 'A3',
595 ));
596 $this->assertEquals('A3', $result['values'][$contactId]['first_name']);
597 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
598 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
599
600 // Restricted return -- because we don't have permission
601 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts');
602 $result = $this->callAPISuccess('Contact', 'create', array(
603 'check_permissions' => 1,
604 'id' => $contactId,
605 'first_name' => 'A4',
606 ));
607 $this->assertEquals('A4', $result['values'][$contactId]['first_name']);
608 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
609 $this->assertTrue(empty($result['values'][$contactId]['api_key']));
610 }
611
6a488035 612 /**
381fa321 613 * Check with complete array + custom field.
614 *
6a488035
TO
615 * Note that the test is written on purpose without any
616 * variables specific to participant so it can be replicated into other entities
617 * and / or moved to the automated test suite
2d932085
CW
618 * @param int $version
619 * @dataProvider versionThreeAndFour
6a488035 620 */
2d932085
CW
621 public function testCreateWithCustom($version) {
622 $this->_apiversion = $version;
6a488035
TO
623 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
624
625 $params = $this->_params;
626 $params['custom_' . $ids['custom_field_id']] = "custom string";
5c49fee0 627 $description = "This demonstrates setting a custom field through the API.";
fb32de45 628 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, $description);
6a488035 629
5896d037 630 $check = $this->callAPISuccess($this->_entity, 'get', array(
92915c55
TO
631 'return.custom_' . $ids['custom_field_id'] => 1,
632 'id' => $result['id'],
633 ));
4b58ed3b 634 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
6a488035
TO
635
636 $this->customFieldDelete($ids['custom_field_id']);
637 $this->customGroupDelete($ids['custom_group_id']);
638 }
639
fe6daa04 640 /**
381fa321 641 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
fe6daa04 642 */
00be9182 643 public function testCreateWithNULLCustomCRM12773() {
fe6daa04 644 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
645 $params = $this->_params;
646 $params['custom_' . $ids['custom_field_id']] = NULL;
4b58ed3b 647 $this->callAPISuccess('contact', 'create', $params);
fe6daa04 648 $this->customFieldDelete($ids['custom_field_id']);
649 $this->customGroupDelete($ids['custom_group_id']);
650 }
651
9747df8a 652 /**
653 * CRM-14232 test preferred language set to site default if not passed.
2d932085
CW
654 * @param int $version
655 * @dataProvider versionThreeAndFour
9747df8a 656 */
2d932085
CW
657 public function testCreatePreferredLanguageUnset($version) {
658 $this->_apiversion = $version;
9747df8a 659 $this->callAPISuccess('Contact', 'create', array(
660 'first_name' => 'Snoop',
661 'last_name' => 'Dog',
39b959db
SL
662 'contact_type' => 'Individual',
663 ));
9747df8a 664 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
665 $this->assertEquals('en_US', $result['preferred_language']);
666 }
667
668 /**
669 * CRM-14232 test preferred language returns setting if not passed.
2d932085
CW
670 * @param int $version
671 * @dataProvider versionThreeAndFour
9747df8a 672 */
2d932085
CW
673 public function testCreatePreferredLanguageSet($version) {
674 $this->_apiversion = $version;
9747df8a 675 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'fr_FR'));
676 $this->callAPISuccess('Contact', 'create', array(
677 'first_name' => 'Snoop',
678 'last_name' => 'Dog',
679 'contact_type' => 'Individual',
680 ));
681 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
682 $this->assertEquals('fr_FR', $result['preferred_language']);
683 }
684
685 /**
686 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
2d932085 687 * TODO: Api4
9747df8a 688 */
689 public function testCreatePreferredLanguageNull() {
690 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
691 $this->callAPISuccess('Contact', 'create', array(
39b959db
SL
692 'first_name' => 'Snoop',
693 'last_name' => 'Dog',
694 'contact_type' => 'Individual',
695 ));
9747df8a 696 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
697 $this->assertEquals(NULL, $result['preferred_language']);
698 }
699
700 /**
701 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
2d932085
CW
702 * @param int $version
703 * @dataProvider versionThreeAndFour
9747df8a 704 */
2d932085
CW
705 public function testCreatePreferredLanguagePassed($version) {
706 $this->_apiversion = $version;
9747df8a 707 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
708 $this->callAPISuccess('Contact', 'create', array(
709 'first_name' => 'Snoop',
710 'last_name' => 'Dog',
711 'contact_type' => 'Individual',
712 'preferred_language' => 'en_AU',
713 ));
714 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
715 $this->assertEquals('en_AU', $result['preferred_language']);
716 }
717
2930d67a 718 /**
719 * CRM-15792 - create/update datetime field for contact.
720 */
721 public function testCreateContactCustomFldDateTime() {
722 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
723 $dateTime = CRM_Utils_Date::currentDBDate();
724 //check date custom field is saved along with time when time_format is set
725 $params = array(
726 'first_name' => 'abc3',
727 'last_name' => 'xyz3',
728 'contact_type' => 'Individual',
729 'email' => 'man3@yahoo.com',
730 'api.CustomField.create' => array(
731 'custom_group_id' => $customGroup['id'],
732 'name' => 'test_datetime',
733 'label' => 'Demo Date',
734 'html_type' => 'Select Date',
735 'data_type' => 'Date',
736 'time_format' => 2,
737 'weight' => 4,
738 'is_required' => 1,
739 'is_searchable' => 0,
740 'is_active' => 1,
741 ),
742 );
743
3c27d467 744 $result = $this->callAPISuccess('Contact', 'create', $params);
2930d67a 745 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
ba4a1892 746 $this->assertNotNull($result['id']);
a15773db 747 $this->assertNotNull($customFldId);
2930d67a 748
749 $params = array(
750 'id' => $result['id'],
751 "custom_{$customFldId}" => $dateTime,
752 'api.CustomValue.get' => 1,
753 );
754
3c27d467 755 $result = $this->callAPISuccess('Contact', 'create', $params);
ba4a1892 756 $this->assertNotNull($result['id']);
2930d67a 757 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
a15773db 758 $this->assertNotNull($customFldDate);
2930d67a 759 $this->assertEquals($dateTime, $customFldDate);
760 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
761 $dateTime = date('Ymd');
762 //date custom field should not contain time part when time_format is null
763 $params = array(
764 'id' => $result['id'],
765 'api.CustomField.create' => array(
41755648 766 'id' => $customFldId,
2930d67a 767 'html_type' => 'Select Date',
768 'data_type' => 'Date',
769 'time_format' => '',
770 ),
771 'api.CustomValue.create' => array(
772 'id' => $customValueId,
773 'entity_id' => $result['id'],
774 "custom_{$customFldId}" => $dateTime,
775 ),
776 'api.CustomValue.get' => 1,
777 );
3c27d467 778 $result = $this->callAPISuccess('Contact', 'create', $params);
ba4a1892 779 $this->assertNotNull($result['id']);
2930d67a 780 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
781 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
a15773db 782 $this->assertNotNull($customFldDate);
2930d67a 783 $this->assertEquals($dateTime, $customFldDate);
784 $this->assertEquals(000000, $customFldTime);
3c27d467 785 $this->callAPISuccess('Contact', 'create', $params);
2930d67a 786 }
787
d424ffde 788 /**
381fa321 789 * Test creating a current employer through API.
6a488035 790 */
5896d037 791 public function testContactCreateCurrentEmployer() {
381fa321 792 // Here we will just do the get for set-up purposes.
f6722559 793 $count = $this->callAPISuccess('contact', 'getcount', array(
6a488035 794 'organization_name' => 'new employer org',
21dfd5f5 795 'contact_type' => 'Organization',
6a488035
TO
796 ));
797 $this->assertEquals(0, $count);
f6722559 798 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
39b959db
SL
799 'current_employer' => 'new employer org',
800 )));
bb043d6f
E
801 // do it again as an update to check it doesn't cause an error
802 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
39b959db
SL
803 'current_employer' => 'new employer org',
804 'id' => $employerResult['id'],
805 )));
f6722559 806 $expectedCount = 1;
4b58ed3b 807 $this->callAPISuccess('contact', 'getcount', array(
39b959db
SL
808 'organization_name' => 'new employer org',
809 'contact_type' => 'Organization',
810 ), $expectedCount);
6a488035 811
f6722559 812 $result = $this->callAPISuccess('contact', 'getsingle', array(
6a488035
TO
813 'id' => $employerResult['id'],
814 ));
815
816 $this->assertEquals('new employer org', $result['current_employer']);
817
818 }
5896d037 819
d424ffde 820 /**
381fa321 821 * Test creating a current employer through API.
822 *
823 * Check it will re-activate a de-activated employer
d424ffde 824 */
5896d037 825 public function testContactCreateDuplicateCurrentEmployerEnables() {
381fa321 826 // Set up - create employer relationship.
bb043d6f 827 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
39b959db
SL
828 'current_employer' => 'new employer org',
829 )
bb043d6f 830 ));
6c6e6187 831 $relationship = $this->callAPISuccess('relationship', 'get', array(
bb043d6f 832 'contact_id_a' => $employerResult['id'],
6c6e6187 833 ));
bb043d6f
E
834
835 //disable & check it is disabled
836 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
6c6e6187 837 $this->callAPISuccess('relationship', 'getvalue', array(
bb043d6f 838 'id' => $relationship['id'],
21dfd5f5 839 'return' => 'is_active',
bb043d6f
E
840 ), 0);
841
381fa321 842 // Re-set the current employer - thus enabling the relationship.
4b58ed3b 843 $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
39b959db
SL
844 'current_employer' => 'new employer org',
845 'id' => $employerResult['id'],
846 )
bb043d6f
E
847 ));
848 //check is_active is now 1
6c6e6187 849 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
5896d037
TO
850 'return' => 'is_active',
851 ));
6c6e6187 852 $this->assertEquals(1, $relationship['is_active']);
bb043d6f
E
853 }
854
8f32b005 855 /**
381fa321 856 * Check deceased contacts are not retrieved.
857 *
858 * Note at time of writing the default is to return default. This should possibly be changed & test added.
2d932085
CW
859 * @param int $version
860 * @dataProvider versionThreeAndFour
8f32b005 861 */
2d932085
CW
862 public function testGetDeceasedRetrieved($version) {
863 $this->_apiversion = $version;
4b58ed3b 864 $this->callAPISuccess($this->_entity, 'create', $this->_params);
5896d037 865 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
92915c55
TO
866 'first_name' => 'bb',
867 'last_name' => 'ccc',
868 'contact_type' => 'Individual',
869 'is_deceased' => 1,
870 ));
8f32b005 871 $result = $this->callAPISuccess($this->_entity, 'get', array('is_deceased' => 0));
872 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
873 }
6a488035 874
c490a46a 875 /**
381fa321 876 * Test that sort works - old syntax.
c490a46a 877 */
00be9182 878 public function testGetSort() {
f6722559 879 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
5896d037 880 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
92915c55
TO
881 'first_name' => 'bb',
882 'last_name' => 'ccc',
883 'contact_type' => 'Individual',
884 ));
5896d037
TO
885 $result = $this->callAPISuccess($this->_entity, 'get', array(
886 'sort' => 'first_name ASC',
887 'return.first_name' => 1,
888 'sequential' => 1,
889 'rowCount' => 1,
c8747697 890 'contact_type' => 'Individual',
5896d037 891 ));
6a488035
TO
892
893 $this->assertEquals('abc1', $result['values'][0]['first_name']);
f6722559 894 $result = $this->callAPISuccess($this->_entity, 'get', array(
895 'sort' => 'first_name DESC',
896 'return.first_name' => 1,
897 'sequential' => 1,
898 'rowCount' => 1,
899 ));
6a488035
TO
900 $this->assertEquals('bb', $result['values'][0]['first_name']);
901
f6722559 902 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
903 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
6a488035 904 }
5896d037 905
d424ffde 906 /**
381fa321 907 * Test that we can retrieve contacts using array syntax.
908 *
909 * I.e 'id' => array('IN' => array('3,4')).
2d932085
CW
910 * @param int $version
911 * @dataProvider versionThreeAndFour
d424ffde 912 */
2d932085
CW
913 public function testGetINIDArray($version) {
914 $this->_apiversion = $version;
78c0bfc0 915 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
5896d037 916 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
92915c55
TO
917 'first_name' => 'bb',
918 'last_name' => 'ccc',
919 'contact_type' => 'Individual',
920 ));
5896d037 921 $c3 = $this->callAPISuccess($this->_entity, 'create', array(
92915c55
TO
922 'first_name' => 'hh',
923 'last_name' => 'll',
924 'contact_type' => 'Individual',
925 ));
78c0bfc0 926 $result = $this->callAPISuccess($this->_entity, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
927 $this->assertEquals(2, $result['count']);
928 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
929 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
930 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
931 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c3['id']));
932 }
5896d037 933
d424ffde 934 /**
381fa321 935 * Test variants on deleted behaviour.
6a488035 936 */
00be9182 937 public function testGetDeleted() {
6a488035 938 $params = $this->_params;
f6722559 939 $contact1 = $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
940 $params['is_deleted'] = 1;
941 $params['last_name'] = 'bcd';
f6722559 942 $contact2 = $this->callAPISuccess('contact', 'create', $params);
c8747697 943 $countActive = $this->callAPISuccess('contact', 'getcount', array(
944 'showAll' => 'active',
945 'contact_type' => 'Individual',
946 ));
947 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all', 'contact_type' => 'Individual'));
948 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash', 'contact_type' => 'Individual'));
949 $countDefault = $this->callAPISuccess('contact', 'getcount', array('contact_type' => 'Individual'));
f6722559 950 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
c8747697 951 'contact_type' => 'Individual',
f6722559 952 'contact_is_deleted' => 1,
5896d037 953 ));
f6722559 954 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
955 'contact_is_deleted' => 0,
c8747697 956 'contact_type' => 'Individual',
5896d037 957 ));
f6722559 958 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
959 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
c8747697 960 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected');
fe482240
EM
961 $this->assertEquals(1, $countActive);
962 $this->assertEquals(1, $countTrash);
963 $this->assertEquals(2, $countAll);
964 $this->assertEquals(1, $countDeleted);
c8747697 965 $this->assertEquals(1, $countDefault, 'Only active by default in line');
6a488035 966 }
c490a46a
CW
967
968 /**
381fa321 969 * Test that sort works - new syntax.
2d932085
CW
970 * @param int $version
971 * @dataProvider versionThreeAndFour
c490a46a 972 */
2d932085
CW
973 public function testGetSortNewSyntax($version) {
974 $this->_apiversion = $version;
5896d037
TO
975 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
976 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
92915c55
TO
977 'first_name' => 'bb',
978 'last_name' => 'ccc',
979 'contact_type' => 'Individual',
980 ));
f6722559 981 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
6a488035 982 'return' => 'first_name',
c8747697 983 'contact_type' => 'Individual',
5896d037
TO
984 'options' => array(
985 'limit' => 1,
986 'sort' => 'first_name',
987 ),
988 ));
c8747697 989 $this->assertEquals('abc1', $result);
6a488035 990
f6722559 991 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
5896d037 992 'return' => 'first_name',
c8747697 993 'contact_type' => 'Individual',
5896d037
TO
994 'options' => array(
995 'limit' => 1,
996 'sort' => 'first_name DESC',
997 ),
998 ));
6a488035
TO
999 $this->assertEquals('bb', $result);
1000
f6722559 1001 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
1002 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
6a488035 1003 }
c490a46a 1004
c4bc3d5a
JV
1005 /**
1006 * Test sort and limit for chained relationship get.
1007 *
1008 * https://issues.civicrm.org/jira/browse/CRM-15983
2d932085
CW
1009 * @param int $version
1010 * @dataProvider versionThreeAndFour
c4bc3d5a 1011 */
2d932085
CW
1012 public function testSortLimitChainedRelationshipGetCRM15983($version) {
1013 $this->_apiversion = $version;
c4bc3d5a
JV
1014 // Some contact
1015 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1016 'first_name' => 'Jules',
1017 'last_name' => 'Smos',
1018 'contact_type' => 'Individual',
1019 ));
1020
1021 // Create another contact with two relationships.
1022 $create_params = array(
1023 'first_name' => 'Jos',
1024 'last_name' => 'Smos',
1025 'contact_type' => 'Individual',
1026 'api.relationship.create' => array(
1027 array(
1028 'contact_id_a' => '$value.id',
1029 'contact_id_b' => $create_result_1['id'],
1030 // spouse of:
1031 'relationship_type_id' => 2,
1032 'start_date' => '2005-01-12',
1033 'end_date' => '2006-01-11',
1034 'description' => 'old',
1035 ),
1036 array(
1037 'contact_id_a' => '$value.id',
1038 'contact_id_b' => $create_result_1['id'],
1039 // spouse of (was married twice :))
1040 'relationship_type_id' => 2,
1041 'start_date' => '2006-07-01',
1042 'end_date' => '2010-07-01',
1043 'description' => 'new',
1044 ),
1045 ),
1046 );
1047 $create_result = $this->callAPISuccess('contact', 'create', $create_params);
1048
1049 // Try to retrieve the contact and the most recent relationship.
1050 $get_params = array(
1051 'sequential' => 1,
1052 'id' => $create_result['id'],
1053 'api.relationship.get' => array(
1054 'contact_id_a' => '$value.id',
1055 'options' => array(
1056 'limit' => '1',
1057 'sort' => 'start_date DESC',
39b959db
SL
1058 ),
1059 ),
c4bc3d5a
JV
1060 );
1061 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1062
1063 // Clean up.
1064 $this->callAPISuccess('contact', 'delete', array(
1065 'id' => $create_result['id'],
1066 ));
1067
1068 // Assert.
1069 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1070 $this->assertEquals('new', $get_result['api.relationship.get']['values'][0]['description']);
1071 }
1072
c490a46a 1073 /**
381fa321 1074 * Test apostrophe works in get & create.
2d932085
CW
1075 * @param int $version
1076 * @dataProvider versionThreeAndFour
6a488035 1077 */
2d932085
CW
1078 public function testGetApostropheCRM10857($version) {
1079 $this->_apiversion = $version;
6a488035 1080 $params = array_merge($this->_params, array('last_name' => "O'Connor"));
4b58ed3b 1081 $this->callAPISuccess($this->_entity, 'create', $params);
f6722559 1082 $result = $this->callAPISuccess($this->_entity, 'getsingle', array(
6a488035
TO
1083 'last_name' => "O'Connor",
1084 'sequential' => 1,
1085 ));
d03a02d9 1086 $this->assertEquals("O'Connor", $result['last_name']);
1087 }
1088
1089 /**
1090 * Test between accepts zero.
1091 *
1092 * In the past it incorrectly required !empty.
2d932085
CW
1093 * @param int $version
1094 * @dataProvider versionThreeAndFour
d03a02d9 1095 */
2d932085
CW
1096 public function testGetBetweenZeroWorks($version) {
1097 $this->_apiversion = $version;
d03a02d9 1098 $this->callAPISuccess($this->_entity, 'get', [
1099 'contact_id' => ['BETWEEN' => [0, 9]],
1100 ]);
1101 $this->callAPISuccess($this->_entity, 'get', [
1102 'contact_id' => [
1103 'BETWEEN' => [
1104 (0 - 9),
1105 0,
1106 ],
1107 ],
1108 ]);
6a488035
TO
1109 }
1110
54e389ac 1111 /**
1112 * Test retrieval by addressee id.
2d932085 1113 * V3 only - the "skip_greeting_processing" param is not currently in v4
54e389ac 1114 */
1115 public function testGetByAddresseeID() {
1116 $individual1ID = $this->individualCreate([
1117 'skip_greeting_processing' => 1,
1118 'addressee_id' => 'null',
1119 'email_greeting_id' => 'null',
39b959db 1120 'postal_greeting_id' => 'null',
54e389ac 1121 ]);
1122 $individual2ID = $this->individualCreate();
1123
1124 $this->assertEquals($individual1ID,
1125 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['IS NULL' => 1], 'return' => 'id'])
1126 );
1127 $this->assertEquals($individual1ID,
1128 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'email_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1129 );
1130 $this->assertEquals($individual1ID,
1131 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'postal_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1132 );
1133
1134 $this->assertEquals($individual2ID,
1135 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['NOT NULL' => 1], 'return' => 'id'])
1136 );
1137 }
1138
6a488035 1139 /**
381fa321 1140 * Check with complete array + custom field.
1141 *
6a488035
TO
1142 * Note that the test is written on purpose without any
1143 * variables specific to participant so it can be replicated into other entities
1144 * and / or moved to the automated test suite
1145 */
00be9182 1146 public function testGetWithCustom() {
6a488035
TO
1147 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1148
1149 $params = $this->_params;
1150 $params['custom_' . $ids['custom_field_id']] = "custom string";
5c49fee0 1151 $description = "This demonstrates setting a custom field through the API.";
6a488035 1152 $subfile = "CustomFieldGet";
f6722559 1153 $result = $this->callAPISuccess($this->_entity, 'create', $params);
6a488035 1154
5896d037 1155 $check = $this->callAPIAndDocument($this->_entity, 'get', array(
92915c55
TO
1156 'return.custom_' . $ids['custom_field_id'] => 1,
1157 'id' => $result['id'],
1158 ), __FUNCTION__, __FILE__, $description, $subfile);
6a488035 1159
4b58ed3b 1160 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
f6722559 1161 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
6a488035
TO
1162 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
1163 $this->customFieldDelete($ids['custom_field_id']);
1164 $this->customGroupDelete($ids['custom_group_id']);
1165 }
c490a46a 1166
697aad03 1167 /**
1168 * Tests that using 'return' with a custom field not of type contact does not inappropriately filter.
1169 *
1170 * https://lab.civicrm.org/dev/core/issues/1025
1171 *
1172 * @throws \CRM_Core_Exception
1173 */
1174 public function testGetWithCustomOfActivityType() {
1175 $this->createCustomGroupWithFieldOfType(['extends' => 'Activity']);
1176 $this->createCustomGroupWithFieldOfType(['extends' => 'Contact'], 'text', 'contact_');
1177 $contactID = $this->individualCreate();
1178 $this->callAPISuccessGetSingle('Contact', ['id' => $contactID, 'return' => ['external_identifier', $this->getCustomFieldName('contact_text')]]);
1179 }
1180
c490a46a 1181 /**
381fa321 1182 * Check with complete array + custom field.
1183 *
c490a46a
CW
1184 * Note that the test is written on purpose without any
1185 * variables specific to participant so it can be replicated into other entities
1186 * and / or moved to the automated test suite
1187 */
00be9182 1188 public function testGetWithCustomReturnSyntax() {
6a488035
TO
1189 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1190
1191 $params = $this->_params;
1192 $params['custom_' . $ids['custom_field_id']] = "custom string";
5c49fee0 1193 $description = "This demonstrates setting a custom field through the API.";
6a488035 1194 $subfile = "CustomFieldGetReturnSyntaxVariation";
f6722559 1195 $result = $this->callAPISuccess($this->_entity, 'create', $params);
1196 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
1197 $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
6a488035 1198
43ef1263 1199 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
6a488035
TO
1200 $this->customFieldDelete($ids['custom_field_id']);
1201 $this->customGroupDelete($ids['custom_group_id']);
1202 }
1203
43ef1263 1204 /**
66670e4d 1205 * Check that address name, ID is returned if required.
43ef1263 1206 */
66670e4d 1207 public function testGetReturnAddress() {
43ef1263 1208 $contactID = $this->individualCreate();
66670e4d 1209 $result = $this->callAPISuccess('address', 'create', array(
92915c55
TO
1210 'contact_id' => $contactID,
1211 'address_name' => 'My house',
1212 'location_type_id' => 'Home',
1213 'street_address' => '1 my road',
1214 ));
66670e4d 1215 $addressID = $result['id'];
1216
5896d037 1217 $result = $this->callAPISuccessGetSingle('contact', array(
66670e4d 1218 'return' => 'address_name, street_address, address_id',
92915c55
TO
1219 'id' => $contactID,
1220 ));
66670e4d 1221 $this->assertEquals($addressID, $result['address_id']);
43ef1263
EM
1222 $this->assertEquals('1 my road', $result['street_address']);
1223 $this->assertEquals('My house', $result['address_name']);
1224
1225 }
1226
701a69da 1227 /**
1228 * Test group filter syntaxes.
1229 */
00be9182 1230 public function testGetGroupIDFromContact() {
5896d037 1231 $groupId = $this->groupCreate();
5896d037 1232 $params = array(
6a488035
TO
1233 'email' => 'man2@yahoo.com',
1234 'contact_type' => 'Individual',
1235 'location_type_id' => 1,
6a488035
TO
1236 'api.group_contact.create' => array('group_id' => $groupId),
1237 );
1238
4b58ed3b 1239 $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
1240 // testing as integer
1241 $params = array(
d0aa0e47 1242 'filter.group_id' => $groupId,
6a488035
TO
1243 'contact_type' => 'Individual',
1244 );
d0aa0e47 1245 $result = $this->callAPISuccess('contact', 'get', $params);
6a488035
TO
1246 $this->assertEquals(1, $result['count']);
1247 // group 26 doesn't exist, but we can still search contacts in it.
1248 $params = array(
d0aa0e47 1249 'filter.group_id' => 26,
6a488035
TO
1250 'contact_type' => 'Individual',
1251 );
4b58ed3b 1252 $this->callAPISuccess('contact', 'get', $params);
6a488035
TO
1253 // testing as string
1254 $params = array(
d0aa0e47 1255 'filter.group_id' => "$groupId, 26",
6a488035
TO
1256 'contact_type' => 'Individual',
1257 );
d0aa0e47 1258 $result = $this->callAPISuccess('contact', 'get', $params);
6a488035
TO
1259 $this->assertEquals(1, $result['count']);
1260 $params = array(
d0aa0e47 1261 'filter.group_id' => "26,27",
6a488035
TO
1262 'contact_type' => 'Individual',
1263 );
4b58ed3b 1264 $this->callAPISuccess('contact', 'get', $params);
6a488035
TO
1265
1266 // testing as string
6c6e6187 1267 $params = array(
d0aa0e47 1268 'filter.group_id' => array($groupId, 26),
6a488035
TO
1269 'contact_type' => 'Individual',
1270 );
d0aa0e47 1271 $result = $this->callAPISuccess('contact', 'get', $params);
6a488035
TO
1272 $this->assertEquals(1, $result['count']);
1273
1274 //test in conjunction with other criteria
6c6e6187 1275 $params = array(
d0aa0e47 1276 'filter.group_id' => array($groupId, 26),
6a488035
TO
1277 'contact_type' => 'Organization',
1278 );
6c6e6187
TO
1279 $this->callAPISuccess('contact', 'get', $params);
1280 $params = array(
d0aa0e47 1281 'filter.group_id' => array(26, 27),
6a488035
TO
1282 'contact_type' => 'Individual',
1283 );
f6722559 1284 $result = $this->callAPISuccess('contact', 'get', $params);
4b58ed3b 1285 $this->assertEquals(0, $result['count']);
6a488035
TO
1286 }
1287
1288 /**
381fa321 1289 * Verify that attempt to create individual contact with two chained websites succeeds.
6a488035 1290 */
00be9182 1291 public function testCreateIndividualWithContributionDottedSyntax() {
5c49fee0 1292 $description = "This demonstrates the syntax to create 2 chained entities.";
5896d037
TO
1293 $subFile = "ChainTwoWebsites";
1294 $params = array(
6a488035
TO
1295 'first_name' => 'abc3',
1296 'last_name' => 'xyz3',
1297 'contact_type' => 'Individual',
1298 'email' => 'man3@yahoo.com',
6a488035
TO
1299 'api.contribution.create' => array(
1300 'receive_date' => '2010-01-01',
1301 'total_amount' => 100.00,
5896d037 1302 'financial_type_id' => $this->_financialTypeId,
6a488035
TO
1303 'payment_instrument_id' => 1,
1304 'non_deductible_amount' => 10.00,
1305 'fee_amount' => 50.00,
1306 'net_amount' => 90.00,
1307 'trxn_id' => 15345,
1308 'invoice_id' => 67990,
1309 'source' => 'SSF',
1310 'contribution_status_id' => 1,
25ac4ffa 1311 'skipCleanMoney' => 1,
6a488035
TO
1312 ),
1313 'api.website.create' => array(
1314 'url' => "http://civicrm.org",
1315 ),
1316 'api.website.create.2' => array(
1317 'url' => "http://chained.org",
1318 ),
1319 );
1320
4b58ed3b 1321 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subFile);
6a488035 1322
f6722559 1323 // checking child function result not covered in callAPIAndDocument
1324 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
fe482240
EM
1325 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
1326 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
6a488035
TO
1327
1328 // delete the contact
f6722559 1329 $this->callAPISuccess('contact', 'delete', $result);
6a488035
TO
1330 }
1331
1332 /**
381fa321 1333 * Verify that attempt to create individual contact with chained contribution and website succeeds.
6a488035 1334 */
00be9182 1335 public function testCreateIndividualWithContributionChainedArrays() {
6a488035
TO
1336 $params = array(
1337 'first_name' => 'abc3',
1338 'last_name' => 'xyz3',
1339 'contact_type' => 'Individual',
1340 'email' => 'man3@yahoo.com',
6a488035
TO
1341 'api.contribution.create' => array(
1342 'receive_date' => '2010-01-01',
1343 'total_amount' => 100.00,
5896d037 1344 'financial_type_id' => $this->_financialTypeId,
6a488035
TO
1345 'payment_instrument_id' => 1,
1346 'non_deductible_amount' => 10.00,
1347 'fee_amount' => 50.00,
1348 'net_amount' => 90.00,
1349 'trxn_id' => 12345,
1350 'invoice_id' => 67890,
1351 'source' => 'SSF',
1352 'contribution_status_id' => 1,
25ac4ffa 1353 'skipCleanMoney' => 1,
6a488035
TO
1354 ),
1355 'api.website.create' => array(
1356 array(
1357 'url' => "http://civicrm.org",
1358 ),
1359 array(
1360 'url' => "http://chained.org",
1361 'website_type_id' => 2,
1362 ),
1363 ),
1364 );
1365
5c49fee0 1366 $description = "Demonstrates creating two websites as an array.";
5896d037
TO
1367 $subfile = "ChainTwoWebsitesSyntax2";
1368 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
f6722559 1369
f6722559 1370 // the callAndDocument doesn't check the chained call
fe482240
EM
1371 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
1372 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
1373 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
6a488035 1374
f6722559 1375 $this->callAPISuccess('contact', 'delete', $result);
6a488035
TO
1376 }
1377
92d270fd
JV
1378 /**
1379 * Test for direction when chaining relationships.
1380 *
1381 * https://issues.civicrm.org/jira/browse/CRM-16084
2d932085
CW
1382 * @param int $version
1383 * @dataProvider versionThreeAndFour
92d270fd 1384 */
2d932085
CW
1385 public function testDirectionChainingRelationshipsCRM16084($version) {
1386 $this->_apiversion = $version;
92d270fd
JV
1387 // Some contact, called Jules.
1388 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1389 'first_name' => 'Jules',
1390 'last_name' => 'Smos',
1391 'contact_type' => 'Individual',
1392 ));
1393
1394 // Another contact: Jos, child of Jules.
1395 $create_params = array(
1396 'first_name' => 'Jos',
1397 'last_name' => 'Smos',
1398 'contact_type' => 'Individual',
1399 'api.relationship.create' => array(
1400 array(
1401 'contact_id_a' => '$value.id',
1402 'contact_id_b' => $create_result_1['id'],
1403 // child of
1404 'relationship_type_id' => 1,
1405 ),
1406 ),
1407 );
1408 $create_result_2 = $this->callAPISuccess('contact', 'create', $create_params);
1409
1410 // Mia is the child of Jos.
1411 $create_params = array(
1412 'first_name' => 'Mia',
1413 'last_name' => 'Smos',
1414 'contact_type' => 'Individual',
1415 'api.relationship.create' => array(
1416 array(
1417 'contact_id_a' => '$value.id',
1418 'contact_id_b' => $create_result_2['id'],
1419 // child of
1420 'relationship_type_id' => 1,
1421 ),
1422 ),
1423 );
1424 $create_result_3 = $this->callAPISuccess('contact', 'create', $create_params);
1425
1426 // Get Jos and his children.
1427 $get_params = array(
1428 'sequential' => 1,
1429 'id' => $create_result_2['id'],
1430 'api.relationship.get' => array(
1431 'contact_id_b' => '$value.id',
1432 'relationship_type_id' => 1,
1433 ),
1434 );
1435 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1436
1437 // Clean up first.
1438 $this->callAPISuccess('contact', 'delete', array(
1439 'id' => $create_result_1['id'],
39b959db 1440 ));
92d270fd
JV
1441 $this->callAPISuccess('contact', 'delete', array(
1442 'id' => $create_result_2['id'],
39b959db 1443 ));
92d270fd
JV
1444
1445 // Assert.
1446 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1447 $this->assertEquals($create_result_3['id'], $get_result['api.relationship.get']['values'][0]['contact_id_a']);
1448 }
1449
6a488035 1450 /**
fe482240 1451 * Verify that attempt to create individual contact with first, and last names and email succeeds.
6a488035 1452 */
00be9182 1453 public function testCreateIndividualWithNameEmail() {
6a488035
TO
1454 $params = array(
1455 'first_name' => 'abc3',
1456 'last_name' => 'xyz3',
1457 'contact_type' => 'Individual',
1458 'email' => 'man3@yahoo.com',
6a488035
TO
1459 );
1460
f6722559 1461 $contact = $this->callAPISuccess('contact', 'create', $params);
6a488035 1462
f6722559 1463 $this->callAPISuccess('contact', 'delete', $contact);
6a488035 1464 }
5896d037 1465
6a488035 1466 /**
eceb18cc 1467 * Verify that attempt to create individual contact with no data fails.
6a488035 1468 */
00be9182 1469 public function testCreateIndividualWithOutNameEmail() {
6a488035
TO
1470 $params = array(
1471 'contact_type' => 'Individual',
6a488035 1472 );
4b58ed3b 1473 $this->callAPIFailure('contact', 'create', $params);
6a488035 1474 }
5896d037 1475
6a488035 1476 /**
fe482240 1477 * Test create individual contact with first &last names, email and location type succeeds.
6a488035 1478 */
00be9182 1479 public function testCreateIndividualWithNameEmailLocationType() {
6a488035
TO
1480 $params = array(
1481 'first_name' => 'abc4',
1482 'last_name' => 'xyz4',
1483 'email' => 'man4@yahoo.com',
1484 'contact_type' => 'Individual',
1485 'location_type_id' => 1,
6a488035 1486 );
f6722559 1487 $result = $this->callAPISuccess('contact', 'create', $params);
6a488035 1488
f6722559 1489 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
6a488035
TO
1490 }
1491
1492 /**
fe482240 1493 * Verify that when changing employers the old employer relationship becomes inactive.
6a488035 1494 */
00be9182 1495 public function testCreateIndividualWithEmployer() {
6a488035
TO
1496 $employer = $this->organizationCreate();
1497 $employer2 = $this->organizationCreate();
1498
1499 $params = array(
5896d037
TO
1500 'email' => 'man4@yahoo.com',
1501 'contact_type' => 'Individual',
1502 'employer_id' => $employer,
6a488035
TO
1503 );
1504
f6722559 1505 $result = $this->callAPISuccess('contact', 'create', $params);
1506 $relationships = $this->callAPISuccess('relationship', 'get', array(
6a488035
TO
1507 'contact_id_a' => $result['id'],
1508 'sequential' => 1,
1509 ));
1510
1511 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1512
1513 // Add more random relationships to make the test more realistic
4b58ed3b
EM
1514 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
1515 $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
1516 $this->callAPISuccess('relationship', 'create', array(
6a488035
TO
1517 'contact_id_a' => $result['id'],
1518 'contact_id_b' => $this->organizationCreate(),
1519 'is_active' => 1,
1520 'relationship_type_id' => $relTypeId,
1521 ));
6c6e6187 1522 }
6a488035
TO
1523
1524 // Add second employer
1525 $params['employer_id'] = $employer2;
1526 $params['id'] = $result['id'];
f6722559 1527 $result = $this->callAPISuccess('contact', 'create', $params);
6a488035 1528
f6722559 1529 $relationships = $this->callAPISuccess('relationship', 'get', array(
6a488035
TO
1530 'contact_id_a' => $result['id'],
1531 'sequential' => 1,
1532 'is_active' => 0,
1533 ));
1534
1535 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1536 }
1537
1538 /**
fe482240 1539 * Verify that attempt to create household contact with details succeeds.
6a488035 1540 */
00be9182 1541 public function testCreateHouseholdDetails() {
6a488035
TO
1542 $params = array(
1543 'household_name' => 'abc8\'s House',
1544 'nick_name' => 'x House',
1545 'email' => 'man8@yahoo.com',
1546 'contact_type' => 'Household',
6a488035
TO
1547 );
1548
f6722559 1549 $contact = $this->callAPISuccess('contact', 'create', $params);
1550
f6722559 1551 $this->callAPISuccess('contact', 'delete', $contact);
6a488035 1552 }
5896d037 1553
6a488035 1554 /**
381fa321 1555 * Verify that attempt to create household contact with inadequate details fails.
6a488035 1556 */
00be9182 1557 public function testCreateHouseholdInadequateDetails() {
6a488035
TO
1558 $params = array(
1559 'nick_name' => 'x House',
1560 'email' => 'man8@yahoo.com',
1561 'contact_type' => 'Household',
6a488035 1562 );
4b58ed3b 1563 $this->callAPIFailure('contact', 'create', $params);
6a488035
TO
1564 }
1565
6a488035 1566 /**
381fa321 1567 * Verify successful update of individual contact.
6a488035 1568 */
00be9182 1569 public function testUpdateIndividualWithAll() {
ae8bd424 1570 $contactID = $this->individualCreate();
6a488035 1571
ae8bd424 1572 $params = [
1573 'id' => $contactID,
6a488035
TO
1574 'first_name' => 'abcd',
1575 'contact_type' => 'Individual',
1576 'nick_name' => 'This is nickname first',
1577 'do_not_email' => '1',
1578 'do_not_phone' => '1',
1579 'do_not_mail' => '1',
1580 'do_not_trade' => '1',
1581 'legal_identifier' => 'ABC23853ZZ2235',
1582 'external_identifier' => '1928837465',
1583 'image_URL' => 'http://some.url.com/image.jpg',
1584 'home_url' => 'http://www.example.org',
ae8bd424 1585 ];
43ef1263 1586
4b58ed3b 1587 $this->callAPISuccess('Contact', 'Update', $params);
f6722559 1588 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
6a488035
TO
1589 unset($params['contact_id']);
1590 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
4b58ed3b 1591 //reducing this test partially back to api v2 level to get it through
6a488035
TO
1592 unset($params['home_url']);
1593 foreach ($params as $key => $value) {
ae8bd424 1594 $this->assertEquals($value, $getResult['values'][$contactID][$key]);
6a488035 1595 }
6a488035
TO
1596 }
1597
1598 /**
eceb18cc 1599 * Verify successful update of organization contact.
ae8bd424 1600 *
1601 * @throws \Exception
6a488035 1602 */
00be9182 1603 public function testUpdateOrganizationWithAll() {
ae8bd424 1604 $contactID = $this->organizationCreate();
6a488035 1605
ae8bd424 1606 $params = [
1607 'id' => $contactID,
6a488035
TO
1608 'organization_name' => 'WebAccess India Pvt Ltd',
1609 'legal_name' => 'WebAccess',
1610 'sic_code' => 'ABC12DEF',
1611 'contact_type' => 'Organization',
ae8bd424 1612 ];
6a488035 1613
4b58ed3b 1614 $this->callAPISuccess('Contact', 'Update', $params);
ae8bd424 1615 $this->getAndCheck($params, $contactID, 'Contact');
6a488035
TO
1616 }
1617
4099a9c5
AP
1618 /**
1619 * Test merging 2 organizations.
1620 *
1621 * CRM-20421: This test make sure that inherited memberships are deleted upon merging organization.
1622 */
1623 public function testMergeOrganizations() {
aefc291e 1624 $organizationID1 = $this->organizationCreate([], 0);
4099a9c5
AP
1625 $organizationID2 = $this->organizationCreate(array(), 1);
1626 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
39b959db
SL
1627 'employer_id' => $organizationID1,
1628 )));
4099a9c5
AP
1629 $contact = $contact["values"][$contact["id"]];
1630
1631 $membershipType = $this->createEmployerOfMembership();
1632 $membershipParams = array(
1633 'membership_type_id' => $membershipType["id"],
1634 'contact_id' => $organizationID1,
1635 'start_date' => "01/01/2015",
1636 'join_date' => "01/01/2010",
1637 'end_date' => "12/31/2015",
1638 );
1639 $ownermembershipid = $this->contactMembershipCreate($membershipParams);
1640
1641 $contactmembership = $this->callAPISuccess("membership", "getsingle", array(
1642 "contact_id" => $contact["id"],
1643 ));
1644
1645 $this->assertEquals($ownermembershipid, $contactmembership["owner_membership_id"], "Contact membership must be inherited from Organization");
1646
1647 CRM_Dedupe_Merger::moveAllBelongings($organizationID2, $organizationID1, array(
1648 "move_rel_table_memberships" => "0",
1649 "move_rel_table_relationships" => "1",
1650 "main_details" => array(
1651 "contact_id" => $organizationID2,
1652 "contact_type" => "Organization",
1653 ),
1654 "other_details" => array(
1655 "contact_id" => $organizationID1,
1656 "contact_type" => "Organization",
1657 ),
1658 ));
1659
1660 $contactmembership = $this->callAPISuccess("membership", "get", array(
1661 "contact_id" => $contact["id"],
1662 ));
1663
1664 $this->assertEquals(0, $contactmembership["count"], "Contact membership must be deleted after merging organization without memberships.");
1665 }
1666
aefc291e 1667 /**
1668 * Test the function that determines if 2 contacts have conflicts.
712ee28f 1669 *
1670 * @throws \Exception
aefc291e 1671 */
1672 public function testMergeGetConflicts() {
712ee28f 1673 $this->createCustomGroupWithFieldOfType();
1674 $contact1 = $this->individualCreate([
1675 'email' => 'bob@example.com',
1676 'api.address.create' => ['location_type_id' => 'work', 'street_address' => 'big office', 'city' => 'small city'],
1677 'api.address.create.2' => ['location_type_id' => 'home', 'street_address' => 'big house', 'city' => 'small city'],
1678 'external_identifier' => 'unique and special',
1679 $this->getCustomFieldName('text') => 'mummy loves me',
1680 ]);
1681 $contact2 = $this->individualCreate([
1682 'first_name' => 'different',
1683 'api.address.create.1' => ['location_type_id' => 'home', 'street_address' => 'medium house', 'city' => 'small city'],
1684 'api.address.create.2' => ['location_type_id' => 'work', 'street_address' => 'medium office', 'city' => 'small city'],
1685 'external_identifier' => 'uniquer and specialler',
1686 $this->getCustomFieldName('text') => 'mummy loves me more',
1687 ]);
aefc291e 1688 $conflicts = $this->callAPISuccess('Contact', 'get_merge_conflicts', ['to_keep_id' => $contact1, 'to_remove_id' => $contact2])['values'];
712ee28f 1689 $this->assertEquals([
1690 'safe' => [
1691 'conflicts' => [
1692 'contact' => [
1693 [
1694 'first_name' => [$contact1 => 'Anthony', $contact2 => 'different'],
1695 'external_identifier' => [$contact1 => 'unique and special', $contact2 => 'uniquer and specialler'],
1696 $this->getCustomFieldName('text') => [$contact1 => 'mummy loves me', $contact2 => 'mummy loves me more'],
1697 ],
1698 ],
1699 'address' => [
1700 [
1701 'location_type_id' => '1',
1702 'street_address' => [
1703 $contact1 => 'big house',
1704 $contact2 => 'medium house',
1705 ],
1706 ],
1707 [
1708 'location_type_id' => '2',
1709 'street_address' => [
1710 $contact1 => 'big office',
1711 $contact2 => 'medium office',
1712 ],
1713 ],
1714 ],
1715 'email' => [
1716 [
1717 'location_type_id' => '1',
1718 'email' => [
1719 $contact1 => 'bob@example.com',
1720 $contact2 => 'anthony_anderson@civicrm.org',
1721 ],
1722 ],
1723 ],
1724 ],
1725 ],
1726 ], $conflicts);
aefc291e 1727 }
1728
4099a9c5
AP
1729 private function createEmployerOfMembership() {
1730 $params = array(
1731 'domain_id' => CRM_Core_Config::domainID(),
1732 'name' => 'Organization Membership',
1733 'description' => NULL,
1734 'member_of_contact_id' => 1,
1735 'financial_type_id' => 1,
1736 'minimum_fee' => 10,
1737 'duration_unit' => 'year',
1738 'duration_interval' => 1,
1739 'period_type' => 'rolling',
1740 'relationship_type_id' => 5,
1741 'relationship_direction' => 'b_a',
1742 'visibility' => 'Public',
1743 'is_active' => 1,
1744 );
1745 $membershipType = $this->callAPISuccess('membership_type', 'create', $params);
1746 return $membershipType["values"][$membershipType["id"]];
1747 }
1748
6a488035 1749 /**
381fa321 1750 * Verify successful update of household contact.
2d932085
CW
1751 * @param int $version
1752 * @dataProvider versionThreeAndFour
6a488035 1753 */
2d932085
CW
1754 public function testUpdateHouseholdWithAll($version) {
1755 $this->_apiversion = $version;
ae8bd424 1756 $contactID = $this->householdCreate();
6a488035 1757
ae8bd424 1758 $params = [
1759 'id' => $contactID ,
6a488035
TO
1760 'household_name' => 'ABC household',
1761 'nick_name' => 'ABC House',
1762 'contact_type' => 'Household',
ae8bd424 1763 ];
6a488035 1764
f6722559 1765 $result = $this->callAPISuccess('Contact', 'Update', $params);
6a488035 1766
ae8bd424 1767 $expected = [
43ef1263
EM
1768 'contact_type' => 'Household',
1769 'is_opt_out' => 0,
1770 'sort_name' => 'ABC household',
1771 'display_name' => 'ABC household',
1772 'nick_name' => 'ABC House',
ae8bd424 1773 ];
43ef1263 1774 $this->getAndCheck($expected, $result['id'], 'contact');
6a488035
TO
1775 }
1776
1777 /**
381fa321 1778 * Test civicrm_update() without contact type.
1779 *
1780 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1781 *
1782 * CRM-7645.
2d932085
CW
1783 * @param int $version
1784 * @dataProvider versionThreeAndFour
6a488035 1785 */
2d932085
CW
1786 public function testUpdateCreateWithID($version) {
1787 $this->_apiversion = $version;
ae8bd424 1788 $contactID = $this->individualCreate();
1789 $this->callAPISuccess('Contact', 'Update', [
1790 'id' => $contactID,
6a488035
TO
1791 'first_name' => 'abcd',
1792 'last_name' => 'wxyz',
ae8bd424 1793 ]);
6a488035
TO
1794 }
1795
1796 /**
381fa321 1797 * Test civicrm_contact_delete() with no contact ID.
2d932085
CW
1798 * @param int $version
1799 * @dataProvider versionThreeAndFour
6a488035 1800 */
2d932085
CW
1801 public function testContactDeleteNoID($version) {
1802 $this->_apiversion = $version;
6a488035
TO
1803 $params = array(
1804 'foo' => 'bar',
6a488035 1805 );
4b58ed3b 1806 $this->callAPIFailure('contact', 'delete', $params);
6a488035
TO
1807 }
1808
1809 /**
381fa321 1810 * Test civicrm_contact_delete() with error.
2d932085
CW
1811 * @param int $version
1812 * @dataProvider versionThreeAndFour
6a488035 1813 */
2d932085
CW
1814 public function testContactDeleteError($version) {
1815 $this->_apiversion = $version;
f6722559 1816 $params = array('contact_id' => 999);
4b58ed3b 1817 $this->callAPIFailure('contact', 'delete', $params);
6a488035
TO
1818 }
1819
1820 /**
381fa321 1821 * Test civicrm_contact_delete().
2d932085
CW
1822 * @param int $version
1823 * @dataProvider versionThreeAndFour
6a488035 1824 */
2d932085
CW
1825 public function testContactDelete($version) {
1826 $this->_apiversion = $version;
f6722559 1827 $contactID = $this->individualCreate();
6a488035 1828 $params = array(
5896d037 1829 'id' => $contactID,
6a488035 1830 );
4b58ed3b 1831 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__, __FILE__);
6a488035
TO
1832 }
1833
1834 /**
381fa321 1835 * Test civicrm_contact_get() return only first name.
2d932085
CW
1836 * @param int $version
1837 * @dataProvider versionThreeAndFour
6a488035 1838 */
2d932085
CW
1839 public function testContactGetRetFirst($version) {
1840 $this->_apiversion = $version;
f6722559 1841 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
6a488035
TO
1842 $params = array(
1843 'contact_id' => $contact['id'],
1844 'return_first_name' => TRUE,
1845 'sort' => 'first_name',
6a488035 1846 );
f6722559 1847 $result = $this->callAPISuccess('contact', 'get', $params);
4b58ed3b
EM
1848 $this->assertEquals(1, $result['count']);
1849 $this->assertEquals($contact['id'], $result['id']);
1850 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
6a488035
TO
1851 }
1852
1853 /**
381fa321 1854 * Test civicrm_contact_get() return only first name & last name.
1855 *
1856 * Use comma separated string return with a space.
2d932085
CW
1857 * @param int $version
1858 * @dataProvider versionThreeAndFour
6a488035 1859 */
2d932085
CW
1860 public function testContactGetReturnFirstLast($version) {
1861 $this->_apiversion = $version;
f6722559 1862 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
6a488035
TO
1863 $params = array(
1864 'contact_id' => $contact['id'],
1865 'return' => 'first_name, last_name',
6a488035 1866 );
f6722559 1867 $result = $this->callAPISuccess('contact', 'getsingle', $params);
4b58ed3b
EM
1868 $this->assertEquals('abc1', $result['first_name']);
1869 $this->assertEquals('xyz1', $result['last_name']);
6a488035
TO
1870 //check that other defaults not returns
1871 $this->assertArrayNotHasKey('sort_name', $result);
1872 $params = array(
1873 'contact_id' => $contact['id'],
1874 'return' => 'first_name,last_name',
6a488035 1875 );
f6722559 1876 $result = $this->callAPISuccess('contact', 'getsingle', $params);
4b58ed3b
EM
1877 $this->assertEquals('abc1', $result['first_name']);
1878 $this->assertEquals('xyz1', $result['last_name']);
6a488035
TO
1879 //check that other defaults not returns
1880 $this->assertArrayNotHasKey('sort_name', $result);
1881 }
1882
1883 /**
381fa321 1884 * Test civicrm_contact_get() return only first name & last name.
1885 *
d177a2a6 1886 * Use comma separated string return without a space
2d932085
CW
1887 * @param int $version
1888 * @dataProvider versionThreeAndFour
6a488035 1889 */
2d932085
CW
1890 public function testContactGetReturnFirstLastNoComma($version) {
1891 $this->_apiversion = $version;
f6722559 1892 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
6a488035
TO
1893 $params = array(
1894 'contact_id' => $contact['id'],
1895 'return' => 'first_name,last_name',
6a488035 1896 );
f6722559 1897 $result = $this->callAPISuccess('contact', 'getsingle', $params);
4b58ed3b
EM
1898 $this->assertEquals('abc1', $result['first_name']);
1899 $this->assertEquals('xyz1', $result['last_name']);
6a488035
TO
1900 //check that other defaults not returns
1901 $this->assertArrayNotHasKey('sort_name', $result);
1902 }
1903
1904 /**
381fa321 1905 * Test civicrm_contact_get() with default return properties.
6a488035
TO
1906 */
1907 public function testContactGetRetDefault() {
43ef1263 1908 $contactID = $this->individualCreate();
6a488035 1909 $params = array(
43ef1263 1910 'contact_id' => $contactID,
6a488035 1911 'sort' => 'first_name',
6a488035 1912 );
f6722559 1913 $result = $this->callAPISuccess('contact', 'get', $params);
43ef1263
EM
1914 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1915 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
6a488035
TO
1916 }
1917
1918 /**
381fa321 1919 * Test civicrm_contact_getquick() with empty name param.
6a488035
TO
1920 */
1921 public function testContactGetQuick() {
ae8bd424 1922 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact', 'email' => 'TestContact@example.com']);
6a488035 1923
ae8bd424 1924 $result = $this->callAPISuccess('contact', 'getquick', ['name' => 'T']);
1925 $this->assertEquals($contactID, $result['values'][0]['id']);
1926 $params = [
a9096cd1
SL
1927 'name' => "TestContact@example.com",
1928 'field_name' => 'sort_name',
ae8bd424 1929 ];
a9096cd1 1930 $result = $this->callAPISuccess('contact', 'getquick', $params);
ae8bd424 1931 $this->assertEquals($contactID, $result['values'][0]['id']);
6a488035
TO
1932 }
1933
1934 /**
fe482240 1935 * Test civicrm_contact_get) with empty params.
2d932085
CW
1936 * @param int $version
1937 * @dataProvider versionThreeAndFour
6a488035 1938 */
2d932085
CW
1939 public function testContactGetEmptyParams($version) {
1940 $this->_apiversion = $version;
ae8bd424 1941 $this->callAPISuccess('contact', 'get', []);
6a488035
TO
1942 }
1943
1944 /**
fe482240 1945 * Test civicrm_contact_get(,true) with no matches.
2d932085
CW
1946 * @param int $version
1947 * @dataProvider versionThreeAndFour
6a488035 1948 */
2d932085
CW
1949 public function testContactGetOldParamsNoMatches($version) {
1950 $this->_apiversion = $version;
ae8bd424 1951 $this->individualCreate();
1952 $result = $this->callAPISuccess('contact', 'get', ['first_name' => 'Fred']);
fe482240 1953 $this->assertEquals(0, $result['count']);
6a488035
TO
1954 }
1955
1956 /**
fe482240 1957 * Test civicrm_contact_get(,true) with one match.
6a488035
TO
1958 */
1959 public function testContactGetOldParamsOneMatch() {
ae8bd424 1960 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact']);
6a488035 1961
ae8bd424 1962 $result = $this->callAPISuccess('contact', 'get', ['first_name' => 'Test']);
1963 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1964 $this->assertEquals($contactID, $result['id']);
6a488035 1965 }
6a488035
TO
1966
1967 /**
fe482240 1968 * Test civicrm_contact_search_count().
6a488035
TO
1969 */
1970 public function testContactGetEmail() {
1971 $params = array(
1972 'email' => 'man2@yahoo.com',
1973 'contact_type' => 'Individual',
1974 'location_type_id' => 1,
6a488035
TO
1975 );
1976
f6722559 1977 $contact = $this->callAPISuccess('contact', 'create', $params);
1978
6a488035
TO
1979 $params = array(
1980 'email' => 'man2@yahoo.com',
6a488035 1981 );
f6722559 1982 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__);
c8747697 1983 $this->assertEquals('man2@yahoo.com', $result['values'][$result['id']]['email']);
6a488035 1984
f6722559 1985 $this->callAPISuccess('contact', 'delete', $contact);
6a488035
TO
1986 }
1987
37f7ae88 1988 /**
1989 * Ensure consistent return format for option group fields.
2d932085
CW
1990 * @param int $version
1991 * @dataProvider versionThreeAndFour
37f7ae88 1992 */
2d932085
CW
1993 public function testSetPreferredCommunicationNull($version) {
1994 $this->_apiversion = $version;
37f7ae88 1995 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
1996 'preferred_communication_method' => array('Phone', 'SMS'),
1997 )));
1998 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1999 'id' => $contact['id'],
2000 'return' => 'preferred_communication_method',
2001 ));
2002 $this->assertNotEmpty($preferredCommunicationMethod);
2003 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
2004 'preferred_communication_method' => 'null',
2005 'id' => $contact['id'],
2006 )));
2007 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
2008 'id' => $contact['id'],
2009 'return' => 'preferred_communication_method',
2010 ));
2011 $this->assertEmpty($preferredCommunicationMethod);
2012 }
2013
86ab13b7 2014 /**
2015 * Ensure consistent return format for option group fields.
2016 */
2017 public function testPseudoFields() {
2018 $params = array(
2019 'preferred_communication_method' => array('Phone', 'SMS'),
2020 'preferred_language' => 'en_US',
2021 'gender_id' => 'Female',
2022 'prefix_id' => 'Mrs.',
2023 'suffix_id' => 'II',
2024 'communication_style_id' => 'Formal',
2025 );
2026
2027 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, $params));
2028
2029 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
2030 $this->assertEquals('Both', $result['preferred_mail_format']);
2031
2032 $this->assertEquals('en_US', $result['preferred_language']);
2033 $this->assertEquals(1, $result['communication_style_id']);
2034 $this->assertEquals(1, $result['gender_id']);
2035 $this->assertEquals('Female', $result['gender']);
2036 $this->assertEquals('Mrs.', $result['individual_prefix']);
2037 $this->assertEquals(1, $result['prefix_id']);
2038 $this->assertEquals('II', $result['individual_suffix']);
2039 $this->assertEquals(CRM_Core_PseudoConstant::getKey("CRM_Contact_BAO_Contact", 'suffix_id', 'II'), $result['suffix_id']);
2040 $this->callAPISuccess('contact', 'delete', $contact);
2041 $this->assertEquals(array(
2042 CRM_Core_PseudoConstant::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'Phone'),
2043 CRM_Core_PseudoConstant::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'SMS'),
2044 ), $result['preferred_communication_method']);
2045 }
2046
b1f09bea 2047 /**
fe482240
EM
2048 * Test birth date parameters.
2049 *
2050 * These include value, array & birth_date_high, birth_date_low
2051 * && deceased.
b1f09bea 2052 */
4b58ed3b 2053 public function testContactGetBirthDate() {
b1f09bea
E
2054 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month - 2 years')));
2055 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month - 5 years')));
2056 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month -20 years')));
2057
2058 $result = $this->callAPISuccess('contact', 'get', array());
2059 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
2060 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
2061 $this->assertEquals(1, $result['count']);
2062 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
2063 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
2064 $this->assertEquals(1, $result['count']);
2065 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
5896d037 2066 $result = $this->callAPISuccess('contact', 'get', array(
92915c55
TO
2067 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
2068 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
2069 ));
b1f09bea
E
2070 $this->assertEquals(1, $result['count']);
2071 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
5896d037 2072 $result = $this->callAPISuccess('contact', 'get', array(
92915c55
TO
2073 'birth_date_low' => '-6 years',
2074 'birth_date_high' => '- 3 years',
2075 ));
9f60788a
EM
2076 $this->assertEquals(1, $result['count']);
2077 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
b1f09bea
E
2078 }
2079
d0bfb983 2080 /**
2081 * Test Address parameters
2082 *
2083 * This include state_province, state_province_name, country
2084 */
2085 public function testContactGetWithAddressFields() {
2086 $individuals = array(
2087 array(
2088 'first_name' => 'abc1',
2089 'contact_type' => 'Individual',
2090 'last_name' => 'xyz1',
2091 'api.address.create' => array(
2092 'country' => 'United States',
2093 'state_province_id' => 'Michigan',
2094 'location_type_id' => 1,
2095 ),
2096 ),
2097 array(
2098 'first_name' => 'abc2',
2099 'contact_type' => 'Individual',
2100 'last_name' => 'xyz2',
2101 'api.address.create' => array(
2102 'country' => 'United States',
2103 'state_province_id' => 'Alabama',
2104 'location_type_id' => 1,
2105 ),
2106 ),
2107 );
2108 foreach ($individuals as $params) {
2109 $contact = $this->callAPISuccess('contact', 'create', $params);
2110 }
2111
2112 // Check whether Contact get API return successfully with below Address params.
2113 $fieldsToTest = array(
2114 'state_province_name' => 'Michigan',
2115 'state_province' => 'Michigan',
2116 'country' => 'United States',
2117 'state_province_name' => array('IN' => array('Michigan', 'Alabama')),
2118 'state_province' => array('IN' => array('Michigan', 'Alabama')),
2119 );
2120 foreach ($fieldsToTest as $field => $value) {
2121 $getParams = array(
2122 'id' => $contact['id'],
2123 $field => $value,
2124 );
41a74135 2125 $result = $this->callAPISuccess('Contact', 'get', $getParams);
2126 $this->assertEquals(1, $result['count']);
d0bfb983 2127 }
2128 }
2129
b1f09bea 2130 /**
fe482240
EM
2131 * Test Deceased date parameters.
2132 *
2133 * These include value, array & Deceased_date_high, Deceased date_low
d177a2a6 2134 * && deceased.
b1f09bea 2135 */
4b58ed3b 2136 public function testContactGetDeceasedDate() {
b1f09bea
E
2137 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month - 2 years')));
2138 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month - 5 years')));
2139 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month -20 years')));
2140
2141 $result = $this->callAPISuccess('contact', 'get', array());
2142 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
2143 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
2144 $this->assertEquals(1, $result['count']);
2145 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2146 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
2147 $this->assertEquals(1, $result['count']);
2148 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
5896d037 2149 $result = $this->callAPISuccess('contact', 'get', array(
92915c55
TO
2150 'deceased_date_low' => '-6 years',
2151 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
2152 ));
b1f09bea
E
2153 $this->assertEquals(1, $result['count']);
2154 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2155 }
2156
e635f9d4 2157 /**
fe482240 2158 * Test for Contact.get id=@user:username.
e635f9d4 2159 */
00be9182 2160 public function testContactGetByUsername() {
fe482240 2161 // Setup - create contact with a uf-match.
e635f9d4
TO
2162 $cid = $this->individualCreate(array(
2163 'contact_type' => 'Individual',
2164 'first_name' => 'testGetByUsername',
2165 'last_name' => 'testGetByUsername',
2166 ));
2167
2168 $ufMatchParams = array(
2169 'domain_id' => CRM_Core_Config::domainID(),
2170 'uf_id' => 99,
2171 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
2172 'contact_id' => $cid,
2173 );
2174 $ufMatch = CRM_Core_BAO_UFMatch::create($ufMatchParams);
2175 $this->assertTrue(is_numeric($ufMatch->id));
2176
2177 // setup - mock the calls to CRM_Utils_System_*::getUfId
dcadbba4
SL
2178 $mockFunction = $this->mockMethod;
2179 $userSystem = $this->$mockFunction('CRM_Utils_System_UnitTests', array('getUfId'));
e635f9d4
TO
2180 $userSystem->expects($this->once())
2181 ->method('getUfId')
2182 ->with($this->equalTo('exampleUser'))
2183 ->will($this->returnValue(99));
2184 CRM_Core_Config::singleton()->userSystem = $userSystem;
2185
2186 // perform a lookup
2187 $result = $this->callAPISuccess('Contact', 'get', array(
e635f9d4
TO
2188 'id' => '@user:exampleUser',
2189 ));
2190 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
8d475ce9
CW
2191
2192 // Check search of contacts with & without uf records
2193 $result = $this->callAPISuccess('Contact', 'get', ['uf_user' => 1]);
2194 $this->assertArrayHasKey($cid, $result['values']);
2195
2196 $result = $this->callAPISuccess('Contact', 'get', ['uf_user' => 0]);
2197 $this->assertArrayNotHasKey($cid, $result['values']);
e635f9d4
TO
2198 }
2199
265cc07d 2200 /**
eceb18cc 2201 * Test to check return works OK.
265cc07d 2202 */
00be9182 2203 public function testContactGetReturnValues() {
701a69da 2204 $extraParams = array(
2205 'nick_name' => 'Bob',
2206 'phone' => '456',
2207 'email' => 'e@mail.com',
2208 );
265cc07d 2209 $contactID = $this->individualCreate($extraParams);
2210 //actually it turns out the above doesn't create a phone
6c6e6187 2211 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
265cc07d 2212 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
2213 foreach ($extraParams as $key => $value) {
2214 $this->assertEquals($result[$key], $value);
2215 }
2216 //now we check they are still returned with 'return' key
5896d037 2217 $result = $this->callAPISuccess('contact', 'getsingle', array(
92915c55
TO
2218 'id' => $contactID,
2219 'return' => array_keys($extraParams),
2220 ));
265cc07d 2221 foreach ($extraParams as $key => $value) {
2222 $this->assertEquals($result[$key], $value);
2223 }
2224 }
2225
701a69da 2226 /**
2227 * Test creating multiple phones using chaining.
2228 *
2229 * @throws \Exception
2d932085
CW
2230 * @param int $version
2231 * @dataProvider versionThreeAndFour
701a69da 2232 */
2d932085
CW
2233 public function testCRM13252MultipleChainedPhones($version) {
2234 $this->_apiversion = $version;
265cc07d 2235 $contactID = $this->householdCreate();
2236 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
2237 $params = array(
5896d037
TO
2238 'contact_id' => $contactID,
2239 'household_name' => 'Household 1',
2240 'contact_type' => 'Household',
2241 'api.phone.create' => array(
265cc07d 2242 0 => array(
2243 'phone' => '111-111-1111',
2244 'location_type_id' => 1,
2245 'phone_type_id' => 1,
2246 ),
2247 1 => array(
2248 'phone' => '222-222-2222',
2249 'location_type_id' => 1,
2250 'phone_type_id' => 2,
21dfd5f5
TO
2251 ),
2252 ),
265cc07d 2253 );
4b58ed3b 2254 $this->callAPISuccess('contact', 'create', $params);
265cc07d 2255 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
2256
2257 }
5896d037 2258
e635f9d4 2259 /**
fe482240 2260 * Test for Contact.get id=@user:username (with an invalid username).
e635f9d4 2261 */
00be9182 2262 public function testContactGetByUnknownUsername() {
e635f9d4 2263 // setup - mock the calls to CRM_Utils_System_*::getUfId
dcadbba4
SL
2264 $mockFunction = $this->mockMethod;
2265 $userSystem = $this->$mockFunction('CRM_Utils_System_UnitTests', array('getUfId'));
e635f9d4
TO
2266 $userSystem->expects($this->once())
2267 ->method('getUfId')
2268 ->with($this->equalTo('exampleUser'))
2269 ->will($this->returnValue(NULL));
2270 CRM_Core_Config::singleton()->userSystem = $userSystem;
2271
2272 // perform a lookup
2273 $result = $this->callAPIFailure('Contact', 'get', array(
e635f9d4
TO
2274 'id' => '@user:exampleUser',
2275 ));
2276 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
2277 }
2278
6a488035 2279 /**
701a69da 2280 * Verify attempt to create individual with chained arrays and sequential.
2d932085
CW
2281 * @param int $version
2282 * @dataProvider versionThreeAndFour
48bb2598 2283 */
2d932085
CW
2284 public function testGetIndividualWithChainedArraysAndSequential($version) {
2285 $this->_apiversion = $version;
48bb2598
JV
2286 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2287 $params['custom_' . $ids['custom_field_id']] = "custom string";
2288
84b51197 2289 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
48bb2598
JV
2290 $params = array(
2291 'sequential' => 1,
2292 'first_name' => 'abc3',
2293 'last_name' => 'xyz3',
2294 'contact_type' => 'Individual',
2295 'email' => 'man3@yahoo.com',
2296 'api.website.create' => array(
2297 array(
2298 'url' => "http://civicrm.org",
2299 ),
2300 array(
2301 'url' => "https://civicrm.org",
2302 ),
2303 ),
2304 );
2305
2306 $result = $this->callAPISuccess('Contact', 'create', $params);
2307
48bb2598
JV
2308 // delete the contact and custom groups
2309 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
2310 $this->customGroupDelete($ids['custom_group_id']);
84b51197 2311 $this->customGroupDelete($moreIDs['custom_group_id']);
48bb2598
JV
2312
2313 $this->assertEquals($result['id'], $result['values'][0]['id']);
2314 $this->assertArrayKeyExists('api.website.create', $result['values'][0]);
2315 }
2316
2317 /**
701a69da 2318 * Verify attempt to create individual with chained arrays.
6a488035 2319 */
00be9182 2320 public function testGetIndividualWithChainedArrays() {
6a488035
TO
2321 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2322 $params['custom_' . $ids['custom_field_id']] = "custom string";
2323
381fa321 2324 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
5c49fee0 2325 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
5896d037
TO
2326 $subfile = "APIChainedArray";
2327 $params = array(
6a488035
TO
2328 'first_name' => 'abc3',
2329 'last_name' => 'xyz3',
2330 'contact_type' => 'Individual',
2331 'email' => 'man3@yahoo.com',
6a488035
TO
2332 'api.contribution.create' => array(
2333 'receive_date' => '2010-01-01',
2334 'total_amount' => 100.00,
2335 'financial_type_id' => 1,
2336 'payment_instrument_id' => 1,
2337 'non_deductible_amount' => 10.00,
2338 'fee_amount' => 50.00,
2339 'net_amount' => 90.00,
2340 'trxn_id' => 12345,
2341 'invoice_id' => 67890,
2342 'source' => 'SSF',
2343 'contribution_status_id' => 1,
2344 ),
2345 'api.contribution.create.1' => array(
2346 'receive_date' => '2011-01-01',
2347 'total_amount' => 120.00,
6c6e6187 2348 'financial_type_id' => $this->_financialTypeId = 1,
6a488035
TO
2349 'payment_instrument_id' => 1,
2350 'non_deductible_amount' => 10.00,
2351 'fee_amount' => 50.00,
2352 'net_amount' => 90.00,
2353 'trxn_id' => 12335,
2354 'invoice_id' => 67830,
2355 'source' => 'SSF',
2356 'contribution_status_id' => 1,
2357 ),
2358 'api.website.create' => array(
2359 array(
2360 'url' => "http://civicrm.org",
2361 ),
2362 ),
2363 );
2364
f6722559 2365 $result = $this->callAPISuccess('Contact', 'create', $params);
6a488035 2366 $params = array(
f6722559 2367 'id' => $result['id'],
6a488035
TO
2368 'api.website.get' => array(),
2369 'api.Contribution.get' => array(
2370 'total_amount' => '120.00',
5896d037
TO
2371 ),
2372 'api.CustomValue.get' => 1,
6a488035
TO
2373 'api.Note.get' => 1,
2374 );
f6722559 2375 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
6a488035 2376 // delete the contact
f6722559 2377 $this->callAPISuccess('contact', 'delete', $result);
6a488035 2378 $this->customGroupDelete($ids['custom_group_id']);
381fa321 2379 $this->customGroupDelete($moreIDs['custom_group_id']);
4b58ed3b
EM
2380 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
2381 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
6a488035
TO
2382 }
2383
a77b0380 2384 /**
701a69da 2385 * Verify attempt to create individual with chained arrays and sequential.
a77b0380 2386 *
2d932085
CW
2387 * @see https://issues.civicrm.org/jira/browse/CRM-15815
2388 * @param int $version
2389 * @dataProvider versionThreeAndFour
a77b0380 2390 */
2d932085
CW
2391 public function testCreateIndividualWithChainedArrayAndSequential($version) {
2392 $this->_apiversion = $version;
a77b0380
JV
2393 $params = array(
2394 'sequential' => 1,
2395 'first_name' => 'abc5',
2396 'last_name' => 'xyz5',
2397 'contact_type' => 'Individual',
2398 'email' => 'woman5@yahoo.com',
2399 'api.phone.create' => array(
2400 array('phone' => '03-231 07 95'),
2401 array('phone' => '03-232 51 62'),
2402 ),
2403 'api.website.create' => array(
2404 'url' => 'http://civicrm.org',
2405 ),
2406 );
2407 $result = $this->callAPISuccess('Contact', 'create', $params);
2408
2409 // I could try to parse the result to see whether the two phone numbers
2410 // and the website are there, but I am not sure about the correct format.
2411 // So I will just fetch it again before checking.
2412 // See also http://forum.civicrm.org/index.php/topic,35393.0.html
2413 $params = array(
2414 'sequential' => 1,
2415 'id' => $result['id'],
2416 'api.website.get' => array(),
2417 'api.phone.get' => array(),
2418 );
2419 $result = $this->callAPISuccess('Contact', 'get', $params);
2420
2421 // delete the contact
2422 $this->callAPISuccess('contact', 'delete', $result);
2423
2424 $this->assertEquals(2, $result['values'][0]['api.phone.get']['count']);
2425 $this->assertEquals(1, $result['values'][0]['api.website.get']['count']);
2426 }
2427
701a69da 2428 /**
2429 * Test retrieving an individual with chained array syntax.
2430 */
00be9182 2431 public function testGetIndividualWithChainedArraysFormats() {
5c49fee0 2432 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
6a488035
TO
2433 $subfile = "APIChainedArrayFormats";
2434 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2435 $params['custom_' . $ids['custom_field_id']] = "custom string";
2436
381fa321 2437 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
6a488035
TO
2438 $params = array(
2439 'first_name' => 'abc3',
2440 'last_name' => 'xyz3',
2441 'contact_type' => 'Individual',
2442 'email' => 'man3@yahoo.com',
6a488035
TO
2443 'api.contribution.create' => array(
2444 'receive_date' => '2010-01-01',
2445 'total_amount' => 100.00,
f6722559 2446 'financial_type_id' => $this->_financialTypeId,
6a488035
TO
2447 'payment_instrument_id' => 1,
2448 'non_deductible_amount' => 10.00,
2449 'fee_amount' => 50.00,
2450 'net_amount' => 90.00,
2451 'source' => 'SSF',
2452 'contribution_status_id' => 1,
25ac4ffa 2453 'skipCleanMoney' => 1,
6a488035
TO
2454 ),
2455 'api.contribution.create.1' => array(
2456 'receive_date' => '2011-01-01',
2457 'total_amount' => 120.00,
f6722559 2458 'financial_type_id' => $this->_financialTypeId,
6a488035
TO
2459 'payment_instrument_id' => 1,
2460 'non_deductible_amount' => 10.00,
2461 'fee_amount' => 50.00,
2462 'net_amount' => 90.00,
2463 'source' => 'SSF',
2464 'contribution_status_id' => 1,
25ac4ffa 2465 'skipCleanMoney' => 1,
6a488035
TO
2466 ),
2467 'api.website.create' => array(
2468 array(
2469 'url' => "http://civicrm.org",
2470 ),
2471 ),
2472 );
2473
f6722559 2474 $result = $this->callAPISuccess('Contact', 'create', $params);
6a488035 2475 $params = array(
f6722559 2476 'id' => $result['id'],
6a488035
TO
2477 'api.website.getValue' => array('return' => 'url'),
2478 'api.Contribution.getCount' => array(),
2479 'api.CustomValue.get' => 1,
2480 'api.Note.get' => 1,
2481 'api.Membership.getCount' => array(),
2482 );
f6722559 2483 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
4b58ed3b
EM
2484 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
2485 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
2486 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
6a488035 2487
f6722559 2488 $this->callAPISuccess('contact', 'delete', $result);
6a488035 2489 $this->customGroupDelete($ids['custom_group_id']);
381fa321 2490 $this->customGroupDelete($moreIDs['custom_group_id']);
6a488035
TO
2491 }
2492
381fa321 2493 /**
2494 * Test complex chaining.
2495 */
00be9182 2496 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
6a488035
TO
2497 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2498 $params['custom_' . $ids['custom_field_id']] = "custom string";
381fa321 2499 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2500 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
92915c55
TO
2501 'title' => "another group",
2502 'name' => 'another name',
2503 ));
5c49fee0 2504 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
6a488035
TO
2505 $subfile = "APIChainedArrayMultipleCustom";
2506 $params = array(
2507 'first_name' => 'abc3',
2508 'last_name' => 'xyz3',
2509 'contact_type' => 'Individual',
2510 'email' => 'man3@yahoo.com',
6a488035
TO
2511 'api.contribution.create' => array(
2512 'receive_date' => '2010-01-01',
2513 'total_amount' => 100.00,
5896d037 2514 'financial_type_id' => 1,
6a488035
TO
2515 'payment_instrument_id' => 1,
2516 'non_deductible_amount' => 10.00,
2517 'fee_amount' => 50.00,
2518 'net_amount' => 90.00,
2519 'trxn_id' => 12345,
2520 'invoice_id' => 67890,
2521 'source' => 'SSF',
2522 'contribution_status_id' => 1,
25ac4ffa 2523 'skipCleanMoney' => 1,
6a488035
TO
2524 ),
2525 'api.contribution.create.1' => array(
2526 'receive_date' => '2011-01-01',
2527 'total_amount' => 120.00,
5896d037 2528 'financial_type_id' => 1,
6a488035
TO
2529 'payment_instrument_id' => 1,
2530 'non_deductible_amount' => 10.00,
2531 'fee_amount' => 50.00,
2532 'net_amount' => 90.00,
2533 'trxn_id' => 12335,
2534 'invoice_id' => 67830,
2535 'source' => 'SSF',
2536 'contribution_status_id' => 1,
25ac4ffa 2537 'skipCleanMoney' => 1,
6a488035
TO
2538 ),
2539 'api.website.create' => array(
2540 array(
2541 'url' => "http://civicrm.org",
2542 ),
2543 ),
2544 'custom_' . $ids['custom_field_id'] => "value 1",
381fa321 2545 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
2546 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
2547 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
6a488035
TO
2548 );
2549
f6722559 2550 $result = $this->callAPISuccess('Contact', 'create', $params);
2551 $result = $this->callAPISuccess('Contact', 'create', array(
6c6e6187 2552 'contact_type' => 'Individual',
5896d037
TO
2553 'id' => $result['id'],
2554 'custom_' .
381fa321 2555 $moreIDs['custom_field_id'][0] => "value 3",
5896d037
TO
2556 'custom_' .
2557 $ids['custom_field_id'] => "value 4",
2558 ));
6a488035
TO
2559
2560 $params = array(
f6722559 2561 'id' => $result['id'],
6a488035
TO
2562 'api.website.getValue' => array('return' => 'url'),
2563 'api.Contribution.getCount' => array(),
2564 'api.CustomValue.get' => 1,
2565 );
f6722559 2566 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2567
6a488035 2568 $this->customGroupDelete($ids['custom_group_id']);
381fa321 2569 $this->customGroupDelete($moreIDs['custom_group_id']);
2570 $this->customGroupDelete($andMoreIDs['custom_group_id']);
4b58ed3b
EM
2571 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
2572 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
6a488035 2573 }
5896d037 2574
d424ffde 2575 /**
381fa321 2576 * Test checks usage of $values to pick & choose inputs.
2d932085
CW
2577 *
2578 * Api3 Only - chaining syntax is too funky for v4 (assuming entityTag "entity_id" field will be filled by magic)
6a488035 2579 */
00be9182 2580 public function testChainingValuesCreate() {
5c49fee0
CW
2581 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
2582 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
6a488035
TO
2583 $subfile = "APIChainedArrayValuesFromSiblingFunction";
2584 $params = array(
6c6e6187 2585 'display_name' => 'batman',
5896d037 2586 'contact_type' => 'Individual',
701a69da 2587 'api.tag.create' => array(
2588 'name' => '$value.id',
2589 'description' => '$value.display_name',
2590 'format.only_id' => 1,
2591 ),
6a488035
TO
2592 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
2593 );
f6722559 2594 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
6a488035 2595 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
f6722559 2596
6a488035
TO
2597 $tablesToTruncate = array(
2598 'civicrm_contact',
2599 'civicrm_activity',
2600 'civicrm_entity_tag',
2601 'civicrm_tag',
2602 );
2603 $this->quickCleanup($tablesToTruncate, TRUE);
2604 }
2605
d424ffde 2606 /**
fe482240 2607 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
2d932085
CW
2608 * @param int $version
2609 * @dataProvider versionThreeAndFour
6a488035 2610 */
2d932085
CW
2611 public function testContactGetFormatIsSuccessTrue($version) {
2612 $this->_apiversion = $version;
ae8bd424 2613 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact']);
6a488035
TO
2614 $description = "This demonstrates use of the 'format.is_success' param.
2615 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2616 $subfile = "FormatIsSuccess_True";
ae8bd424 2617 $params = ['id' => $contactID, 'format.is_success' => 1];
5896d037 2618 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
6a488035 2619 $this->assertEquals(1, $result);
f6722559 2620 $this->callAPISuccess('Contact', 'Delete', $params);
6a488035 2621 }
5896d037 2622
d424ffde 2623 /**
fe482240 2624 * Test TrueFalse format.
2d932085
CW
2625 * @param int $version
2626 * @dataProvider versionThreeAndFour
6a488035 2627 */
2d932085
CW
2628 public function testContactCreateFormatIsSuccessFalse($version) {
2629 $this->_apiversion = $version;
6a488035
TO
2630
2631 $description = "This demonstrates use of the 'format.is_success' param.
2632 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2633 $subfile = "FormatIsSuccess_Fail";
5896d037
TO
2634 $params = array('id' => 500, 'format.is_success' => 1);
2635 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
6a488035
TO
2636 $this->assertEquals(0, $result);
2637 }
5896d037 2638
3628dc86 2639 /**
2640 * Test long display names.
2641 *
2642 * CRM-21258
2d932085
CW
2643 * @param int $version
2644 * @dataProvider versionThreeAndFour
3628dc86 2645 */
2d932085
CW
2646 public function testContactCreateLongDisplayName($version) {
2647 $this->_apiversion = $version;
3628dc86 2648 $result = $this->callAPISuccess('Contact', 'Create', array(
2649 'first_name' => str_pad('a', 64, 'a'),
2650 'last_name' => str_pad('a', 64, 'a'),
2651 'contact_type' => 'Individual',
2652 ));
2653 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['display_name']);
2654 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['sort_name']);
2655 }
2656
1bdbd4ec 2657 /**
2658 * Test that we can set the sort name via the api or alter it via a hook.
2659 *
2660 * As of writing this is being fixed for Organization & Household but it makes sense to do for individuals too.
2d932085
CW
2661 * @param int $version
2662 * @dataProvider versionThreeAndFour
1bdbd4ec 2663 */
2d932085
CW
2664 public function testCreateAlterSortName($version) {
2665 $this->_apiversion = $version;
1bdbd4ec 2666 $organizationID = $this->organizationCreate(['organization_name' => 'The Justice League', 'sort_name' => 'Justice League, The']);
2667 $organization = $this->callAPISuccessGetSingle('Contact', ['return' => ['sort_name', 'display_name'], 'id' => $organizationID]);
2668 $this->assertEquals('Justice League, The', $organization['sort_name']);
2669 $this->assertEquals('The Justice League', $organization['display_name']);
2670 $this->hookClass->setHook('civicrm_pre', array($this, 'killTheJusticeLeague'));
2671 $this->organizationCreate(['id' => $organizationID, 'sort_name' => 'Justice League, The']);
2672 $organization = $this->callAPISuccessGetSingle('Contact', ['return' => ['sort_name', 'display_name', 'is_deceased'], 'id' => $organizationID]);
2673 $this->assertEquals('Steppenwolf wuz here', $organization['display_name']);
2674 $this->assertEquals('Steppenwolf wuz here', $organization['sort_name']);
2675 $this->assertEquals(1, $organization['is_deceased']);
2676
2677 $householdID = $this->householdCreate();
2678 $household = $this->callAPISuccessGetSingle('Contact', ['return' => ['sort_name', 'display_name'], 'id' => $householdID]);
2679 $this->assertEquals('Steppenwolf wuz here', $household['display_name']);
2680 $this->assertEquals('Steppenwolf wuz here', $household['sort_name']);
2681 }
2682
2683 /**
2684 * Implements hook_pre().
2685 */
2686 public function killTheJusticeLeague($op, $entity, $id, &$params) {
2687 $params['sort_name'] = 'Steppenwolf wuz here';
2688 $params['display_name'] = 'Steppenwolf wuz here';
2689 $params['is_deceased'] = 1;
2690 }
2691
d424ffde 2692 /**
fe482240 2693 * Test Single Entity format.
2d932085
CW
2694 * @param int $version
2695 * @dataProvider versionThreeAndFour
6a488035 2696 */
2d932085
CW
2697 public function testContactGetSingleEntityArray($version) {
2698 $this->_apiversion = $version;
ae8bd424 2699 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact']);
6a488035 2700 $description = "This demonstrates use of the 'format.single_entity_array' param.
5c49fee0
CW
2701 This param causes the only contact to be returned as an array without the other levels.
2702 It will be ignored if there is not exactly 1 result";
6a488035 2703 $subfile = "GetSingleContact";
ae8bd424 2704 $result = $this->callAPIAndDocument('Contact', 'GetSingle', ['id' => $contactID], __FUNCTION__, __FILE__, $description, $subfile);
2705 $this->assertEquals('Mr. Test Contact II', $result['display_name']);
2706 $this->callAPISuccess('Contact', 'Delete', ['id' => $contactID]);
6a488035
TO
2707 }
2708
d424ffde 2709 /**
381fa321 2710 * Test Single Entity format.
2d932085
CW
2711 * @param int $version
2712 * @dataProvider versionThreeAndFour
6a488035 2713 */
2d932085
CW
2714 public function testContactGetFormatCountOnly($version) {
2715 $this->_apiversion = $version;
ae8bd424 2716 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact']);
5c49fee0
CW
2717 $description = "This demonstrates use of the 'getCount' action.
2718 This param causes the count of the only function to be returned as an integer.";
ae8bd424 2719 $params = ['id' => $contactID];
381fa321 2720 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__, __FILE__, $description,
84b51197 2721 'GetCountContact');
4b58ed3b 2722 $this->assertEquals('1', $result);
f6722559 2723 $this->callAPISuccess('Contact', 'Delete', $params);
6a488035 2724 }
5896d037 2725
d424ffde 2726 /**
381fa321 2727 * Test id only format.
2d932085
CW
2728 * @param int $version
2729 * @dataProvider versionThreeAndFour
408b79bf 2730 */
2d932085
CW
2731 public function testContactGetFormatIDOnly($version) {
2732 $this->_apiversion = $version;
ae8bd424 2733 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact']);
5c49fee0
CW
2734 $description = "This demonstrates use of the 'format.id_only' param.
2735 This param causes the id of the only entity to be returned as an integer.
2736 It will be ignored if there is not exactly 1 result";
6a488035 2737 $subfile = "FormatOnlyID";
ae8bd424 2738 $params = ['id' => $contactID, 'format.only_id' => 1];
5896d037 2739 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
ae8bd424 2740 $this->assertEquals($contactID, $result);
f6722559 2741 $this->callAPISuccess('Contact', 'Delete', $params);
6a488035
TO
2742 }
2743
d424ffde 2744 /**
381fa321 2745 * Test id only format.
2d932085
CW
2746 * @param int $version
2747 * @dataProvider versionThreeAndFour
408b79bf 2748 */
2d932085
CW
2749 public function testContactGetFormatSingleValue($version) {
2750 $this->_apiversion = $version;
ae8bd424 2751 $contactID = $this->individualCreate(['first_name' => 'Test', 'last_name' => 'Contact']);
6a488035 2752 $description = "This demonstrates use of the 'format.single_value' param.
5c49fee0
CW
2753 This param causes only a single value of the only entity to be returned as an string.
2754 It will be ignored if there is not exactly 1 result";
4b58ed3b 2755 $subFile = "FormatSingleValue";
ae8bd424 2756 $params = ['id' => $contactID, 'return' => 'display_name'];
a828d7b8 2757 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__, __FILE__, $description, $subFile);
ae8bd424 2758 $this->assertEquals('Mr. Test Contact II', $result);
f6722559 2759 $this->callAPISuccess('Contact', 'Delete', $params);
6a488035
TO
2760 }
2761
b2130237 2762 /**
381fa321 2763 * Test that permissions are respected when creating contacts.
2d932085
CW
2764 * @param int $version
2765 * @dataProvider versionThreeAndFour
b2130237 2766 */
2d932085
CW
2767 public function testContactCreationPermissions($version) {
2768 $this->_apiversion = $version;
6a488035 2769 $params = array(
6c6e6187 2770 'contact_type' => 'Individual',
5896d037 2771 'first_name' => 'Foo',
6a488035
TO
2772 'last_name' => 'Bear',
2773 'check_permissions' => TRUE,
6a488035
TO
2774 );
2775 $config = CRM_Core_Config::singleton();
2776 $config->userPermissionClass->permissions = array('access CiviCRM');
d0e1eff2 2777 $result = $this->callAPIFailure('contact', 'create', $params);
2d932085 2778 $this->assertContains('failed', $result['error_message'], 'lacking permissions should not be enough to create a contact');
6a488035
TO
2779
2780 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts');
701a69da 2781 $this->callAPISuccess('contact', 'create', $params);
6a488035
TO
2782 }
2783
fa6448fa
EM
2784 /**
2785 * Test that delete with skip undelete respects permissions.
2d932085 2786 * TODO: Api4
fa6448fa
EM
2787 */
2788 public function testContactDeletePermissions() {
2789 $contactID = $this->individualCreate();
2790 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
2791 $this->callAPIFailure('Contact', 'delete', array(
2792 'id' => $contactID,
2793 'check_permissions' => 1,
2794 'skip_undelete' => 1,
2795 ));
2796 $this->callAPISuccess('Contact', 'delete', array(
2797 'id' => $contactID,
2798 'check_permissions' => 0,
2799 'skip_undelete' => 1,
2800 ));
2801 }
2802
381fa321 2803 /**
2804 * Test update with check permissions set.
2d932085
CW
2805 * @param int $version
2806 * @dataProvider versionThreeAndFour
381fa321 2807 */
2d932085
CW
2808 public function testContactUpdatePermissions($version) {
2809 $this->_apiversion = $version;
5896d037
TO
2810 $params = array(
2811 'contact_type' => 'Individual',
2812 'first_name' => 'Foo',
2813 'last_name' => 'Bear',
21dfd5f5 2814 'check_permissions' => TRUE,
5896d037 2815 );
f6722559 2816 $result = $this->callAPISuccess('contact', 'create', $params);
6a488035 2817 $config = CRM_Core_Config::singleton();
5896d037
TO
2818 $params = array(
2819 'id' => $result['id'],
2820 'contact_type' => 'Individual',
2821 'last_name' => 'Bar',
21dfd5f5 2822 'check_permissions' => TRUE,
5896d037 2823 );
6a488035
TO
2824
2825 $config->userPermissionClass->permissions = array('access CiviCRM');
d0e1eff2 2826 $result = $this->callAPIFailure('contact', 'update', $params);
0a61b6e2 2827 $this->assertEquals('Permission denied to modify contact record', $result['error_message']);
6a488035 2828
5896d037
TO
2829 $config->userPermissionClass->permissions = array(
2830 'access CiviCRM',
2831 'add contacts',
2832 'view all contacts',
2833 'edit all contacts',
21dfd5f5 2834 'import contacts',
5896d037 2835 );
701a69da 2836 $this->callAPISuccess('contact', 'update', $params);
6a488035
TO
2837 }
2838
381fa321 2839 /**
2840 * Test contact proximity api.
2841 */
00be9182 2842 public function testContactProximity() {
6a488035
TO
2843 // first create a contact with a SF location with a specific
2844 // geocode
2845 $contactID = $this->organizationCreate();
2846
2847 // now create the address
2848 $params = array(
2849 'street_address' => '123 Main Street',
2850 'city' => 'San Francisco',
2851 'is_primary' => 1,
2852 'country_id' => 1228,
2853 'state_province_id' => 1004,
2854 'geo_code_1' => '37.79',
2855 'geo_code_2' => '-122.40',
2856 'location_type_id' => 1,
2857 'contact_id' => $contactID,
6a488035
TO
2858 );
2859
f6722559 2860 $result = $this->callAPISuccess('address', 'create', $params);
ba4a1892 2861 $this->assertEquals(1, $result['count']);
6a488035
TO
2862
2863 // now do a proximity search with a close enough geocode and hope to match
2864 // that specific contact only!
2865 $proxParams = array(
2866 'latitude' => 37.7,
2867 'longitude' => -122.3,
2868 'unit' => 'mile',
2869 'distance' => 10,
6a488035 2870 );
f6722559 2871 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
ba4a1892 2872 $this->assertEquals(1, $result['count']);
6a488035 2873 }
60ec9f43
E
2874
2875 /**
381fa321 2876 * Test that Ajax API permission is sufficient to access getquick api.
2877 *
1d6020f1 2878 * (note that getquick api is required for autocomplete & has ACL permissions applied)
60ec9f43 2879 */
fe482240 2880 public function testGetquickPermissionCRM13744() {
60ec9f43 2881 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviEvent');
4b58ed3b 2882 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
60ec9f43 2883 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
4b58ed3b 2884 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
60ec9f43 2885 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access AJAX API');
4b58ed3b 2886 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
60ec9f43 2887 }
9c8096cb 2888
08f4ab8d 2889 /**
2890 * Test that getquick returns contacts with an exact first name match first.
2baa1e00 2891 *
2892 * The search string 'b' & 'bob' both return ordered by sort_name if includeOrderByClause
2893 * is true (default) but if it is false then matches are returned in ID order.
613643e0 2894 *
2895 * @dataProvider getSearchSortOptions
08f4ab8d 2896 */
613643e0 2897 public function testGetQuickExactFirst($searchParameters, $settings, $firstContact, $secondContact = NULL) {
08f4ab8d 2898 $this->getQuickSearchSampleData();
613643e0 2899 $this->callAPISuccess('Setting', 'create', $settings);
2900 $result = $this->callAPISuccess('contact', 'getquick', $searchParameters);
2901 $this->assertEquals($firstContact, $result['values'][0]['sort_name']);
2902 $this->assertEquals($secondContact, $result['values'][1]['sort_name']);
2903 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE));
2904 }
2905
2906 public function getSearchSortOptions() {
2907 $firstAlphabeticalContactBySortName = 'A Bobby, Bobby';
2908 $secondAlphabeticalContactBySortName = 'Aadvark, Bob';
2909 $secondAlphabeticalContactWithEmailBySortName = 'Bob, Bob';
2910 $firstAlphabeticalContactFirstNameBob = 'Aadvark, Bob';
2911 $secondAlphabeticalContactFirstNameBob = 'Bob, Bob';
2912 $firstByIDContactFirstNameBob = 'Bob, Bob';
2913 $secondByIDContactFirstNameBob = 'K Bobby, Bob';
2914 $firstContactByID = 'Bob, Bob';
2915 $secondContactByID = 'E Bobby, Bobby';
2916 $bobLikeEmail = 'A Bobby, Bobby';
2917
2918 return array(
2919 'empty_search_basic' => array(
2920 'search_parameters' => array('name' => '%'),
2921 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2922 'first_contact' => $firstAlphabeticalContactBySortName,
2923 'second_contact' => $secondAlphabeticalContactBySortName,
2924 ),
2925 'empty_search_basic_no_wildcard' => array(
2926 'search_parameters' => array('name' => '%'),
2927 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2928 'first_contact' => $firstAlphabeticalContactBySortName,
2929 'second_contact' => $secondAlphabeticalContactBySortName,
2930 ),
2931 'single_letter_search_basic' => array(
2932 'search_parameters' => array('name' => 'b'),
2933 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2934 'first_contact' => $firstAlphabeticalContactBySortName,
2935 'second_contact' => $secondAlphabeticalContactBySortName,
2936 ),
2937 'bob_search_basic' => array(
2938 'search_parameters' => array('name' => 'bob'),
2939 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2940 'first_contact' => $firstAlphabeticalContactBySortName,
2941 'second_contact' => $secondAlphabeticalContactBySortName,
2942 ),
fae75b58
SL
2943 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2944 // 'bob_search_no_orderby' => array(
2945 // 'search_parameters' => array('name' => 'bob'),
2946 // 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2947 // 'first_contact' => $firstContactByID,
2948 // 'second_contact' => $secondContactByID,
2949 //),
613643e0 2950 'bob_search_no_wildcard' => array(
2951 'search_parameters' => array('name' => 'bob'),
2952 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2953 'second_contact' => $bobLikeEmail,
2954 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2955 ),
2956 // This should be the same as just no wildcard as if we had an exactMatch while searching by
2957 // sort name it would rise to the top CRM-19547
2958 'bob_search_no_wildcard_no_orderby' => array(
2959 'search_parameters' => array('name' => 'bob'),
2960 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2961 'second_contact' => $bobLikeEmail,
2962 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2963 ),
2964 'first_name_search_basic' => array(
2965 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2966 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2967 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2968 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2969 ),
2970 'first_name_search_no_wildcard' => array(
2971 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2972 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2973 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2974 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2975 ),
fae75b58
SL
2976 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2977 //'first_name_search_no_orderby' => array(
2978 // 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2979 // 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2980 // 'first_contact' => $firstByIDContactFirstNameBob,
2981 // 'second_contact' => $secondByIDContactFirstNameBob,
2982 //),
613643e0 2983 'email_search_basic' => array(
2984 'search_parameters' => array('name' => 'bob', 'field_name' => 'email', 'table_name' => 'eml'),
2985 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2986 'first_contact' => $firstAlphabeticalContactBySortName,
2987 'second_contact' => $secondAlphabeticalContactWithEmailBySortName,
2988 ),
2989 );
2baa1e00 2990 }
2991
e9e27a80 2992 /**
2993 * Test that getquick returns contacts with an exact first name match first.
2994 */
2995 public function testGetQuickEmail() {
2996 $this->getQuickSearchSampleData();
1ca22999 2997 $loggedInContactID = $this->createLoggedInUser();
e9e27a80 2998 $result = $this->callAPISuccess('contact', 'getquick', array(
2999 'name' => 'c',
3000 ));
3001 $expectedData = array(
613643e0 3002 'A Bobby, Bobby :: bob@bobby.com',
e9e27a80 3003 'Bob, Bob :: bob@bob.com',
3004 'C Bobby, Bobby',
e9e27a80 3005 'H Bobby, Bobby :: bob@h.com',
1ca22999 3006 'Second Domain',
3007 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
e9e27a80 3008 );
1ca22999 3009 $this->assertEquals(6, $result['count']);
e9e27a80 3010 foreach ($expectedData as $index => $value) {
3011 $this->assertEquals($value, $result['values'][$index]['data']);
3012 }
7f6f3df1 3013 $result = $this->callAPISuccess('contact', 'getquick', array(
3014 'name' => 'h.',
3015 ));
3016 $expectedData = array(
3017 'H Bobby, Bobby :: bob@h.com',
3018 );
3019 foreach ($expectedData as $index => $value) {
3020 $this->assertEquals($value, $result['values'][$index]['data']);
3021 }
3022 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => FALSE));
3023 $result = $this->callAPISuccess('contact', 'getquick', array(
3024 'name' => 'h.',
3025 ));
3026 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE));
3027 $this->assertEquals(0, $result['count']);
e9e27a80 3028 }
3029
c37a2d66 3030 /**
3031 * Test that getquick returns contacts with an exact first name match first.
3032 */
3033 public function testGetQuickEmailACL() {
3034 $this->getQuickSearchSampleData();
1ca22999 3035 $loggedInContactID = $this->createLoggedInUser();
c37a2d66 3036 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
3037 $result = $this->callAPISuccess('contact', 'getquick', array(
3038 'name' => 'c',
3039 ));
3040 $this->assertEquals(0, $result['count']);
3041
3042 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
1ca22999 3043 CRM_Contact_BAO_Contact_Permission::cache($loggedInContactID, CRM_Core_Permission::VIEW, TRUE);
c37a2d66 3044 $result = $this->callAPISuccess('contact', 'getquick', array(
3045 'name' => 'c',
3046 ));
1ca22999 3047
3048 // Without the acl it would be 6 like the previous email getquick test.
3049 $this->assertEquals(5, $result['count']);
c37a2d66 3050 $expectedData = array(
613643e0 3051 'A Bobby, Bobby :: bob@bobby.com',
c37a2d66 3052 'Bob, Bob :: bob@bob.com',
3053 'C Bobby, Bobby',
1ca22999 3054 'Second Domain',
3055 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
c37a2d66 3056 );
3057 foreach ($expectedData as $index => $value) {
3058 $this->assertEquals($value, $result['values'][$index]['data']);
3059 }
3060 }
3061
2baa1e00 3062 /**
3063 * Test that getquick returns contacts with an exact first name match first.
3064 */
3065 public function testGetQuickExternalID() {
3066 $this->getQuickSearchSampleData();
3067 $result = $this->callAPISuccess('contact', 'getquick', array(
3068 'name' => 'b',
3069 'field_name' => 'external_identifier',
3070 'table_name' => 'cc',
3071 ));
3072 $this->assertEquals(0, $result['count']);
3073 $result = $this->callAPISuccess('contact', 'getquick', array(
3074 'name' => 'abc',
3075 'field_name' => 'external_identifier',
3076 'table_name' => 'cc',
3077 ));
3078 $this->assertEquals(1, $result['count']);
3079 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
3080 }
3081
3082 /**
3083 * Test that getquick returns contacts with an exact first name match first.
3084 */
3085 public function testGetQuickID() {
1ca22999 3086 $max = CRM_Core_DAO::singleValueQuery("SELECT max(id) FROM civicrm_contact");
2baa1e00 3087 $this->getQuickSearchSampleData();
3088 $result = $this->callAPISuccess('contact', 'getquick', array(
1ca22999 3089 'name' => $max + 2,
2baa1e00 3090 'field_name' => 'id',
3091 'table_name' => 'cc',
3092 ));
3093 $this->assertEquals(1, $result['count']);
613643e0 3094 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2baa1e00 3095 $result = $this->callAPISuccess('contact', 'getquick', array(
1ca22999 3096 'name' => $max + 2,
2baa1e00 3097 'field_name' => 'contact_id',
3098 'table_name' => 'cc',
3099 ));
3100 $this->assertEquals(1, $result['count']);
613643e0 3101 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2baa1e00 3102 }
3103
3104 /**
3105 * Test that getquick returns contacts with an exact first name match first.
ef3fd279 3106 *
3107 * Depending on the setting the sort name sort might click in next or not - test!
2baa1e00 3108 */
3109 public function testGetQuickFirstName() {
3110 $this->getQuickSearchSampleData();
ef3fd279 3111 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2baa1e00 3112 $result = $this->callAPISuccess('contact', 'getquick', array(
3113 'name' => 'Bob',
3114 'field_name' => 'first_name',
3115 'table_name' => 'cc',
3116 ));
e9e27a80 3117 $expected = array(
613643e0 3118 'Aadvark, Bob',
e9e27a80 3119 'Bob, Bob',
3120 'K Bobby, Bob',
3121 'A Bobby, Bobby',
3122 );
3123
3124 foreach ($expected as $index => $value) {
3125 $this->assertEquals($value, $result['values'][$index]['sort_name']);
3126 }
08f4ab8d 3127 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
3128 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
3129 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
fae75b58
SL
3130 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
3131 //$this->assertEquals('E Bobby, Bobby', $result['values'][1]['sort_name']);
08f4ab8d 3132 }
3133
1b9c2802 3134 /**
3135 * Test that getquick applies ACLs.
3136 */
3137 public function testGetQuickFirstNameACLs() {
3138 $this->getQuickSearchSampleData();
3139 $userID = $this->createLoggedInUser();
613643e0 3140 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE, 'search_autocomplete_count' => 15));
1b9c2802 3141 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
3142 $result = $this->callAPISuccess('contact', 'getquick', array(
3143 'name' => 'Bob',
3144 'field_name' => 'first_name',
3145 'table_name' => 'cc',
3146 ));
3147 $this->assertEquals(0, $result['count']);
3148
3149 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
3150 CRM_Contact_BAO_Contact_Permission::cache($userID, CRM_Core_Permission::VIEW, TRUE);
3151 $result = $this->callAPISuccess('contact', 'getquick', array(
3152 'name' => 'Bob',
3153 'field_name' => 'first_name',
3154 'table_name' => 'cc',
3155 ));
613643e0 3156 $this->assertEquals('K Bobby, Bob', $result['values'][2]['sort_name']);
1b9c2802 3157 // Without the ACL 9 would be bob@h.com.
613643e0 3158 $this->assertEquals('I Bobby, Bobby', $result['values'][10]['sort_name']);
1b9c2802 3159 }
3160
3161 /**
3162 * Full results returned.
3163 * @implements CRM_Utils_Hook::aclWhereClause
3164 *
3165 * @param string $type
3166 * @param array $tables
3167 * @param array $whereTables
3168 * @param int $contactID
3169 * @param string $where
3170 */
3171 public function aclWhereNoBobH($type, &$tables, &$whereTables, &$contactID, &$where) {
c37a2d66 3172 $where = " (email <> 'bob@h.com' OR email IS NULL) ";
1b9c2802 3173 $whereTables['civicrm_email'] = "LEFT JOIN civicrm_email e ON contact_a.id = e.contact_id";
3174 }
3175
e9e27a80 3176 /**
3177 * Test that getquick returns contacts with an exact last name match first.
3178 */
3179 public function testGetQuickLastName() {
3180 $this->getQuickSearchSampleData();
3181 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
3182 $result = $this->callAPISuccess('contact', 'getquick', array(
3183 'name' => 'Bob',
3184 'field_name' => 'last_name',
3185 'table_name' => 'cc',
3186 ));
3187 $expected = array(
3188 'Bob, Bob',
3189 'A Bobby, Bobby',
36575b09 3190 'B Bobby, Bobby',
e9e27a80 3191 );
3192
3193 foreach ($expected as $index => $value) {
3194 $this->assertEquals($value, $result['values'][$index]['sort_name']);
3195 }
3196 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
3197 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
3198 $this->assertEquals('Bob, Bob :: bob@bob.com', $result['values'][0]['data']);
3199 }
3200
3201 /**
3202 * Test that getquick returns contacts by city.
3203 */
3204 public function testGetQuickCity() {
3205 $this->getQuickSearchSampleData();
3206 $result = $this->callAPISuccess('contact', 'getquick', array(
3207 'name' => 'o',
3208 'field_name' => 'city',
3209 'table_name' => 'sts',
3210 ));
3211 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
3212 $result = $this->callAPISuccess('contact', 'getquick', array(
3213 'name' => 'n',
3214 'field_name' => 'city',
3215 'table_name' => 'sts',
3216 ));
3217 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
3218 $this->assertEquals('C Bobby, Bobby :: Whanganui', $result['values'][1]['data']);
3219 }
3220
08f4ab8d 3221 /**
3222 * Set up some sample data for testing quicksearch.
3223 */
3224 public function getQuickSearchSampleData() {
3225 $contacts = array(
e9e27a80 3226 array('first_name' => 'Bob', 'last_name' => 'Bob', 'external_identifier' => 'abc', 'email' => 'bob@bob.com'),
613643e0 3227 array('first_name' => 'Bobby', 'last_name' => 'E Bobby', 'external_identifier' => 'abcd'),
36575b09 3228 array(
3229 'first_name' => 'Bobby',
3230 'last_name' => 'B Bobby',
3231 'external_identifier' => 'bcd',
3232 'api.address.create' => array(
3233 'street_address' => 'Sesame Street',
3234 'city' => 'Toronto',
3235 'location_type_id' => 1,
3236 ),
3237 ),
3238 array(
3239 'first_name' => 'Bobby',
3240 'last_name' => 'C Bobby',
3241 'external_identifier' => 'bcde',
3242 'api.address.create' => array(
3243 'street_address' => 'Te huarahi',
3244 'city' => 'Whanganui',
3245 'location_type_id' => 1,
3246 ),
3247 ),
2baa1e00 3248 array('first_name' => 'Bobby', 'last_name' => 'D Bobby', 'external_identifier' => 'efg'),
613643e0 3249 array('first_name' => 'Bobby', 'last_name' => 'A Bobby', 'external_identifier' => 'hij', 'email' => 'bob@bobby.com'),
2baa1e00 3250 array('first_name' => 'Bobby', 'last_name' => 'F Bobby', 'external_identifier' => 'klm'),
3251 array('first_name' => 'Bobby', 'last_name' => 'G Bobby', 'external_identifier' => 'nop'),
e9e27a80 3252 array('first_name' => 'Bobby', 'last_name' => 'H Bobby', 'external_identifier' => 'qrs', 'email' => 'bob@h.com'),
2baa1e00 3253 array('first_name' => 'Bobby', 'last_name' => 'I Bobby'),
3254 array('first_name' => 'Bobby', 'last_name' => 'J Bobby'),
3255 array('first_name' => 'Bob', 'last_name' => 'K Bobby', 'external_identifier' => 'bcdef'),
613643e0 3256 array('first_name' => 'Bob', 'last_name' => 'Aadvark'),
08f4ab8d 3257 );
3258 foreach ($contacts as $type => $contact) {
3259 $contact['contact_type'] = 'Individual';
3260 $this->callAPISuccess('Contact', 'create', $contact);
3261 }
3262 }
3263
b2130237 3264 /**
381fa321 3265 * Test get ref api - gets a list of references to an entity.
b2130237 3266 */
00be9182 3267 public function testGetReferenceCounts() {
9c8096cb
TO
3268 $result = $this->callAPISuccess('Contact', 'create', array(
3269 'first_name' => 'Testily',
3270 'last_name' => 'McHaste',
3271 'contact_type' => 'Individual',
3272 'api.Address.replace' => array(
3273 'values' => array(),
3274 ),
3275 'api.Email.replace' => array(
3276 'values' => array(
3277 array(
3278 'email' => 'spam@dev.null',
3279 'is_primary' => 0,
3280 'location_type_id' => 1,
21dfd5f5 3281 ),
9c8096cb
TO
3282 ),
3283 ),
3284 'api.Phone.replace' => array(
3285 'values' => array(
3286 array(
3287 'phone' => '234-567-0001',
3288 'is_primary' => 1,
3289 'location_type_id' => 1,
3290 ),
3291 array(
3292 'phone' => '234-567-0002',
3293 'is_primary' => 0,
3294 'location_type_id' => 1,
3295 ),
3296 ),
3297 ),
3298 ));
3299
3300 //$dao = new CRM_Contact_BAO_Contact();
3301 //$dao->id = $result['id'];
3302 //$this->assertTrue((bool) $dao->find(TRUE));
3303 //
3304 //$refCounts = $dao->getReferenceCounts();
3305 //$this->assertTrue(is_array($refCounts));
3306 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
3307
3308 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
21dfd5f5 3309 'id' => $result['id'],
9c8096cb
TO
3310 ));
3311 $refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts['values']);
3312
3313 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
3314 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
3315 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
3316 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
3317 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
3318 }
3319
701a69da 3320 /**
3321 * Test the use of sql operators.
2d932085
CW
3322 * @param int $version
3323 * @dataProvider versionThreeAndFour
701a69da 3324 */
2d932085
CW
3325 public function testSQLOperatorsOnContactAPI($version) {
3326 $this->_apiversion = $version;
a75c13cc
EM
3327 $this->individualCreate();
3328 $this->organizationCreate();
3329 $this->householdCreate();
3330 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
3331 $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
3332 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
3333 $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
3334 }
9bee5ea2 3335
9bee5ea2 3336 /**
fe482240 3337 * CRM-14743 - test api respects search operators.
2d932085
CW
3338 * @param int $version
3339 * @dataProvider versionThreeAndFour
9bee5ea2 3340 */
2d932085
CW
3341 public function testGetModifiedDateByOperators($version) {
3342 $this->_apiversion = $version;
9bee5ea2
EM
3343 $preExistingContactCount = CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact');
3344 $contact1 = $this->individualCreate();
3345 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
3346 CRM_Core_DAO::executeQuery($sql);
3347 $contact2 = $this->individualCreate();
3348 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
3349 CRM_Core_DAO::executeQuery($sql);
3350 $contact3 = $this->householdCreate();
3351 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
3352 CRM_Core_DAO::executeQuery($sql);
3353 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
3354 $this->assertEquals($contacts['count'], 3);
3355 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
3356 $this->assertEquals($contacts['count'], $preExistingContactCount);
3357 }
2134e310 3358
2134e310 3359 /**
fe482240 3360 * CRM-14743 - test api respects search operators.
2d932085
CW
3361 * @param int $version
3362 * @dataProvider versionThreeAndFour
2134e310 3363 */
2d932085
CW
3364 public function testGetCreatedDateByOperators($version) {
3365 $this->_apiversion = $version;
2134e310
EM
3366 $preExistingContactCount = CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact');
3367 $contact1 = $this->individualCreate();
3368 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
3369 CRM_Core_DAO::executeQuery($sql);
3370 $contact2 = $this->individualCreate();
3371 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
3372 CRM_Core_DAO::executeQuery($sql);
3373 $contact3 = $this->householdCreate();
3374 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
3375 CRM_Core_DAO::executeQuery($sql);
3376 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
3377 $this->assertEquals($contacts['count'], 3);
3378 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
3379 $this->assertEquals($contacts['count'], $preExistingContactCount);
3380 }
e5fccefb
EM
3381
3382 /**
fe482240 3383 * CRM-14263 check that API is not affected by search profile related bug.
e5fccefb 3384 */
5896d037 3385 public function testReturnCityProfile() {
e5fccefb
EM
3386 $contactID = $this->individualCreate();
3387 CRM_Core_Config::singleton()->defaultSearchProfileID = 1;
5896d037 3388 $this->callAPISuccess('address', 'create', array(
92915c55
TO
3389 'contact_id' => $contactID,
3390 'city' => 'Cool City',
3391 'location_type_id' => 1,
3392 ));
e5fccefb
EM
3393 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
3394 $this->assertEquals(1, $result['count']);
3395 }
eaa112a5 3396
eaa112a5 3397 /**
701a69da 3398 * CRM-15443 - ensure getlist api does not return deleted contacts.
eaa112a5 3399 */
00be9182 3400 public function testGetlistExcludeConditions() {
9436d5d5 3401 $name = 'Scarabée';
45fcf8b7 3402 $contact = $this->individualCreate(array('last_name' => $name));
381fa321 3403 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
3404 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
3405 // We should get all but the deleted contact.
eaa112a5 3406 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
ba4a1892 3407 $this->assertEquals(2, $result['count']);
381fa321 3408 // Force-exclude the deceased contact.
5896d037 3409 $result = $this->callAPISuccess('contact', 'getlist', array(
92915c55
TO
3410 'input' => $name,
3411 'params' => array('is_deceased' => 0),
3412 ));
ba4a1892
TM
3413 $this->assertEquals(1, $result['count']);
3414 $this->assertEquals($contact, $result['values'][0]['id']);
eaa112a5 3415 }
92776611
CW
3416
3417 /**
fe482240 3418 * Test contact getactions.
92776611 3419 */
00be9182 3420 public function testGetActions() {
92776611
CW
3421 $description = "Getting the available actions for an entity.";
3422 $result = $this->callAPIAndDocument($this->_entity, 'getactions', array(), __FUNCTION__, __FILE__, $description);
3423 $expected = array(
3424 'create',
3425 'delete',
3426 'get',
3427 'getactions',
3428 'getcount',
3429 'getfields',
3430 'getlist',
3431 'getoptions',
3432 'getquick',
3433 'getrefcount',
3434 'getsingle',
3435 'getvalue',
3436 'merge',
3437 'proximity',
3438 'replace',
3439 'setvalue',
3440 'update',
3441 );
3442 $deprecated = array(
3443 'update',
3444 'getquick',
3445 );
3446 foreach ($expected as $action) {
3447 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
3448 }
3449 foreach ($deprecated as $action) {
3450 $this->assertArrayKeyExists($action, $result['deprecated']);
3451 }
3452 }
96025800 3453
ffe87781 3454 /**
3455 * Test the duplicate check function.
3456 */
3457 public function testDuplicateCheck() {
fedc3428 3458 $harry = array(
ffe87781 3459 'first_name' => 'Harry',
3460 'last_name' => 'Potter',
3461 'email' => 'harry@hogwarts.edu',
3462 'contact_type' => 'Individual',
fedc3428 3463 );
3464 $this->callAPISuccess('Contact', 'create', $harry);
ffe87781 3465 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
fedc3428 3466 'match' => $harry,
ffe87781 3467 ));
3468
3469 $this->assertEquals(1, $result['count']);
3470 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3471 'match' => array(
3472 'first_name' => 'Harry',
3473 'last_name' => 'Potter',
3474 'email' => 'no5@privet.drive',
3475 'contact_type' => 'Individual',
3476 ),
3477 ));
3478 $this->assertEquals(0, $result['count']);
fedc3428 3479 $this->callAPIFailure('Contact', 'create', array_merge($harry, array('dupe_check' => 1)));
ffe87781 3480 }
3481
a2dd33d3 3482 /**
3483 * Test the duplicate check function.
3484 */
3485 public function testDuplicateCheckRuleNotReserved() {
3486 $harry = array(
3487 'first_name' => 'Harry',
3488 'last_name' => 'Potter',
3489 'email' => 'harry@hogwarts.edu',
3490 'contact_type' => 'Individual',
3491 );
3492 $defaultRule = $this->callAPISuccess('RuleGroup', 'getsingle', array('used' => 'Unsupervised', 'is_reserved' => 1));
3493 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 0));
3494 $this->callAPISuccess('Contact', 'create', $harry);
3495 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3496 'match' => $harry,
3497 ));
3498
3499 $this->assertEquals(1, $result['count']);
3500 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 1));
3501 }
3502
3503 /**
3504 * Test variants on retrieving contact by type.
3505 */
46b3417a
CW
3506 public function testGetByContactType() {
3507 $individual = $this->callAPISuccess('Contact', 'create', array(
3508 'email' => 'individual@test.com',
3509 'contact_type' => 'Individual',
3510 ));
3511 $household = $this->callAPISuccess('Contact', 'create', array(
3512 'household_name' => 'household@test.com',
3513 'contact_type' => 'Household',
3514 ));
3515 $organization = $this->callAPISuccess('Contact', 'create', array(
3516 'organization_name' => 'organization@test.com',
3517 'contact_type' => 'Organization',
3518 ));
3519 // Test with id - getsingle will throw an exception if not found
3520 $this->callAPISuccess('Contact', 'getsingle', array(
3521 'id' => $individual['id'],
3522 'contact_type' => 'Individual',
3523 ));
3524 $this->callAPISuccess('Contact', 'getsingle', array(
3525 'id' => $individual['id'],
3526 'contact_type' => array('IN' => array('Individual')),
3527 'return' => 'id',
3528 ));
3529 $this->callAPISuccess('Contact', 'getsingle', array(
3530 'id' => $organization['id'],
3531 'contact_type' => array('IN' => array('Individual', 'Organization')),
3532 ));
3533 // Test as array
3534 $result = $this->callAPISuccess('Contact', 'get', array(
3535 'contact_type' => array('IN' => array('Individual', 'Organization')),
3536 'options' => array('limit' => 0),
3537 'return' => 'id',
3538 ));
3539 $this->assertContains($organization['id'], array_keys($result['values']));
3540 $this->assertContains($individual['id'], array_keys($result['values']));
3541 $this->assertNotContains($household['id'], array_keys($result['values']));
3542 // Test as string
3543 $result = $this->callAPISuccess('Contact', 'get', array(
3544 'contact_type' => 'Household',
3545 'options' => array('limit' => 0),
3546 'return' => 'id',
3547 ));
3548 $this->assertNotContains($organization['id'], array_keys($result['values']));
3549 $this->assertNotContains($individual['id'], array_keys($result['values']));
3550 $this->assertContains($household['id'], array_keys($result['values']));
3551 }
3552
12d73bba 3553 /**
3554 * Test merging 2 contacts.
5ea06a7b 3555 *
3556 * Someone kindly bequethed us the legacy of mixed up use of main_id & other_id
3557 * in the params for contact.merge api.
3558 *
3559 * This test protects that legacy.
12d73bba 3560 */
5ea06a7b 3561 public function testMergeBizzareOldParams() {
3562 $this->createLoggedInUser();
12d73bba 3563 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3564 $mainContact = $this->callAPISuccess('contact', 'create', $this->_params);
5ea06a7b 3565 $this->callAPISuccess('contact', 'merge', array(
3566 'main_id' => $mainContact['id'],
3567 'other_id' => $otherContact['id'],
3568 ));
12d73bba 3569 $contacts = $this->callAPISuccess('contact', 'get', $this->_params);
3570 $this->assertEquals($otherContact['id'], $contacts['id']);
5ea06a7b 3571 }
3572
3573 /**
3574 * Test merging 2 contacts.
3575 */
3576 public function testMerge() {
3577 $this->createLoggedInUser();
3578 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3579 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params);
3580 $this->callAPISuccess('contact', 'merge', array(
3581 'to_keep_id' => $retainedContact['id'],
3582 'to_remove_id' => $otherContact['id'],
3583 'auto_flip' => FALSE,
3584 ));
3585
3586 $contacts = $this->callAPISuccess('contact', 'get', $this->_params);
3587 $this->assertEquals($retainedContact['id'], $contacts['id']);
3588 $activity = $this->callAPISuccess('Activity', 'getsingle', array(
3589 'target_contact_id' => $retainedContact['id'],
3590 'activity_type_id' => 'Contact Merged',
3591 ));
3592 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($activity['activity_date_time'])));
f00283b5 3593 $activity2 = $this->callAPISuccess('Activity', 'getsingle', array(
3594 'target_contact_id' => $otherContact['id'],
3595 'activity_type_id' => 'Contact Deleted by Merge',
3596 ));
3597 $this->assertEquals($activity['id'], $activity2['parent_id']);
3598 $this->assertEquals('Normal', civicrm_api3('option_value', 'getvalue', array(
3599 'value' => $activity['priority_id'],
3600 'return' => 'label',
3601 'option_group_id' => 'priority',
3602 )));
12d73bba 3603
3604 }
3605
119664d6 3606 /**
3607 * Test merging 2 contacts with custom fields.
3608 *
3609 * @throws \Exception
3610 */
3611 public function testMergeCustomFields() {
3612 $contact1 = $this->individualCreate();
1600a9c0 3613 // Not sure this is quite right but it does get it into the file table
119664d6 3614 $file = $this->callAPISuccess('Attachment', 'create', [
1600a9c0 3615 'name' => 'header.txt',
3616 'mime_type' => 'text/plain',
3617 'description' => 'My test description',
3618 'content' => 'My test content',
3619 'entity_table' => 'civicrm_contact',
3620 'entity_id' => $contact1,
119664d6 3621 ]);
119664d6 3622
3623 $this->createCustomGroupWithFieldsOfAllTypes();
3624 $fileField = $this->getCustomFieldName('file');
3625 $linkField = $this->getCustomFieldName('link');
3626 $dateField = $this->getCustomFieldName('select_date');
3627 $selectField = $this->getCustomFieldName('select_string');
3628 $countryField = $this->getCustomFieldName('country');
3629
3630 $countriesByName = array_flip(CRM_Core_PseudoConstant::country(FALSE, FALSE));
3631 $customFieldValues = [
3632 // @todo fix the fatal bug on this & uncomment - see dev/core#723
1600a9c0 3633 $fileField => $file['id'],
119664d6 3634 $linkField => 'http://example.org',
3635 $dateField => '2018-01-01 17:10:56',
3636 $selectField => 'G',
3637 // Currently broken.
3638 //$countryField => $countriesByName['New Zealand'],
3639 ];
3640 $this->callAPISuccess('Contact', 'create', array_merge([
3641 'id' => $contact1,
3642 ], $customFieldValues));
3643
3644 $contact2 = $this->individualCreate();
3645 $this->callAPISuccess('contact', 'merge', [
3646 'to_keep_id' => $contact2,
3647 'to_remove_id' => $contact1,
3648 'auto_flip' => FALSE,
3649 ]);
3650 $contact = $this->callAPISuccessGetSingle('Contact', ['id' => $contact2, 'return' => array_keys($customFieldValues)]);
1600a9c0 3651 $this->assertEquals($contact2, CRM_Core_DAO::singleValueQuery('SELECT entity_id FROM civicrm_entity_file WHERE file_id = ' . $file['id']));
119664d6 3652 foreach ($customFieldValues as $key => $value) {
3653 $this->assertEquals($value, $contact[$key]);
3654 }
3655 }
3656
734cd0d5 3657 /**
3658 * Test retrieving merged contacts.
3659 *
3660 * The goal here is to start with a contact deleted by merged and find out the contact that is the current version of them.
3661 */
3662 public function testMergedGet() {
3663 $this->contactIDs[] = $this->individualCreate();
3664 $this->contactIDs[] = $this->individualCreate();
3665 $this->contactIDs[] = $this->individualCreate();
3666 $this->contactIDs[] = $this->individualCreate();
3667
3668 // First do an 'unnatural merge' - they 'like to merge into the lowest but this will mean that contact 0 merged to contact [3].
3669 // When the batch merge runs.... the new lowest contact is contact[1]. All contacts will merge into that contact,
3670 // including contact[3], resulting in only 3 existing at the end. For each contact the correct answer to 'who did I eventually
3671 // wind up being should be [1]
3672 $this->callAPISuccess('Contact', 'merge', ['to_remove_id' => $this->contactIDs[0], 'to_keep_id' => $this->contactIDs[3]]);
3673
3674 $this->callAPISuccess('Job', 'process_batch_merge', []);
3675 foreach ($this->contactIDs as $contactID) {
3676 if ($contactID === $this->contactIDs[1]) {
3677 continue;
3678 }
3679 $result = $this->callAPIAndDocument('Contact', 'getmergedto', ['sequential' => 1, 'contact_id' => $contactID], __FUNCTION__, __FILE__);
3680 $this->assertEquals(1, $result['count']);
3681 $this->assertEquals($this->contactIDs[1], $result['values'][0]['id']);
3682 }
3683
3684 $result = $this->callAPIAndDocument('Contact', 'getmergedfrom', ['contact_id' => $this->contactIDs[1]], __FUNCTION__, __FILE__)['values'];
3685 $mergedContactIds = array_merge(array_diff($this->contactIDs, [$this->contactIDs[1]]));
3686 $this->assertEquals($mergedContactIds, array_keys($result));
3687 }
3688
4d834a99 3689 /**
3690 * Test merging 2 contacts with delete to trash off.
3691 *
3692 * We are checking that there is no error due to attempting to add an activity for the
3693 * deleted contact.
3694 *
3695 * CRM-18307
3696 */
3697 public function testMergeNoTrash() {
3698 $this->createLoggedInUser();
3699 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => FALSE));
3700 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3701 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params);
3702 $this->callAPISuccess('contact', 'merge', array(
3703 'to_keep_id' => $retainedContact['id'],
3704 'to_remove_id' => $otherContact['id'],
3705 'auto_flip' => FALSE,
3706 ));
3707 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => TRUE));
3708 }
3709
00ed3e04
CB
3710 /**
3711 * Ensure format with return=group shows comma-separated group IDs.
3712 *
3713 * CRM-19426
3714 */
3715 public function testContactGetReturnGroup() {
3716 // Set up a contact, asser that they were created.
3717 $contact_params = array(
3718 'contact_type' => 'Individual',
3719 'first_name' => 'Test',
3720 'last_name' => 'Groupmember',
3721 'email' => 'test@example.org',
3722 );
3723 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3724 $this->assertEquals(0, $create_contact['is_error']);
3725 $this->assertInternalType('int', $create_contact['id']);
3726
3727 $created_contact_id = $create_contact['id'];
3728
3729 // Set up multiple groups, add the contact to the groups.
3730 $test_groups = array('Test group A', 'Test group B');
3731 foreach ($test_groups as $title) {
3732 // Use this contact as group owner, since we know they exist.
3733 $group_params = array(
3734 'title' => $title,
3735 'created_id' => $created_contact_id,
3736 );
3737 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3738 $this->assertEquals(0, $create_group['is_error']);
3739 $this->assertInternalType('int', $create_group['id']);
3740
3741 $created_group_ids[] = $create_group['id'];
3742
3743 // Add contact to the new group.
3744 $group_contact_params = array(
3745 'contact_id' => $created_contact_id,
3746 'group_id' => $create_group['id'],
3747 );
3748 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3749 $this->assertEquals(0, $create_group_contact['is_error']);
3750 $this->assertInternalType('int', $create_group_contact['added']);
3751 }
3752
3753 // Use the Contact,get API to retrieve the contact
3754 $contact_get_params = array(
3755 'id' => $created_contact_id,
3756 'return' => 'group',
3757 );
3758 $contact_get = $this->callApiSuccess('Contact', 'get', $contact_get_params);
3759 $this->assertInternalType('array', $contact_get['values'][$created_contact_id]);
3760 $this->assertInternalType('string', $contact_get['values'][$created_contact_id]['groups']);
3761
3762 // Ensure they are shown as being in each created group.
3763 $contact_group_ids = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3764 foreach ($created_group_ids as $created_group_id) {
3765 $this->assertContains($created_group_id, $contact_group_ids);
3766 }
3767 }
3768
309f98a9
SL
3769 /**
3770 * CRM-20144 Verify that passing title of group works as well as id
0c66b30c
SL
3771 * Tests the following formats
3772 * contact.get group='title1'
3773 * contact.get group=id1
309f98a9
SL
3774 */
3775 public function testContactGetWithGroupTitle() {
3776 // Set up a contact, asser that they were created.
3777 $contact_params = array(
3778 'contact_type' => 'Individual',
3779 'first_name' => 'Test2',
3780 'last_name' => 'Groupmember',
3781 'email' => 'test@example.org',
3782 );
3783 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3784 $created_contact_id = $create_contact['id'];
3785 // Set up multiple groups, add the contact to the groups.
3786 $test_groups = array('Test group C', 'Test group D');
3787 foreach ($test_groups as $title) {
3788 $group_params = array(
3789 'title' => $title,
3790 'created_id' => $created_contact_id,
3791 );
3792 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3793 $created_group_id = $create_group['id'];
3794
3795 // Add contact to the new group.
3796 $group_contact_params = array(
3797 'contact_id' => $created_contact_id,
3798 'group_id' => $create_group['id'],
3799 );
6d054a8e 3800 $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
309f98a9
SL
3801 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $title, 'return' => 'group'));
3802 $this->assertEquals(1, $contact_get['count']);
3803 $this->assertEquals($created_contact_id, $contact_get['id']);
3804 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3805 $this->assertContains((string) $create_group['id'], $contact_groups);
3806 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => $created_group_id, 'return' => 'group'));
3807 $this->assertEquals($created_contact_id, $contact_get2['id']);
3808 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3809 $this->assertContains((string) $create_group['id'], $contact_groups2);
3810 $this->callAPISuccess('group', 'delete', array('id' => $created_group_id));
3811 }
3812 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3813 }
3814
0c66b30c
SL
3815 /**
3816 * CRM-20144 Verify that passing title of group works as well as id
3817 * Tests the following formats
3818 * contact.get group=array('title1', title1)
3819 * contact.get group=array('IN' => array('title1', 'title2)
3820 */
3821 public function testContactGetWithGroupTitleMultipleGroups() {
d0aa0e47
SL
3822 $description = "Get all from group and display contacts.";
3823 $subFile = "GroupFilterUsingContactAPI";
0c66b30c
SL
3824 // Set up a contact, asser that they were created.
3825 $contact_params = array(
3826 'contact_type' => 'Individual',
3827 'first_name' => 'Test2',
3828 'last_name' => 'Groupmember',
3829 'email' => 'test@example.org',
3830 );
3831 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3832 $created_contact_id = $create_contact['id'];
3833 $createdGroupsTitles = $createdGroupsIds = array();
3834 // Set up multiple groups, add the contact to the groups.
3835 $test_groups = array('Test group C', 'Test group D');
3836 foreach ($test_groups as $title) {
3837 $group_params = array(
3838 'title' => $title,
3839 'created_id' => $created_contact_id,
3840 );
3841 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3842 $created_group_id = $create_group['id'];
3843 $createdGroupsIds[] = $create_group['id'];
3844 $createdGroupTitles[] = $title;
3845 // Add contact to the new group.
3846 $group_contact_params = array(
3847 'contact_id' => $created_contact_id,
3848 'group_id' => $create_group['id'],
3849 );
3850 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3851 }
3852 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $createdGroupTitles, 'return' => 'group'));
3853 $this->assertEquals(1, $contact_get['count']);
3854 $this->assertEquals($created_contact_id, $contact_get['id']);
3855 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3856 foreach ($createdGroupsIds as $id) {
3857 $this->assertContains((string) $id, $contact_groups);
3858 }
d0aa0e47 3859 $contact_get2 = $this->callAPIAndDocument('contact', 'get', array('group' => array('IN' => $createdGroupTitles)), __FUNCTION__, __FILE__, $description, $subFile);
0c66b30c
SL
3860 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array('IN' => $createdGroupTitles), 'return' => 'group'));
3861 $this->assertEquals($created_contact_id, $contact_get2['id']);
3862 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3863 foreach ($createdGroupsIds as $id) {
3864 $this->assertContains((string) $id, $contact_groups2);
3865 }
3866 foreach ($createdGroupsIds as $id) {
3867 $this->callAPISuccess('group', 'delete', array('id' => $id));
3868 }
3869 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3870 }
3871
b6b28d93
SL
3872 /**
3873 * CRM-20144 Verify that passing title of group works as well as id
3874 * Tests the following formats
3875 * contact.get group=array('title1' => 1)
3876 * contact.get group=array('titke1' => 1, 'title2' => 1)
3877 * contact.get group=array('id1' => 1)
3878 * contact.get group=array('id1' => 1, id2 => 1)
3879 */
3880 public function testContactGetWithGroupTitleMultipleGroupsLegacyFormat() {
3881 // Set up a contact, asser that they were created.
3882 $contact_params = array(
3883 'contact_type' => 'Individual',
3884 'first_name' => 'Test2',
3885 'last_name' => 'Groupmember',
3886 'email' => 'test@example.org',
3887 );
3888 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3889 $created_contact_id = $create_contact['id'];
3890 $createdGroupsTitles = $createdGroupsIds = array();
3891 // Set up multiple groups, add the contact to the groups.
3892 $test_groups = array('Test group C', 'Test group D');
3893 foreach ($test_groups as $title) {
3894 $group_params = array(
3895 'title' => $title,
3896 'created_id' => $created_contact_id,
3897 );
3898 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3899 $created_group_id = $create_group['id'];
3900 $createdGroupsIds[] = $create_group['id'];
3901 $createdGroupTitles[] = $title;
3902 // Add contact to the new group.
3903 $group_contact_params = array(
3904 'contact_id' => $created_contact_id,
3905 'group_id' => $create_group['id'],
3906 );
3907 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3908 }
3909 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1), 'return' => 'group'));
3910 $this->assertEquals(1, $contact_get['count']);
3911 $this->assertEquals($created_contact_id, $contact_get['id']);
3912 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3913 foreach ($createdGroupsIds as $id) {
3914 $this->assertContains((string) $id, $contact_groups);
3915 }
3916 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1, $createdGroupTitles[1] => 1), 'return' => 'group'));
3917 $this->assertEquals(1, $contact_get2['count']);
3918 $this->assertEquals($created_contact_id, $contact_get2['id']);
62b8c91c 3919 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
b6b28d93 3920 foreach ($createdGroupsIds as $id) {
62b8c91c 3921 $this->assertContains((string) $id, $contact_groups2);
b6b28d93
SL
3922 }
3923 $contact_get3 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1), 'return' => 'group'));
3924 $this->assertEquals($created_contact_id, $contact_get3['id']);
3925 $contact_groups3 = explode(',', $contact_get3['values'][$created_contact_id]['groups']);
3926 foreach ($createdGroupsIds as $id) {
62b8c91c 3927 $this->assertContains((string) $id, $contact_groups3);
b6b28d93
SL
3928 }
3929 $contact_get4 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1, $createdGroupsIds[1] => 1), 'return' => 'group'));
3930 $this->assertEquals($created_contact_id, $contact_get4['id']);
62b8c91c 3931 $contact_groups4 = explode(',', $contact_get4['values'][$created_contact_id]['groups']);
b6b28d93 3932 foreach ($createdGroupsIds as $id) {
62b8c91c 3933 $this->assertContains((string) $id, $contact_groups4);
b6b28d93
SL
3934 }
3935 foreach ($createdGroupsIds as $id) {
3936 $this->callAPISuccess('group', 'delete', array('id' => $id));
3937 }
3938 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3939 }
3940
4b2d36d7 3941 /**
3942 * Test the prox_distance functionality works.
3943 *
3944 * This is primarily testing functionality in the BAO_Query object that 'happens to be'
3945 * accessible via the api.
3946 */
3947 public function testContactGetProximity() {
3948 CRM_Core_Config::singleton()->geocodeMethod = 'CRM_Utils_MockGeocoder';
3949 $this->individualCreate();
3950 $contactID = $this->individualCreate();
3951 $this->callAPISuccess('Address', 'create', [
3952 'contact_id' => $contactID,
3953 'is_primary' => 1,
3954 'city' => 'Whangarei',
3955 'street_address' => 'Dent St',
3956 'geo_code_1' => '-35.8743325',
3957 'geo_code_2' => '174.4567136',
3958 'location_type_id' => 'Home',
3959 ]);
3960 $contact = $this->callAPISuccess('Contact', 'get', [
3961 'prox_distance' => 100,
3962 'prox_geo_code_1' => '-35.72192',
3963 'prox_geo_code_2' => '174.32034',
3964 ]);
3965 $this->assertEquals(1, $contact['count']);
3966 $this->assertEquals($contactID, $contact['id']);
3967 }
3968
83d02301
SL
3969 public function testLoggedInUserAPISupportToken() {
3970 $description = "Get contact id of the current logged in user";
3971 $subFile = "ContactIDOfLoggedInUserContactAPI";
3972 $cid = $this->createLoggedInUser();
3973 $contact = $this->callAPIAndDocument('contact', 'get', array('id' => 'user_contact_id'), __FUNCTION__, __FILE__, $description, $subFile);
3974 $this->assertEquals($cid, $contact['id']);
3975 }
3976
ec52a65a 3977 /**
3978 * @param $groupID
3979 * @param $contact
3980 */
3981 protected function putGroupContactCacheInClearableState($groupID, $contact) {
bb2d2335 3982 // We need to force the situation where there is invalid data in the cache and it
ec52a65a 3983 // is due to be cleared.
3984 CRM_Core_DAO::executeQuery("
3985 INSERT INTO civicrm_group_contact_cache (group_id, contact_id)
3986 VALUES ({$groupID}, {$contact['id']})
3987 ");
3988 CRM_Core_DAO::executeQuery("UPDATE civicrm_group SET cache_date = '2017-01-01'");
3989 // Reset so it does not skip.
3990 Civi::$statics['CRM_Contact_BAO_GroupContactCache']['is_refresh_init'] = FALSE;
3991 }
3992
5b1c3fee
VV
3993 /**
3994 * CRM-21041 Test if 'communication style' is set to site default if not passed.
2d932085
CW
3995 * @param int $version
3996 * @dataProvider versionThreeAndFour
5b1c3fee 3997 */
2d932085
CW
3998 public function testCreateCommunicationStyleUnset($version) {
3999 $this->_apiversion = $version;
5b1c3fee
VV
4000 $this->callAPISuccess('Contact', 'create', array(
4001 'first_name' => 'John',
4002 'last_name' => 'Doe',
39b959db
SL
4003 'contact_type' => 'Individual',
4004 )
5b1c3fee
VV
4005 );
4006 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
4007 $this->assertEquals(1, $result['communication_style_id']);
4008 }
459d57b3 4009
5b1c3fee
VV
4010 /**
4011 * CRM-21041 Test if 'communication style' is set if value is passed.
4012 */
4013 public function testCreateCommunicationStylePassed() {
4014 $this->callAPISuccess('Contact', 'create', array(
4015 'first_name' => 'John',
4016 'last_name' => 'Doe',
4017 'contact_type' => 'Individual',
4018 'communication_style_id' => 'Familiar',
4019 ));
4020 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
4021 $params = array(
4022 'option_group_id' => 'communication_style',
4023 'label' => 'Familiar',
4024 'return' => 'value',
4025 );
4026 $optionResult = civicrm_api3('OptionValue', 'get', $params);
4027 $communicationStyle = reset($optionResult['values']);
4028 $this->assertEquals($communicationStyle['value'], $result['communication_style_id']);
4029 }
4030
0db8cd85 4031 /**
4032 * Test that creating a contact with various contact greetings works.
2d932085 4033 * V3 Only.
0db8cd85 4034 */
4035 public function testContactGreetingsCreate() {
4036 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'last_name' => 'MouseMouse', 'contact_type' => 'Individual'));
4037 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
4038 $this->assertEquals('Dear Alan', $contact['postal_greeting_display']);
4039
4040 $contact = $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 2));
4041 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
4042 $this->assertEquals('Dear Alan MouseMouse', $contact['postal_greeting_display']);
4043
4044 $contact = $this->callAPISuccess('Contact', 'create', array('organization_name' => 'Alan\'s Show', 'contact_type' => 'Organization'));
4045 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting, addressee, email_greeting'));
4046 $this->assertEquals('', $contact['postal_greeting_display']);
4047 $this->assertEquals('', $contact['email_greeting_display']);
4048 $this->assertEquals('Alan\'s Show', $contact['addressee_display']);
4049 }
4050
7c990617 4051 /**
4052 * Test that creating a contact with various contact greetings works.
4053 */
4054 public function testContactGreetingsCreateWithCustomField() {
4055 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
4056 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'contact_type' => 'Individual', 'custom_' . $ids['custom_field_id'] => 'Mice'));
4057
4058 // Change postal greeting to involve a custom field.
4059 $postalOption = $this->callAPISuccessGetSingle('OptionValue', array('option_group_id' => 'postal_greeting', 'filter' => 1, 'is_default' => 1));
4060 $this->callAPISuccess('OptionValue', 'create', array(
4061 'id' => $postalOption['id'],
4062 'name' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
4063 'label' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
4064 ));
4065
4066 // Update contact & see if postal greeting now reflects the new string.
4067 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'last_name' => 'MouseyMousey'));
4068 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
4069 $this->assertEquals('Dear Alan Mice', $contact['postal_greeting_display']);
4070
57369d23 4071 // Set contact to have no postal greeting & check it is correct.
4072 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 'null'));
4073 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
4074 $this->assertEquals('', $contact['postal_greeting_display']);
4075
7c990617 4076 //Cleanup
4077 $this->callAPISuccess('OptionValue', 'create', array('id' => $postalOption['id'], 'name' => 'Dear {contact.first_name}'));
4078 $this->customFieldDelete($ids['custom_field_id']);
4079 $this->customGroupDelete($ids['custom_group_id']);
4080 }
4081
1af690c4 4082 /**
4083 * Test getunique api call for Contact entity
4084 */
4085 public function testContactGetUnique() {
4086 $result = $this->callAPIAndDocument($this->_entity, 'getunique', array(), __FUNCTION__, __FILE__);
4087 $this->assertEquals(1, $result['count']);
4088 $this->assertEquals(array('external_identifier'), $result['values']['UI_external_identifier']);
4089 }
4090
3c8e2962
PN
4091 /**
4092 * API test to retrieve contact from group having different group title and name.
4093 */
4094 public function testContactGetFromGroup() {
4095 $groupId = $this->groupCreate([
4096 'name' => 'Test_Group',
4097 'domain_id' => 1,
4098 'title' => 'New Test Group Created',
4099 'description' => 'New Test Group Created',
4100 'is_active' => 1,
4101 'visibility' => 'User and User Admin Only',
4102 ]);
4103 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
4104 $groupContactCreateParams = array(
4105 'contact_id' => $contact['id'],
4106 'group_id' => $groupId,
4107 'status' => 'Pending',
4108 );
4109 $groupContact = $this->callAPISuccess('groupContact', 'create', $groupContactCreateParams);
4110 $groupGetContact = $this->CallAPISuccess('groupContact', 'get', $groupContactCreateParams);
4111 $this->CallAPISuccess('Contact', 'getcount', [
4112 'group' => "Test_Group",
4113 ]);
4114 }
4115
def88c52 4116 /**
4117 * Test the related contacts filter.
4118 *
4119 * @throws \Exception
4120 */
2bedfb3f
HA
4121 public function testSmartGroupsForRelatedContacts() {
4122 $rtype1 = $this->callAPISuccess('relationship_type', 'create', array(
4123 "name_a_b" => uniqid() . " Child of",
4124 "name_b_a" => uniqid() . " Parent of",
4125 ));
4126 $rtype2 = $this->callAPISuccess('relationship_type', 'create', array(
4127 "name_a_b" => uniqid() . " Household Member of",
4128 "name_b_a" => uniqid() . " Household Member is",
4129 ));
4130 $h1 = $this->householdCreate();
4131 $c1 = $this->individualCreate(array('last_name' => 'Adams'));
4132 $c2 = $this->individualCreate(array('last_name' => 'Adams'));
4133 $this->callAPISuccess('relationship', 'create', array(
4134 'contact_id_a' => $c1,
4135 'contact_id_b' => $c2,
4136 'is_active' => 1,
39b959db
SL
4137 // Child of
4138 'relationship_type_id' => $rtype1['id'],
2bedfb3f
HA
4139 ));
4140 $this->callAPISuccess('relationship', 'create', array(
4141 'contact_id_a' => $c1,
4142 'contact_id_b' => $h1,
4143 'is_active' => 1,
39b959db
SL
4144 // Household Member of
4145 'relationship_type_id' => $rtype2['id'],
2bedfb3f
HA
4146 ));
4147 $this->callAPISuccess('relationship', 'create', array(
4148 'contact_id_a' => $c2,
4149 'contact_id_b' => $h1,
4150 'is_active' => 1,
39b959db
SL
4151 // Household Member of
4152 'relationship_type_id' => $rtype2['id'],
2bedfb3f
HA
4153 ));
4154
4155 $ssParams = array(
4156 'formValues' => array(
39b959db
SL
4157 // Child of
4158 'display_relationship_type' => $rtype1['id'] . '_a_b',
2bedfb3f
HA
4159 'sort_name' => 'Adams',
4160 ),
4161 );
4162 $g1ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
4163 $ssParams = array(
4164 'formValues' => array(
39b959db
SL
4165 // Household Member of
4166 'display_relationship_type' => $rtype2['id'] . '_a_b',
2bedfb3f
HA
4167 ),
4168 );
4169 $g2ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
68f8975b
HA
4170 $ssParams = array(
4171 'formValues' => array(
39b959db
SL
4172 // Household Member is
4173 'display_relationship_type' => $rtype2['id'] . '_b_a',
68f8975b
HA
4174 ),
4175 );
4176 // the reverse of g2 which adds another layer for overlap at related contact filter
4177 $g3ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
2bedfb3f
HA
4178 CRM_Contact_BAO_GroupContactCache::loadAll();
4179 $g1Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g1ID));
4180 $g2Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g2ID));
68f8975b 4181 $g3Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g3ID));
2bedfb3f
HA
4182 $this->assertTrue($g1Contacts['count'] == 1);
4183 $this->assertTrue($g2Contacts['count'] == 2);
68f8975b 4184 $this->assertTrue($g3Contacts['count'] == 1);
2bedfb3f
HA
4185 }
4186
9e4f43aa
SL
4187 /**
4188 * Test creating a note from the contact.create API call when only passing the note as a string.
4189 */
4190 public function testCreateNoteinCreate() {
4191 $loggedInContactID = $this->createLoggedInUser();
4192 $this->_params['note'] = "Test note created by API Call as a String";
4193 $contact = $this->callAPISuccess('Contact', 'create', $this->_params);
4194 $note = $this->callAPISuccess('Note', 'get', ['contact_id' => $loggedInContactID]);
4195 $this->assertEquals($note['values'][$note['id']]['note'], "Test note created by API Call as a String");
4196 $note = $this->callAPISuccess('Note', 'get', ['entity_id' => $contact['id']]);
4197 $this->assertEquals($note['values'][$note['id']]['note'], "Test note created by API Call as a String");
4198 $this->callAPISuccess('Contact', 'delete', ['id' => $contact['id'], 'skip_undelete' => TRUE]);
4199 }
4200
4201 /**
4202 * Test Creating a note from the contact.create api call when passing the note params as an array.
4203 */
4204 public function testCreateNoteinCreateArrayFormat() {
4205 $contact1 = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'last_name' => 'MouseMouse', 'contact_type' => 'Individual'));
4206 $this->_params['note'] = [['note' => "Test note created by API Call as array", 'contact_id' => $contact1['id']]];
4207 $contact2 = $this->callAPISuccess('Contact', 'create', $this->_params);
4208 $note = $this->callAPISuccess('Note', 'get', ['contact_id' => $contact1['id']]);
4209 $this->assertEquals($note['values'][$note['id']]['note'], "Test note created by API Call as array");
4210 $note = $this->callAPISuccess('Note', 'get', ['entity_id' => $contact2['id']]);
4211 $this->assertEquals($note['values'][$note['id']]['note'], "Test note created by API Call as array");
4212 }
4213
0cf0a3f3
PF
4214 /**
4215 * Verify that passing tag IDs to Contact.get works
4216 *
4217 * Tests the following formats
4218 * - Contact.get tag='id1'
4219 * - Contact.get tag='id1,id2'
4220 * - Contact.get tag='id1, id2'
4221 */
4222 public function testContactGetWithTag() {
4223 $contact = $this->callApiSuccess('Contact', 'create', [
4224 'contact_type' => 'Individual',
4225 'first_name' => 'Test',
4226 'last_name' => 'Tagged',
4227 'email' => 'test@example.org',
4228 ]);
4229 $tags = [];
4230 foreach (['Tag A', 'Tag B'] as $name) {
4231 $tags[] = $this->callApiSuccess('Tag', 'create', [
39b959db 4232 'name' => $name,
0cf0a3f3
PF
4233 ]);
4234 }
4235
4236 // assign contact to "Tag B"
4237 $this->callApiSuccess('EntityTag', 'create', [
4238 'entity_table' => 'civicrm_contact',
4239 'entity_id' => $contact['id'],
4240 'tag_id' => $tags[1]['id'],
4241 ]);
4242
4243 // test format Contact.get tag='id1'
4244 $contact_get = $this->callAPISuccess('Contact', 'get', [
4245 'tag' => $tags[1]['id'],
4246 'return' => 'tag',
4247 ]);
4248 $this->assertEquals(1, $contact_get['count']);
4249 $this->assertEquals($contact['id'], $contact_get['id']);
4250 $this->assertEquals('Tag B', $contact_get['values'][$contact['id']]['tags']);
4251
4252 // test format Contact.get tag='id1,id2'
4253 $contact_get = $this->callAPISuccess('Contact', 'get', [
4254 'tag' => $tags[0]['id'] . ',' . $tags[1]['id'],
4255 'return' => 'tag',
4256 ]);
4257 $this->assertEquals(1, $contact_get['count']);
4258 $this->assertEquals($contact['id'], $contact_get['id']);
4259 $this->assertEquals('Tag B', $contact_get['values'][$contact['id']]['tags']);
4260
4261 // test format Contact.get tag='id1, id2'
4262 $contact_get = $this->callAPISuccess('Contact', 'get', [
4263 'tag' => $tags[0]['id'] . ', ' . $tags[1]['id'],
4264 'return' => 'tag',
4265 ]);
4266 $this->assertEquals(1, $contact_get['count']);
4267 $this->assertEquals($contact['id'], $contact_get['id']);
4268 $this->assertEquals('Tag B', $contact_get['values'][$contact['id']]['tags']);
4269
4270 foreach ($tags as $tag) {
4271 $this->callAPISuccess('Tag', 'delete', ['id' => $tag['id']]);
4272 }
4273 $this->callAPISuccess('Contact', 'delete', [
4274 'id' => $contact['id'],
39b959db 4275 'skip_undelete' => TRUE,
0cf0a3f3
PF
4276 ]);
4277 }
4278
6a488035 4279}