4 * File for the TestContact class.
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
11 * GNU Affero General Public License version 3
12 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
15 * This file is part of CiviCRM
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.
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.
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/>.
33 * Test APIv3 civicrm_contact* functions
35 * @package CiviCRM_APIv3
36 * @subpackage API_Contact
39 class api_v3_ContactTest
extends CiviUnitTestCase
{
40 public $DBResetRequired = FALSE;
41 protected $_apiversion;
45 protected $_contactID;
46 protected $_financialTypeId = 1;
49 * Test setup for every test.
51 * Connect to the database, truncate the tables that will be used
52 * and redirect stdin to a temporary file
54 public function setUp() {
55 // Connect to the database.
57 $this->_apiversion
= 3;
58 $this->_entity
= 'contact';
59 $this->_params
= array(
60 'first_name' => 'abc1',
61 'contact_type' => 'Individual',
62 'last_name' => 'xyz1',
67 * Restore the DB for the next test.
71 public function tearDown() {
72 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
73 // truncate a few tables
74 $tablesToTruncate = array(
76 'civicrm_contribution',
79 'civicrm_relationship',
83 'civicrm_acl_contact_cache',
86 $this->quickCleanup($tablesToTruncate, TRUE);
91 * Test civicrm_contact_create.
93 * Verify that attempt to create individual contact with only
94 * first and last names succeeds
96 public function testAddCreateIndividual() {
97 $oldCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
99 'first_name' => 'abc1',
100 'contact_type' => 'Individual',
101 'last_name' => 'xyz1',
104 $contact = $this->callAPISuccess('contact', 'create', $params);
105 $this->assertTrue(is_numeric($contact['id']));
106 $this->assertTrue($contact['id'] > 0);
107 $newCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
108 $this->assertEquals($oldCount +
1, $newCount);
110 $this->assertDBState('CRM_Contact_DAO_Contact',
117 * Test civicrm_contact_create.
119 * Verify that preferred language can be set.
121 public function testAddCreateIndividualWithPreferredLanguage() {
123 'first_name' => 'abc1',
124 'contact_type' => 'Individual',
125 'last_name' => 'xyz1',
126 'preferred_language' => 'es_ES',
129 $contact = $this->callAPISuccess('contact', 'create', $params);
130 $this->getAndCheck($params, $contact['id'], 'Contact');
134 * Test civicrm_contact_create with sub-types.
136 * Verify that sub-types are created successfully and not deleted by subsequent updates.
138 public function testIndividualSubType() {
140 'first_name' => 'test abc',
141 'contact_type' => 'Individual',
142 'last_name' => 'test xyz',
143 'contact_sub_type' => array('Student', 'Staff'),
145 $contact = $this->callAPISuccess('contact', 'create', $params);
146 $cid = $contact['id'];
150 'middle_name' => 'foo',
152 $this->callAPISuccess('contact', 'create', $params);
153 unset($params['middle_name']);
155 $contact = $this->callAPISuccess('contact', 'get', $params);
157 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
161 * Verify that attempt to create contact with empty params fails.
163 public function testCreateEmptyContact() {
164 $this->callAPIFailure('contact', 'create', array());
168 * Verify that attempt to create contact with bad contact type fails.
170 public function testCreateBadTypeContact() {
172 'email' => 'man1@yahoo.com',
173 'contact_type' => 'Does not Exist',
175 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
179 * Verify that attempt to create individual contact without required fields fails.
181 public function testCreateBadRequiredFieldsIndividual() {
183 'middle_name' => 'This field is not required',
184 'contact_type' => 'Individual',
186 $this->callAPIFailure('contact', 'create', $params);
190 * Verify that attempt to create household contact without required fields fails.
192 public function testCreateBadRequiredFieldsHousehold() {
194 'middle_name' => 'This field is not required',
195 'contact_type' => 'Household',
197 $this->callAPIFailure('contact', 'create', $params);
201 * Test required field check.
203 * Verify that attempt to create organization contact without required fields fails.
205 public function testCreateBadRequiredFieldsOrganization() {
207 'middle_name' => 'This field is not required',
208 'contact_type' => 'Organization',
211 $this->callAPIFailure('contact', 'create', $params);
215 * Verify that attempt to create individual contact with only an email succeeds.
217 public function testCreateEmailIndividual() {
220 'email' => 'man3@yahoo.com',
221 'contact_type' => 'Individual',
222 'location_type_id' => 1,
225 $contact = $this->callAPISuccess('contact', 'create', $params);
227 $this->assertEquals(3, $contact['id']);
228 $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id']));
229 $this->assertEquals(1, $email['count']);
230 $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']);
232 $this->callAPISuccess('contact', 'delete', $contact);
236 * Test creating individual by name.
238 * Verify create individual contact with only first and last names succeeds.
240 public function testCreateNameIndividual() {
242 'first_name' => 'abc1',
243 'contact_type' => 'Individual',
244 'last_name' => 'xyz1',
247 $this->callAPISuccess('contact', 'create', $params);
251 * Test creating individual by display_name.
253 * Display name & sort name should be set.
255 public function testCreateDisplayNameIndividual() {
257 'display_name' => 'abc1',
258 'contact_type' => 'Individual',
261 $contact = $this->callAPISuccess('contact', 'create', $params);
262 $params['sort_name'] = 'abc1';
263 $this->getAndCheck($params, $contact['id'], 'contact');
267 * Test old keys still work.
269 * Verify that attempt to create individual contact with
270 * first and last names and old key values works
272 public function testCreateNameIndividualOldKeys() {
274 'individual_prefix' => 'Dr.',
275 'first_name' => 'abc1',
276 'contact_type' => 'Individual',
277 'last_name' => 'xyz1',
278 'individual_suffix' => 'Jr.',
281 $contact = $this->callAPISuccess('contact', 'create', $params);
282 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
284 $this->assertArrayKeyExists('prefix_id', $result);
285 $this->assertArrayKeyExists('suffix_id', $result);
286 $this->assertArrayKeyExists('gender_id', $result);
287 $this->assertEquals(4, $result['prefix_id']);
288 $this->assertEquals(1, $result['suffix_id']);
292 * Test preferred keys work.
294 * Verify that attempt to create individual contact with
295 * first and last names and old key values works
297 public function testCreateNameIndividualRecommendedKeys2() {
299 'prefix_id' => 'Dr.',
300 'first_name' => 'abc1',
301 'contact_type' => 'Individual',
302 'last_name' => 'xyz1',
303 'suffix_id' => 'Jr.',
304 'gender_id' => 'Male',
307 $contact = $this->callAPISuccess('contact', 'create', $params);
308 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
310 $this->assertArrayKeyExists('prefix_id', $result);
311 $this->assertArrayKeyExists('suffix_id', $result);
312 $this->assertArrayKeyExists('gender_id', $result);
313 $this->assertEquals(4, $result['prefix_id']);
314 $this->assertEquals(1, $result['suffix_id']);
318 * Test household name is sufficient for create.
320 * Verify that attempt to create household contact with only
321 * household name succeeds
323 public function testCreateNameHousehold() {
325 'household_name' => 'The abc Household',
326 'contact_type' => 'Household',
328 $this->callAPISuccess('contact', 'create', $params);
332 * Test organization name is sufficient for create.
334 * Verify that attempt to create organization contact with only
335 * organization name succeeds.
337 public function testCreateNameOrganization() {
339 'organization_name' => 'The abc Organization',
340 'contact_type' => 'Organization',
342 $this->callAPISuccess('contact', 'create', $params);
346 * Verify that attempt to create organization contact without organization name fails.
348 public function testCreateNoNameOrganization() {
350 'first_name' => 'The abc Organization',
351 'contact_type' => 'Organization',
353 $this->callAPIFailure('contact', 'create', $params);
357 * Check with complete array + custom field.
359 * Note that the test is written on purpose without any
360 * variables specific to participant so it can be replicated into other entities
361 * and / or moved to the automated test suite
363 public function testCreateWithCustom() {
364 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
366 $params = $this->_params
;
367 $params['custom_' . $ids['custom_field_id']] = "custom string";
368 $description = "This demonstrates setting a custom field through the API.";
369 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
371 $check = $this->callAPISuccess($this->_entity
, 'get', array(
372 'return.custom_' . $ids['custom_field_id'] => 1,
373 'id' => $result['id'],
375 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
377 $this->customFieldDelete($ids['custom_field_id']);
378 $this->customGroupDelete($ids['custom_group_id']);
382 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
384 public function testCreateWithNULLCustomCRM12773() {
385 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
386 $params = $this->_params
;
387 $params['custom_' . $ids['custom_field_id']] = NULL;
388 $this->callAPISuccess('contact', 'create', $params);
389 $this->customFieldDelete($ids['custom_field_id']);
390 $this->customGroupDelete($ids['custom_group_id']);
394 * CRM-14232 test preferred language set to site default if not passed.
396 public function testCreatePreferredLanguageUnset() {
397 $this->callAPISuccess('Contact', 'create', array(
398 'first_name' => 'Snoop',
399 'last_name' => 'Dog',
400 'contact_type' => 'Individual')
402 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
403 $this->assertEquals('en_US', $result['preferred_language']);
407 * CRM-14232 test preferred language returns setting if not passed.
409 public function testCreatePreferredLanguageSet() {
410 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'fr_FR'));
411 $this->callAPISuccess('Contact', 'create', array(
412 'first_name' => 'Snoop',
413 'last_name' => 'Dog',
414 'contact_type' => 'Individual',
416 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
417 $this->assertEquals('fr_FR', $result['preferred_language']);
421 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
423 public function testCreatePreferredLanguageNull() {
424 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
425 $this->callAPISuccess('Contact', 'create', array(
426 'first_name' => 'Snoop',
427 'last_name' => 'Dog',
428 'contact_type' => 'Individual',
431 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
432 $this->assertEquals(NULL, $result['preferred_language']);
436 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
438 public function testCreatePreferredLanguagePassed() {
439 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
440 $this->callAPISuccess('Contact', 'create', array(
441 'first_name' => 'Snoop',
442 'last_name' => 'Dog',
443 'contact_type' => 'Individual',
444 'preferred_language' => 'en_AU',
446 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
447 $this->assertEquals('en_AU', $result['preferred_language']);
451 * CRM-15792 - create/update datetime field for contact.
453 public function testCreateContactCustomFldDateTime() {
454 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
455 $dateTime = CRM_Utils_Date
::currentDBDate();
456 //check date custom field is saved along with time when time_format is set
458 'first_name' => 'abc3',
459 'last_name' => 'xyz3',
460 'contact_type' => 'Individual',
461 'email' => 'man3@yahoo.com',
462 'api.CustomField.create' => array(
463 'custom_group_id' => $customGroup['id'],
464 'name' => 'test_datetime',
465 'label' => 'Demo Date',
466 'html_type' => 'Select Date',
467 'data_type' => 'Date',
471 'is_searchable' => 0,
476 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
477 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
478 $this->assertNotNull($result['id']);
479 $this->assertNotNull($customFldId);
482 'id' => $result['id'],
483 "custom_{$customFldId}" => $dateTime,
484 'api.CustomValue.get' => 1,
487 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
488 $this->assertNotNull($result['id']);
489 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
490 $this->assertNotNull($customFldDate);
491 $this->assertEquals($dateTime, $customFldDate);
492 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
493 $dateTime = date('Ymd');
494 //date custom field should not contain time part when time_format is null
496 'id' => $result['id'],
497 'api.CustomField.create' => array(
498 'id' => $customFldId,
499 'html_type' => 'Select Date',
500 'data_type' => 'Date',
503 'api.CustomValue.create' => array(
504 'id' => $customValueId,
505 'entity_id' => $result['id'],
506 "custom_{$customFldId}" => $dateTime,
508 'api.CustomValue.get' => 1,
510 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
511 $this->assertNotNull($result['id']);
512 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
513 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
514 $this->assertNotNull($customFldDate);
515 $this->assertEquals($dateTime, $customFldDate);
516 $this->assertEquals(000000, $customFldTime);
517 $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
);
522 * Test creating a current employer through API.
524 public function testContactCreateCurrentEmployer() {
525 // Here we will just do the get for set-up purposes.
526 $count = $this->callAPISuccess('contact', 'getcount', array(
527 'organization_name' => 'new employer org',
528 'contact_type' => 'Organization',
530 $this->assertEquals(0, $count);
531 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
532 'current_employer' => 'new employer org',
535 // do it again as an update to check it doesn't cause an error
536 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
537 'current_employer' => 'new employer org',
538 'id' => $employerResult['id'],
542 $this->callAPISuccess('contact', 'getcount', array(
543 'organization_name' => 'new employer org',
544 'contact_type' => 'Organization',
548 $result = $this->callAPISuccess('contact', 'getsingle', array(
549 'id' => $employerResult['id'],
552 $this->assertEquals('new employer org', $result['current_employer']);
557 * Test creating a current employer through API.
559 * Check it will re-activate a de-activated employer
561 public function testContactCreateDuplicateCurrentEmployerEnables() {
562 // Set up - create employer relationship.
563 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
564 'current_employer' => 'new employer org',
567 $relationship = $this->callAPISuccess('relationship', 'get', array(
568 'contact_id_a' => $employerResult['id'],
571 //disable & check it is disabled
572 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
573 $this->callAPISuccess('relationship', 'getvalue', array(
574 'id' => $relationship['id'],
575 'return' => 'is_active',
578 // Re-set the current employer - thus enabling the relationship.
579 $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
580 'current_employer' => 'new employer org',
581 'id' => $employerResult['id'],
584 //check is_active is now 1
585 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
586 'return' => 'is_active',
588 $this->assertEquals(1, $relationship['is_active']);
592 * Check deceased contacts are not retrieved.
594 * Note at time of writing the default is to return default. This should possibly be changed & test added.
596 public function testGetDeceasedRetrieved() {
597 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
598 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
599 'first_name' => 'bb',
600 'last_name' => 'ccc',
601 'contact_type' => 'Individual',
604 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
605 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
609 * Test that sort works - old syntax.
611 public function testGetSort() {
612 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
613 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
614 'first_name' => 'bb',
615 'last_name' => 'ccc',
616 'contact_type' => 'Individual',
618 $result = $this->callAPISuccess($this->_entity
, 'get', array(
619 'sort' => 'first_name ASC',
620 'return.first_name' => 1,
623 'contact_type' => 'Individual',
626 $this->assertEquals('abc1', $result['values'][0]['first_name']);
627 $result = $this->callAPISuccess($this->_entity
, 'get', array(
628 'sort' => 'first_name DESC',
629 'return.first_name' => 1,
633 $this->assertEquals('bb', $result['values'][0]['first_name']);
635 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
636 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
640 * Test that we can retrieve contacts using array syntax.
642 * I.e 'id' => array('IN' => array('3,4')).
644 public function testGetINIDArray() {
645 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
646 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
647 'first_name' => 'bb',
648 'last_name' => 'ccc',
649 'contact_type' => 'Individual',
651 $c3 = $this->callAPISuccess($this->_entity
, 'create', array(
652 'first_name' => 'hh',
654 'contact_type' => 'Individual',
656 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
657 $this->assertEquals(2, $result['count']);
658 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
659 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
660 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
661 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
665 * Test variants on deleted behaviour.
667 public function testGetDeleted() {
668 $params = $this->_params
;
669 $contact1 = $this->callAPISuccess('contact', 'create', $params);
670 $params['is_deleted'] = 1;
671 $params['last_name'] = 'bcd';
672 $contact2 = $this->callAPISuccess('contact', 'create', $params);
673 $countActive = $this->callAPISuccess('contact', 'getcount', array(
674 'showAll' => 'active',
675 'contact_type' => 'Individual',
677 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all', 'contact_type' => 'Individual'));
678 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash', 'contact_type' => 'Individual'));
679 $countDefault = $this->callAPISuccess('contact', 'getcount', array('contact_type' => 'Individual'));
680 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
681 'contact_type' => 'Individual',
682 'contact_is_deleted' => 1,
684 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
685 'contact_is_deleted' => 0,
686 'contact_type' => 'Individual',
688 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
689 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
690 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected');
691 $this->assertEquals(1, $countActive);
692 $this->assertEquals(1, $countTrash);
693 $this->assertEquals(2, $countAll);
694 $this->assertEquals(1, $countDeleted);
695 $this->assertEquals(1, $countDefault, 'Only active by default in line');
699 * Test that sort works - new syntax.
701 public function testGetSortNewSyntax() {
702 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
703 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
704 'first_name' => 'bb',
705 'last_name' => 'ccc',
706 'contact_type' => 'Individual',
708 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
709 'return' => 'first_name',
710 'contact_type' => 'Individual',
713 'sort' => 'first_name',
716 $this->assertEquals('abc1', $result);
718 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
719 'return' => 'first_name',
720 'contact_type' => 'Individual',
723 'sort' => 'first_name DESC',
726 $this->assertEquals('bb', $result);
728 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
729 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
733 * Test sort and limit for chained relationship get.
735 * https://issues.civicrm.org/jira/browse/CRM-15983
737 public function testSortLimitChainedRelationshipGetCRM15983() {
739 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
740 'first_name' => 'Jules',
741 'last_name' => 'Smos',
742 'contact_type' => 'Individual',
745 // Create another contact with two relationships.
746 $create_params = array(
747 'first_name' => 'Jos',
748 'last_name' => 'Smos',
749 'contact_type' => 'Individual',
750 'api.relationship.create' => array(
752 'contact_id_a' => '$value.id',
753 'contact_id_b' => $create_result_1['id'],
755 'relationship_type_id' => 2,
756 'start_date' => '2005-01-12',
757 'end_date' => '2006-01-11',
758 'description' => 'old',
761 'contact_id_a' => '$value.id',
762 'contact_id_b' => $create_result_1['id'],
763 // spouse of (was married twice :))
764 'relationship_type_id' => 2,
765 'start_date' => '2006-07-01',
766 'end_date' => '2010-07-01',
767 'description' => 'new',
771 $create_result = $this->callAPISuccess('contact', 'create', $create_params);
773 // Try to retrieve the contact and the most recent relationship.
776 'id' => $create_result['id'],
777 'api.relationship.get' => array(
778 'contact_id_a' => '$value.id',
781 'sort' => 'start_date DESC',
784 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
787 $this->callAPISuccess('contact', 'delete', array(
788 'id' => $create_result['id'],
792 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
793 $this->assertEquals('new', $get_result['api.relationship.get']['values'][0]['description']);
797 * Test apostrophe works in get & create.
799 public function testGetApostropheCRM10857() {
800 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
801 $this->callAPISuccess($this->_entity
, 'create', $params);
802 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
803 'last_name' => "O'Connor",
806 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
810 * Check with complete array + custom field.
812 * Note that the test is written on purpose without any
813 * variables specific to participant so it can be replicated into other entities
814 * and / or moved to the automated test suite
816 public function testGetWithCustom() {
817 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
819 $params = $this->_params
;
820 $params['custom_' . $ids['custom_field_id']] = "custom string";
821 $description = "This demonstrates setting a custom field through the API.";
822 $subfile = "CustomFieldGet";
823 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
825 $check = $this->callAPIAndDocument($this->_entity
, 'get', array(
826 'return.custom_' . $ids['custom_field_id'] => 1,
827 'id' => $result['id'],
828 ), __FUNCTION__
, __FILE__
, $description, $subfile);
830 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
831 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
832 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
833 $this->customFieldDelete($ids['custom_field_id']);
834 $this->customGroupDelete($ids['custom_group_id']);
838 * Check with complete array + custom field.
840 * Note that the test is written on purpose without any
841 * variables specific to participant so it can be replicated into other entities
842 * and / or moved to the automated test suite
844 public function testGetWithCustomReturnSyntax() {
845 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
847 $params = $this->_params
;
848 $params['custom_' . $ids['custom_field_id']] = "custom string";
849 $description = "This demonstrates setting a custom field through the API.";
850 $subfile = "CustomFieldGetReturnSyntaxVariation";
851 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
852 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
853 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
855 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
856 $this->customFieldDelete($ids['custom_field_id']);
857 $this->customGroupDelete($ids['custom_group_id']);
861 * Check that address name is returned if required.
863 public function testGetReturnAddressName() {
864 $contactID = $this->individualCreate();
865 $this->callAPISuccess('address', 'create', array(
866 'contact_id' => $contactID,
867 'address_name' => 'My house',
868 'location_type_id' => 'Home',
869 'street_address' => '1 my road',
871 $result = $this->callAPISuccessGetSingle('contact', array(
872 'return' => 'address_name, street_address',
875 $this->assertEquals('1 my road', $result['street_address']);
876 $this->assertEquals('My house', $result['address_name']);
881 * Test group filter syntaxes.
883 public function testGetGroupIDFromContact() {
884 $groupId = $this->groupCreate();
885 $description = "Get all from group and display contacts.";
886 $subFile = "GroupFilterUsingContactAPI";
888 'email' => 'man2@yahoo.com',
889 'contact_type' => 'Individual',
890 'location_type_id' => 1,
891 'api.group_contact.create' => array('group_id' => $groupId),
894 $this->callAPISuccess('contact', 'create', $params);
895 // testing as integer
897 'filter.group_id' => $groupId,
898 'contact_type' => 'Individual',
900 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
901 $this->assertEquals(1, $result['count']);
902 // group 26 doesn't exist, but we can still search contacts in it.
904 'filter.group_id' => 26,
905 'contact_type' => 'Individual',
907 $this->callAPISuccess('contact', 'get', $params);
910 'filter.group_id' => "$groupId, 26",
911 'contact_type' => 'Individual',
913 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
914 $this->assertEquals(1, $result['count']);
916 'filter.group_id' => "26,27",
917 'contact_type' => 'Individual',
919 $this->callAPISuccess('contact', 'get', $params);
923 'filter.group_id' => array($groupId, 26),
924 'contact_type' => 'Individual',
926 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
927 $this->assertEquals(1, $result['count']);
929 //test in conjunction with other criteria
931 'filter.group_id' => array($groupId, 26),
932 'contact_type' => 'Organization',
934 $this->callAPISuccess('contact', 'get', $params);
936 'filter.group_id' => array(26, 27),
937 'contact_type' => 'Individual',
939 $result = $this->callAPISuccess('contact', 'get', $params);
940 $this->assertEquals(0, $result['count']);
944 * Verify that attempt to create individual contact with two chained websites succeeds.
946 public function testCreateIndividualWithContributionDottedSyntax() {
947 $description = "This demonstrates the syntax to create 2 chained entities.";
948 $subFile = "ChainTwoWebsites";
950 'first_name' => 'abc3',
951 'last_name' => 'xyz3',
952 'contact_type' => 'Individual',
953 'email' => 'man3@yahoo.com',
954 'api.contribution.create' => array(
955 'receive_date' => '2010-01-01',
956 'total_amount' => 100.00,
957 'financial_type_id' => $this->_financialTypeId
,
958 'payment_instrument_id' => 1,
959 'non_deductible_amount' => 10.00,
960 'fee_amount' => 50.00,
961 'net_amount' => 90.00,
963 'invoice_id' => 67990,
965 'contribution_status_id' => 1,
967 'api.website.create' => array(
968 'url' => "http://civicrm.org",
970 'api.website.create.2' => array(
971 'url' => "http://chained.org",
975 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
977 // checking child function result not covered in callAPIAndDocument
978 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
979 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
980 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
982 // delete the contact
983 $this->callAPISuccess('contact', 'delete', $result);
987 * Verify that attempt to create individual contact with chained contribution and website succeeds.
989 public function testCreateIndividualWithContributionChainedArrays() {
991 'first_name' => 'abc3',
992 'last_name' => 'xyz3',
993 'contact_type' => 'Individual',
994 'email' => 'man3@yahoo.com',
995 'api.contribution.create' => array(
996 'receive_date' => '2010-01-01',
997 'total_amount' => 100.00,
998 'financial_type_id' => $this->_financialTypeId
,
999 'payment_instrument_id' => 1,
1000 'non_deductible_amount' => 10.00,
1001 'fee_amount' => 50.00,
1002 'net_amount' => 90.00,
1004 'invoice_id' => 67890,
1006 'contribution_status_id' => 1,
1008 'api.website.create' => array(
1010 'url' => "http://civicrm.org",
1013 'url' => "http://chained.org",
1014 'website_type_id' => 2,
1019 $description = "Demonstrates creating two websites as an array.";
1020 $subfile = "ChainTwoWebsitesSyntax2";
1021 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1023 // the callAndDocument doesn't check the chained call
1024 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
1025 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
1026 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
1028 $this->callAPISuccess('contact', 'delete', $result);
1032 * Test for direction when chaining relationships.
1034 * https://issues.civicrm.org/jira/browse/CRM-16084
1036 public function testDirectionChainingRelationshipsCRM16084() {
1037 // Some contact, called Jules.
1038 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1039 'first_name' => 'Jules',
1040 'last_name' => 'Smos',
1041 'contact_type' => 'Individual',
1044 // Another contact: Jos, child of Jules.
1045 $create_params = array(
1046 'first_name' => 'Jos',
1047 'last_name' => 'Smos',
1048 'contact_type' => 'Individual',
1049 'api.relationship.create' => array(
1051 'contact_id_a' => '$value.id',
1052 'contact_id_b' => $create_result_1['id'],
1054 'relationship_type_id' => 1,
1058 $create_result_2 = $this->callAPISuccess('contact', 'create', $create_params);
1060 // Mia is the child of Jos.
1061 $create_params = array(
1062 'first_name' => 'Mia',
1063 'last_name' => 'Smos',
1064 'contact_type' => 'Individual',
1065 'api.relationship.create' => array(
1067 'contact_id_a' => '$value.id',
1068 'contact_id_b' => $create_result_2['id'],
1070 'relationship_type_id' => 1,
1074 $create_result_3 = $this->callAPISuccess('contact', 'create', $create_params);
1076 // Get Jos and his children.
1077 $get_params = array(
1079 'id' => $create_result_2['id'],
1080 'api.relationship.get' => array(
1081 'contact_id_b' => '$value.id',
1082 'relationship_type_id' => 1,
1085 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1088 $this->callAPISuccess('contact', 'delete', array(
1089 'id' => $create_result_1['id'],
1091 $this->callAPISuccess('contact', 'delete', array(
1092 'id' => $create_result_2['id'],
1094 $this->callAPISuccess('contact', 'delete', array(
1095 'id' => $create_result_2['id'],
1099 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1100 $this->assertEquals($create_result_3['id'], $get_result['api.relationship.get']['values'][0]['contact_id_a']);
1104 * Verify that attempt to create individual contact with first, and last names and email succeeds.
1106 public function testCreateIndividualWithNameEmail() {
1108 'first_name' => 'abc3',
1109 'last_name' => 'xyz3',
1110 'contact_type' => 'Individual',
1111 'email' => 'man3@yahoo.com',
1114 $contact = $this->callAPISuccess('contact', 'create', $params);
1116 $this->callAPISuccess('contact', 'delete', $contact);
1120 * Verify that attempt to create individual contact with no data fails.
1122 public function testCreateIndividualWithOutNameEmail() {
1124 'contact_type' => 'Individual',
1126 $this->callAPIFailure('contact', 'create', $params);
1130 * Test create individual contact with first &last names, email and location type succeeds.
1132 public function testCreateIndividualWithNameEmailLocationType() {
1134 'first_name' => 'abc4',
1135 'last_name' => 'xyz4',
1136 'email' => 'man4@yahoo.com',
1137 'contact_type' => 'Individual',
1138 'location_type_id' => 1,
1140 $result = $this->callAPISuccess('contact', 'create', $params);
1142 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1146 * Verify that when changing employers the old employer relationship becomes inactive.
1148 public function testCreateIndividualWithEmployer() {
1149 $employer = $this->organizationCreate();
1150 $employer2 = $this->organizationCreate();
1153 'email' => 'man4@yahoo.com',
1154 'contact_type' => 'Individual',
1155 'employer_id' => $employer,
1158 $result = $this->callAPISuccess('contact', 'create', $params);
1159 $relationships = $this->callAPISuccess('relationship', 'get', array(
1160 'contact_id_a' => $result['id'],
1164 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1166 // Add more random relationships to make the test more realistic
1167 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
1168 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
1169 $this->callAPISuccess('relationship', 'create', array(
1170 'contact_id_a' => $result['id'],
1171 'contact_id_b' => $this->organizationCreate(),
1173 'relationship_type_id' => $relTypeId,
1177 // Add second employer
1178 $params['employer_id'] = $employer2;
1179 $params['id'] = $result['id'];
1180 $result = $this->callAPISuccess('contact', 'create', $params);
1182 $relationships = $this->callAPISuccess('relationship', 'get', array(
1183 'contact_id_a' => $result['id'],
1188 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1192 * Verify that attempt to create household contact with details succeeds.
1194 public function testCreateHouseholdDetails() {
1196 'household_name' => 'abc8\'s House',
1197 'nick_name' => 'x House',
1198 'email' => 'man8@yahoo.com',
1199 'contact_type' => 'Household',
1202 $contact = $this->callAPISuccess('contact', 'create', $params);
1204 $this->callAPISuccess('contact', 'delete', $contact);
1208 * Verify that attempt to create household contact with inadequate details fails.
1210 public function testCreateHouseholdInadequateDetails() {
1212 'nick_name' => 'x House',
1213 'email' => 'man8@yahoo.com',
1214 'contact_type' => 'Household',
1216 $this->callAPIFailure('contact', 'create', $params);
1220 * Verify successful update of individual contact.
1222 public function testUpdateIndividualWithAll() {
1223 // Insert a row in civicrm_contact creating individual contact.
1224 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1225 $op->execute($this->_dbconn
,
1226 $this->createXMLDataSet(
1227 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1233 'first_name' => 'abcd',
1234 'contact_type' => 'Individual',
1235 'nick_name' => 'This is nickname first',
1236 'do_not_email' => '1',
1237 'do_not_phone' => '1',
1238 'do_not_mail' => '1',
1239 'do_not_trade' => '1',
1240 'legal_identifier' => 'ABC23853ZZ2235',
1241 'external_identifier' => '1928837465',
1242 'image_URL' => 'http://some.url.com/image.jpg',
1243 'home_url' => 'http://www.example.org',
1247 $this->callAPISuccess('Contact', 'Update', $params);
1248 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
1249 unset($params['contact_id']);
1250 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
1251 //reducing this test partially back to api v2 level to get it through
1252 unset($params['home_url']);
1253 foreach ($params as $key => $value) {
1254 $this->assertEquals($value, $getResult['values'][23][$key]);
1256 // Check updated civicrm_contact against expected.
1257 $expected = $this->createXMLDataSet(
1258 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
1260 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1263 $actual->addTable('civicrm_contact');
1264 $expected->matches($actual);
1268 * Verify successful update of organization contact.
1270 public function testUpdateOrganizationWithAll() {
1271 // Insert a row in civicrm_contact creating organization contact
1272 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1273 $op->execute($this->_dbconn
,
1274 $this->createXMLDataSet(
1275 dirname(__FILE__
) . '/dataset/contact_org.xml'
1281 'organization_name' => 'WebAccess India Pvt Ltd',
1282 'legal_name' => 'WebAccess',
1283 'sic_code' => 'ABC12DEF',
1284 'contact_type' => 'Organization',
1287 $this->callAPISuccess('Contact', 'Update', $params);
1289 // Check updated civicrm_contact against expected.
1290 $expected = $this->createXMLDataSet(
1291 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
1293 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1296 $actual->addTable('civicrm_contact');
1297 $expected->matches($actual);
1301 * Verify successful update of household contact.
1303 public function testUpdateHouseholdWithAll() {
1304 // Insert a row in civicrm_contact creating household contact
1305 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1306 $op->execute($this->_dbconn
,
1307 $this->createXMLDataSet(
1308 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1314 'household_name' => 'ABC household',
1315 'nick_name' => 'ABC House',
1316 'contact_type' => 'Household',
1319 $result = $this->callAPISuccess('Contact', 'Update', $params);
1322 'contact_type' => 'Household',
1324 'sort_name' => 'ABC household',
1325 'display_name' => 'ABC household',
1326 'nick_name' => 'ABC House',
1328 $this->getAndCheck($expected, $result['id'], 'contact');
1332 * Test civicrm_update() without contact type.
1334 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1338 public function testUpdateCreateWithID() {
1339 // Insert a row in civicrm_contact creating individual contact.
1340 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1341 $op->execute($this->_dbconn
,
1342 $this->createXMLDataSet(
1343 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1349 'first_name' => 'abcd',
1350 'last_name' => 'wxyz',
1352 $this->callAPISuccess('Contact', 'Update', $params);
1356 * Test civicrm_contact_delete() with no contact ID.
1358 public function testContactDeleteNoID() {
1362 $this->callAPIFailure('contact', 'delete', $params);
1366 * Test civicrm_contact_delete() with error.
1368 public function testContactDeleteError() {
1369 $params = array('contact_id' => 999);
1370 $this->callAPIFailure('contact', 'delete', $params);
1374 * Test civicrm_contact_delete().
1376 public function testContactDelete() {
1377 $contactID = $this->individualCreate();
1381 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1385 * Test civicrm_contact_get() return only first name.
1387 public function testContactGetRetFirst() {
1388 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1390 'contact_id' => $contact['id'],
1391 'return_first_name' => TRUE,
1392 'sort' => 'first_name',
1394 $result = $this->callAPISuccess('contact', 'get', $params);
1395 $this->assertEquals(1, $result['count']);
1396 $this->assertEquals($contact['id'], $result['id']);
1397 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1401 * Test civicrm_contact_get() return only first name & last name.
1403 * Use comma separated string return with a space.
1405 public function testContactGetReturnFirstLast() {
1406 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1408 'contact_id' => $contact['id'],
1409 'return' => 'first_name, last_name',
1411 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1412 $this->assertEquals('abc1', $result['first_name']);
1413 $this->assertEquals('xyz1', $result['last_name']);
1414 //check that other defaults not returns
1415 $this->assertArrayNotHasKey('sort_name', $result);
1417 'contact_id' => $contact['id'],
1418 'return' => 'first_name,last_name',
1420 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1421 $this->assertEquals('abc1', $result['first_name']);
1422 $this->assertEquals('xyz1', $result['last_name']);
1423 //check that other defaults not returns
1424 $this->assertArrayNotHasKey('sort_name', $result);
1428 * Test civicrm_contact_get() return only first name & last name.
1430 * Use comma separated string return without a space
1432 public function testContactGetReturnFirstLastNoComma() {
1433 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1435 'contact_id' => $contact['id'],
1436 'return' => 'first_name,last_name',
1438 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1439 $this->assertEquals('abc1', $result['first_name']);
1440 $this->assertEquals('xyz1', $result['last_name']);
1441 //check that other defaults not returns
1442 $this->assertArrayNotHasKey('sort_name', $result);
1446 * Test civicrm_contact_get() with default return properties.
1448 public function testContactGetRetDefault() {
1449 $contactID = $this->individualCreate();
1451 'contact_id' => $contactID,
1452 'sort' => 'first_name',
1454 $result = $this->callAPISuccess('contact', 'get', $params);
1455 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1456 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1460 * Test civicrm_contact_getquick() with empty name param.
1462 public function testContactGetQuick() {
1463 // Insert a row in civicrm_contact creating individual contact.
1464 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1465 $op->execute($this->_dbconn
,
1466 $this->createXMLDataSet(
1467 dirname(__FILE__
) . '/dataset/contact_17.xml'
1470 $op->execute($this->_dbconn
,
1471 $this->createXMLDataSet(
1472 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1479 $result = $this->callAPISuccess('contact', 'getquick', $params);
1480 $this->assertEquals(17, $result['values'][0]['id']);
1484 * Test civicrm_contact_get) with empty params.
1486 public function testContactGetEmptyParams() {
1487 $this->callAPISuccess('contact', 'get', array());
1491 * Test civicrm_contact_get(,true) with no matches.
1493 public function testContactGetOldParamsNoMatches() {
1494 // Insert a row in civicrm_contact creating contact 17.
1495 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1496 $op->execute($this->_dbconn
,
1497 $this->createXMLDataSet(
1498 dirname(__FILE__
) . '/dataset/contact_17.xml'
1503 'first_name' => 'Fred',
1505 $result = $this->callAPISuccess('contact', 'get', $params);
1506 $this->assertEquals(0, $result['count']);
1510 * Test civicrm_contact_get(,true) with one match.
1512 public function testContactGetOldParamsOneMatch() {
1513 // Insert a row in civicrm_contact creating contact 17
1514 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1515 $op->execute($this->_dbconn
,
1516 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1521 'first_name' => 'Test',
1523 $result = $this->callAPISuccess('contact', 'get', $params);
1524 $this->assertEquals(17, $result['values'][17]['contact_id']);
1525 $this->assertEquals(17, $result['id']);
1529 * Test civicrm_contact_search_count().
1531 public function testContactGetEmail() {
1533 'email' => 'man2@yahoo.com',
1534 'contact_type' => 'Individual',
1535 'location_type_id' => 1,
1538 $contact = $this->callAPISuccess('contact', 'create', $params);
1541 'email' => 'man2@yahoo.com',
1543 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1544 $this->assertEquals('man2@yahoo.com', $result['values'][$result['id']]['email']);
1546 $this->callAPISuccess('contact', 'delete', $contact);
1550 * Test birth date parameters.
1552 * These include value, array & birth_date_high, birth_date_low
1555 public function testContactGetBirthDate() {
1556 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1557 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1558 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1560 $result = $this->callAPISuccess('contact', 'get', array());
1561 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1562 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1563 $this->assertEquals(1, $result['count']);
1564 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1565 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1566 $this->assertEquals(1, $result['count']);
1567 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1568 $result = $this->callAPISuccess('contact', 'get', array(
1569 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1570 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1572 $this->assertEquals(1, $result['count']);
1573 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1574 $result = $this->callAPISuccess('contact', 'get', array(
1575 'birth_date_low' => '-6 years',
1576 'birth_date_high' => '- 3 years',
1578 $this->assertEquals(1, $result['count']);
1579 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1583 * Test Address parameters
1585 * This include state_province, state_province_name, country
1587 public function testContactGetWithAddressFields() {
1588 $individuals = array(
1590 'first_name' => 'abc1',
1591 'contact_type' => 'Individual',
1592 'last_name' => 'xyz1',
1593 'api.address.create' => array(
1594 'country' => 'United States',
1595 'state_province_id' => 'Michigan',
1596 'location_type_id' => 1,
1600 'first_name' => 'abc2',
1601 'contact_type' => 'Individual',
1602 'last_name' => 'xyz2',
1603 'api.address.create' => array(
1604 'country' => 'United States',
1605 'state_province_id' => 'Alabama',
1606 'location_type_id' => 1,
1610 foreach ($individuals as $params) {
1611 $contact = $this->callAPISuccess('contact', 'create', $params);
1614 // Check whether Contact get API return successfully with below Address params.
1615 $fieldsToTest = array(
1616 'state_province_name' => 'Michigan',
1617 'state_province' => 'Michigan',
1618 'country' => 'United States',
1619 'state_province_name' => array('IN' => array('Michigan', 'Alabama')),
1620 'state_province' => array('IN' => array('Michigan', 'Alabama')),
1622 foreach ($fieldsToTest as $field => $value) {
1624 'id' => $contact['id'],
1627 $result = $this->callAPISuccess('Contact', 'get', $getParams);
1628 $this->assertEquals(1, $result['count']);
1633 * Test Deceased date parameters.
1635 * These include value, array & Deceased_date_high, Deceased date_low
1638 public function testContactGetDeceasedDate() {
1639 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1640 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1641 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1643 $result = $this->callAPISuccess('contact', 'get', array());
1644 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1645 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1646 $this->assertEquals(1, $result['count']);
1647 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1648 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1649 $this->assertEquals(1, $result['count']);
1650 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1651 $result = $this->callAPISuccess('contact', 'get', array(
1652 'deceased_date_low' => '-6 years',
1653 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1655 $this->assertEquals(1, $result['count']);
1656 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1660 * Test for Contact.get id=@user:username.
1662 public function testContactGetByUsername() {
1663 // Setup - create contact with a uf-match.
1664 $cid = $this->individualCreate(array(
1665 'contact_type' => 'Individual',
1666 'first_name' => 'testGetByUsername',
1667 'last_name' => 'testGetByUsername',
1670 $ufMatchParams = array(
1671 'domain_id' => CRM_Core_Config
::domainID(),
1673 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1674 'contact_id' => $cid,
1676 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1677 $this->assertTrue(is_numeric($ufMatch->id
));
1679 // setup - mock the calls to CRM_Utils_System_*::getUfId
1680 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1681 $userSystem->expects($this->once())
1683 ->with($this->equalTo('exampleUser'))
1684 ->will($this->returnValue(99));
1685 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1688 $result = $this->callAPISuccess('Contact', 'get', array(
1689 'id' => '@user:exampleUser',
1691 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1695 * Test to check return works OK.
1697 public function testContactGetReturnValues() {
1698 $extraParams = array(
1699 'nick_name' => 'Bob',
1701 'email' => 'e@mail.com',
1703 $contactID = $this->individualCreate($extraParams);
1704 //actually it turns out the above doesn't create a phone
1705 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1706 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1707 foreach ($extraParams as $key => $value) {
1708 $this->assertEquals($result[$key], $value);
1710 //now we check they are still returned with 'return' key
1711 $result = $this->callAPISuccess('contact', 'getsingle', array(
1713 'return' => array_keys($extraParams),
1715 foreach ($extraParams as $key => $value) {
1716 $this->assertEquals($result[$key], $value);
1721 * Test creating multiple phones using chaining.
1723 * @throws \Exception
1725 public function testCRM13252MultipleChainedPhones() {
1726 $contactID = $this->householdCreate();
1727 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1729 'contact_id' => $contactID,
1730 'household_name' => 'Household 1',
1731 'contact_type' => 'Household',
1732 'api.phone.create' => array(
1734 'phone' => '111-111-1111',
1735 'location_type_id' => 1,
1736 'phone_type_id' => 1,
1739 'phone' => '222-222-2222',
1740 'location_type_id' => 1,
1741 'phone_type_id' => 2,
1745 $this->callAPISuccess('contact', 'create', $params);
1746 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1751 * Test for Contact.get id=@user:username (with an invalid username).
1753 public function testContactGetByUnknownUsername() {
1754 // setup - mock the calls to CRM_Utils_System_*::getUfId
1755 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1756 $userSystem->expects($this->once())
1758 ->with($this->equalTo('exampleUser'))
1759 ->will($this->returnValue(NULL));
1760 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1763 $result = $this->callAPIFailure('Contact', 'get', array(
1764 'id' => '@user:exampleUser',
1766 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1770 * Verify attempt to create individual with chained arrays and sequential.
1772 public function testGetIndividualWithChainedArraysAndSequential() {
1773 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1774 $params['custom_' . $ids['custom_field_id']] = "custom string";
1776 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1779 'first_name' => 'abc3',
1780 'last_name' => 'xyz3',
1781 'contact_type' => 'Individual',
1782 'email' => 'man3@yahoo.com',
1783 'api.website.create' => array(
1785 'url' => "http://civicrm.org",
1788 'url' => "https://civicrm.org",
1793 $result = $this->callAPISuccess('Contact', 'create', $params);
1795 // delete the contact and custom groups
1796 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1797 $this->customGroupDelete($ids['custom_group_id']);
1798 $this->customGroupDelete($moreIDs['custom_group_id']);
1800 $this->assertEquals($result['id'], $result['values'][0]['id']);
1801 $this->assertArrayKeyExists('api.website.create', $result['values'][0]);
1805 * Verify attempt to create individual with chained arrays.
1807 public function testGetIndividualWithChainedArrays() {
1808 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1809 $params['custom_' . $ids['custom_field_id']] = "custom string";
1811 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1812 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1813 $subfile = "APIChainedArray";
1815 'first_name' => 'abc3',
1816 'last_name' => 'xyz3',
1817 'contact_type' => 'Individual',
1818 'email' => 'man3@yahoo.com',
1819 'api.contribution.create' => array(
1820 'receive_date' => '2010-01-01',
1821 'total_amount' => 100.00,
1822 'financial_type_id' => 1,
1823 'payment_instrument_id' => 1,
1824 'non_deductible_amount' => 10.00,
1825 'fee_amount' => 50.00,
1826 'net_amount' => 90.00,
1828 'invoice_id' => 67890,
1830 'contribution_status_id' => 1,
1832 'api.contribution.create.1' => array(
1833 'receive_date' => '2011-01-01',
1834 'total_amount' => 120.00,
1835 'financial_type_id' => $this->_financialTypeId
= 1,
1836 'payment_instrument_id' => 1,
1837 'non_deductible_amount' => 10.00,
1838 'fee_amount' => 50.00,
1839 'net_amount' => 90.00,
1841 'invoice_id' => 67830,
1843 'contribution_status_id' => 1,
1845 'api.website.create' => array(
1847 'url' => "http://civicrm.org",
1852 $result = $this->callAPISuccess('Contact', 'create', $params);
1854 'id' => $result['id'],
1855 'api.website.get' => array(),
1856 'api.Contribution.get' => array(
1857 'total_amount' => '120.00',
1859 'api.CustomValue.get' => 1,
1860 'api.Note.get' => 1,
1862 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1863 // delete the contact
1864 $this->callAPISuccess('contact', 'delete', $result);
1865 $this->customGroupDelete($ids['custom_group_id']);
1866 $this->customGroupDelete($moreIDs['custom_group_id']);
1867 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1868 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1872 * Verify attempt to create individual with chained arrays and sequential.
1874 * See https://issues.civicrm.org/jira/browse/CRM-15815
1876 public function testCreateIndividualWithChainedArrayAndSequential() {
1879 'first_name' => 'abc5',
1880 'last_name' => 'xyz5',
1881 'contact_type' => 'Individual',
1882 'email' => 'woman5@yahoo.com',
1883 'api.phone.create' => array(
1884 array('phone' => '03-231 07 95'),
1885 array('phone' => '03-232 51 62'),
1887 'api.website.create' => array(
1888 'url' => 'http://civicrm.org',
1891 $result = $this->callAPISuccess('Contact', 'create', $params);
1893 // I could try to parse the result to see whether the two phone numbers
1894 // and the website are there, but I am not sure about the correct format.
1895 // So I will just fetch it again before checking.
1896 // See also http://forum.civicrm.org/index.php/topic,35393.0.html
1899 'id' => $result['id'],
1900 'api.website.get' => array(),
1901 'api.phone.get' => array(),
1903 $result = $this->callAPISuccess('Contact', 'get', $params);
1905 // delete the contact
1906 $this->callAPISuccess('contact', 'delete', $result);
1908 $this->assertEquals(2, $result['values'][0]['api.phone.get']['count']);
1909 $this->assertEquals(1, $result['values'][0]['api.website.get']['count']);
1913 * Test retrieving an individual with chained array syntax.
1915 public function testGetIndividualWithChainedArraysFormats() {
1916 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1917 $subfile = "APIChainedArrayFormats";
1918 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1919 $params['custom_' . $ids['custom_field_id']] = "custom string";
1921 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1923 'first_name' => 'abc3',
1924 'last_name' => 'xyz3',
1925 'contact_type' => 'Individual',
1926 'email' => 'man3@yahoo.com',
1927 'api.contribution.create' => array(
1928 'receive_date' => '2010-01-01',
1929 'total_amount' => 100.00,
1930 'financial_type_id' => $this->_financialTypeId
,
1931 'payment_instrument_id' => 1,
1932 'non_deductible_amount' => 10.00,
1933 'fee_amount' => 50.00,
1934 'net_amount' => 90.00,
1936 'contribution_status_id' => 1,
1938 'api.contribution.create.1' => array(
1939 'receive_date' => '2011-01-01',
1940 'total_amount' => 120.00,
1941 'financial_type_id' => $this->_financialTypeId
,
1942 'payment_instrument_id' => 1,
1943 'non_deductible_amount' => 10.00,
1944 'fee_amount' => 50.00,
1945 'net_amount' => 90.00,
1947 'contribution_status_id' => 1,
1949 'api.website.create' => array(
1951 'url' => "http://civicrm.org",
1956 $result = $this->callAPISuccess('Contact', 'create', $params);
1958 'id' => $result['id'],
1959 'api.website.getValue' => array('return' => 'url'),
1960 'api.Contribution.getCount' => array(),
1961 'api.CustomValue.get' => 1,
1962 'api.Note.get' => 1,
1963 'api.Membership.getCount' => array(),
1965 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1966 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1967 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1968 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1970 $this->callAPISuccess('contact', 'delete', $result);
1971 $this->customGroupDelete($ids['custom_group_id']);
1972 $this->customGroupDelete($moreIDs['custom_group_id']);
1976 * Test complex chaining.
1978 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
1979 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1980 $params['custom_' . $ids['custom_field_id']] = "custom string";
1981 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1982 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
1983 'title' => "another group",
1984 'name' => 'another name',
1986 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
1987 $subfile = "APIChainedArrayMultipleCustom";
1989 'first_name' => 'abc3',
1990 'last_name' => 'xyz3',
1991 'contact_type' => 'Individual',
1992 'email' => 'man3@yahoo.com',
1993 'api.contribution.create' => array(
1994 'receive_date' => '2010-01-01',
1995 'total_amount' => 100.00,
1996 'financial_type_id' => 1,
1997 'payment_instrument_id' => 1,
1998 'non_deductible_amount' => 10.00,
1999 'fee_amount' => 50.00,
2000 'net_amount' => 90.00,
2002 'invoice_id' => 67890,
2004 'contribution_status_id' => 1,
2006 'api.contribution.create.1' => array(
2007 'receive_date' => '2011-01-01',
2008 'total_amount' => 120.00,
2009 'financial_type_id' => 1,
2010 'payment_instrument_id' => 1,
2011 'non_deductible_amount' => 10.00,
2012 'fee_amount' => 50.00,
2013 'net_amount' => 90.00,
2015 'invoice_id' => 67830,
2017 'contribution_status_id' => 1,
2019 'api.website.create' => array(
2021 'url' => "http://civicrm.org",
2024 'custom_' . $ids['custom_field_id'] => "value 1",
2025 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
2026 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
2027 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
2030 $result = $this->callAPISuccess('Contact', 'create', $params);
2031 $result = $this->callAPISuccess('Contact', 'create', array(
2032 'contact_type' => 'Individual',
2033 'id' => $result['id'],
2035 $moreIDs['custom_field_id'][0] => "value 3",
2037 $ids['custom_field_id'] => "value 4",
2041 'id' => $result['id'],
2042 'api.website.getValue' => array('return' => 'url'),
2043 'api.Contribution.getCount' => array(),
2044 'api.CustomValue.get' => 1,
2046 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2048 $this->customGroupDelete($ids['custom_group_id']);
2049 $this->customGroupDelete($moreIDs['custom_group_id']);
2050 $this->customGroupDelete($andMoreIDs['custom_group_id']);
2051 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
2052 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
2056 * Test checks usage of $values to pick & choose inputs.
2058 public function testChainingValuesCreate() {
2059 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
2060 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
2061 $subfile = "APIChainedArrayValuesFromSiblingFunction";
2063 'display_name' => 'batman',
2064 'contact_type' => 'Individual',
2065 'api.tag.create' => array(
2066 'name' => '$value.id',
2067 'description' => '$value.display_name',
2068 'format.only_id' => 1,
2070 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
2072 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2073 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
2075 $tablesToTruncate = array(
2078 'civicrm_entity_tag',
2081 $this->quickCleanup($tablesToTruncate, TRUE);
2085 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
2087 public function testContactGetFormatIsSuccessTrue() {
2088 $this->createContactFromXML();
2089 $description = "This demonstrates use of the 'format.is_success' param.
2090 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2091 $subfile = "FormatIsSuccess_True";
2092 $params = array('id' => 17, 'format.is_success' => 1);
2093 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2094 $this->assertEquals(1, $result);
2095 $this->callAPISuccess('Contact', 'Delete', $params);
2099 * Test TrueFalse format.
2101 public function testContactCreateFormatIsSuccessFalse() {
2103 $description = "This demonstrates use of the 'format.is_success' param.
2104 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2105 $subfile = "FormatIsSuccess_Fail";
2106 $params = array('id' => 500, 'format.is_success' => 1);
2107 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2108 $this->assertEquals(0, $result);
2112 * Test Single Entity format.
2114 public function testContactGetSingleEntityArray() {
2115 $this->createContactFromXML();
2116 $description = "This demonstrates use of the 'format.single_entity_array' param.
2117 This param causes the only contact to be returned as an array without the other levels.
2118 It will be ignored if there is not exactly 1 result";
2119 $subfile = "GetSingleContact";
2120 $params = array('id' => 17);
2121 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2122 $this->assertEquals('Test Contact', $result['display_name']);
2123 $this->callAPISuccess('Contact', 'Delete', $params);
2127 * Test Single Entity format.
2129 public function testContactGetFormatCountOnly() {
2130 $this->createContactFromXML();
2131 $description = "This demonstrates use of the 'getCount' action.
2132 This param causes the count of the only function to be returned as an integer.";
2133 $params = array('id' => 17);
2134 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description,
2136 $this->assertEquals('1', $result);
2137 $this->callAPISuccess('Contact', 'Delete', $params);
2141 * Test id only format.
2143 public function testContactGetFormatIDOnly() {
2144 $this->createContactFromXML();
2145 $description = "This demonstrates use of the 'format.id_only' param.
2146 This param causes the id of the only entity to be returned as an integer.
2147 It will be ignored if there is not exactly 1 result";
2148 $subfile = "FormatOnlyID";
2149 $params = array('id' => 17, 'format.only_id' => 1);
2150 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2151 $this->assertEquals('17', $result);
2152 $this->callAPISuccess('Contact', 'Delete', $params);
2156 * Test id only format.
2158 public function testContactGetFormatSingleValue() {
2159 $this->createContactFromXML();
2160 $description = "This demonstrates use of the 'format.single_value' param.
2161 This param causes only a single value of the only entity to be returned as an string.
2162 It will be ignored if there is not exactly 1 result";
2163 $subFile = "FormatSingleValue";
2164 $params = array('id' => 17, 'return' => 'display_name');
2165 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
2166 $this->assertEquals('Test Contact', $result);
2167 $this->callAPISuccess('Contact', 'Delete', $params);
2171 * Test that permissions are respected when creating contacts.
2173 public function testContactCreationPermissions() {
2175 'contact_type' => 'Individual',
2176 'first_name' => 'Foo',
2177 'last_name' => 'Bear',
2178 'check_permissions' => TRUE,
2180 $config = CRM_Core_Config
::singleton();
2181 $config->userPermissionClass
->permissions
= array('access CiviCRM');
2182 $result = $this->callAPIFailure('contact', 'create', $params);
2183 $this->assertEquals('API permission check failed for Contact/create call; insufficient permission: require access CiviCRM and add contacts', $result['error_message'], 'lacking permissions should not be enough to create a contact');
2185 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
2186 $this->callAPISuccess('contact', 'create', $params);
2190 * Test update with check permissions set.
2192 public function testContactUpdatePermissions() {
2194 'contact_type' => 'Individual',
2195 'first_name' => 'Foo',
2196 'last_name' => 'Bear',
2197 'check_permissions' => TRUE,
2199 $result = $this->callAPISuccess('contact', 'create', $params);
2200 $config = CRM_Core_Config
::singleton();
2202 'id' => $result['id'],
2203 'contact_type' => 'Individual',
2204 'last_name' => 'Bar',
2205 'check_permissions' => TRUE,
2208 $config->userPermissionClass
->permissions
= array('access CiviCRM');
2209 $result = $this->callAPIFailure('contact', 'update', $params);
2210 $this->assertEquals('Permission denied to modify contact record', $result['error_message']);
2212 $config->userPermissionClass
->permissions
= array(
2215 'view all contacts',
2216 'edit all contacts',
2219 $this->callAPISuccess('contact', 'update', $params);
2223 * Set up helper to create a contact.
2225 public function createContactFromXML() {
2226 // Insert a row in civicrm_contact creating contact 17.
2227 $op = new PHPUnit_Extensions_Database_Operation_Insert();
2228 $op->execute($this->_dbconn
,
2229 $this->createXMLDataSet(
2230 dirname(__FILE__
) . '/dataset/contact_17.xml'
2236 * Test contact proximity api.
2238 public function testContactProximity() {
2239 // first create a contact with a SF location with a specific
2241 $contactID = $this->organizationCreate();
2243 // now create the address
2245 'street_address' => '123 Main Street',
2246 'city' => 'San Francisco',
2248 'country_id' => 1228,
2249 'state_province_id' => 1004,
2250 'geo_code_1' => '37.79',
2251 'geo_code_2' => '-122.40',
2252 'location_type_id' => 1,
2253 'contact_id' => $contactID,
2256 $result = $this->callAPISuccess('address', 'create', $params);
2257 $this->assertEquals(1, $result['count']);
2259 // now do a proximity search with a close enough geocode and hope to match
2260 // that specific contact only!
2261 $proxParams = array(
2263 'longitude' => -122.3,
2267 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
2268 $this->assertEquals(1, $result['count']);
2272 * Test that Ajax API permission is sufficient to access getquick api.
2274 * (note that getquick api is required for autocomplete & has ACL permissions applied)
2276 public function testGetquickPermissionCRM13744() {
2277 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
2278 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2279 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
2280 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2281 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
2282 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2286 * Test that getquick returns contacts with an exact first name match first.
2288 * The search string 'b' & 'bob' both return ordered by sort_name if includeOrderByClause
2289 * is true (default) but if it is false then matches are returned in ID order.
2291 public function testGetQuickExactFirst() {
2292 $this->getQuickSearchSampleData();
2293 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'b'));
2294 $this->assertEquals('A Bobby, Bobby', $result['values'][0]['sort_name']);
2295 $this->assertEquals('B Bobby, Bobby', $result['values'][1]['sort_name']);
2296 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2297 $this->assertEquals('A Bobby, Bobby', $result['values'][0]['sort_name']);
2298 $this->assertEquals('B Bobby, Bobby', $result['values'][1]['sort_name']);
2299 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2300 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2301 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2302 $this->assertEquals('A Bobby, Bobby', $result['values'][1]['sort_name']);
2306 * Test that getquick returns contacts with an exact first name match first.
2308 public function testGetQuickEmail() {
2309 $this->getQuickSearchSampleData();
2310 $loggedInContactID = $this->createLoggedInUser();
2311 $result = $this->callAPISuccess('contact', 'getquick', array(
2314 $expectedData = array(
2315 'Bob, Bob :: bob@bob.com',
2317 'E Bobby, Bobby :: bob@bobby.com',
2318 'H Bobby, Bobby :: bob@h.com',
2320 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2322 $this->assertEquals(6, $result['count']);
2323 foreach ($expectedData as $index => $value) {
2324 $this->assertEquals($value, $result['values'][$index]['data']);
2326 $result = $this->callAPISuccess('contact', 'getquick', array(
2329 $expectedData = array(
2330 'H Bobby, Bobby :: bob@h.com',
2332 foreach ($expectedData as $index => $value) {
2333 $this->assertEquals($value, $result['values'][$index]['data']);
2335 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => FALSE));
2336 $result = $this->callAPISuccess('contact', 'getquick', array(
2339 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE));
2340 $this->assertEquals(0, $result['count']);
2344 * Test that getquick returns contacts with an exact first name match first.
2346 public function testGetQuickEmailACL() {
2347 $this->getQuickSearchSampleData();
2348 $loggedInContactID = $this->createLoggedInUser();
2349 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
2350 $result = $this->callAPISuccess('contact', 'getquick', array(
2353 $this->assertEquals(0, $result['count']);
2355 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2356 CRM_Contact_BAO_Contact_Permission
::cache($loggedInContactID, CRM_Core_Permission
::VIEW
, TRUE);
2357 $result = $this->callAPISuccess('contact', 'getquick', array(
2361 // Without the acl it would be 6 like the previous email getquick test.
2362 $this->assertEquals(5, $result['count']);
2363 $expectedData = array(
2364 'Bob, Bob :: bob@bob.com',
2366 'E Bobby, Bobby :: bob@bobby.com',
2368 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2370 foreach ($expectedData as $index => $value) {
2371 $this->assertEquals($value, $result['values'][$index]['data']);
2376 * Test that getquick returns contacts with an exact first name match first.
2378 public function testGetQuickExternalID() {
2379 $this->getQuickSearchSampleData();
2380 $result = $this->callAPISuccess('contact', 'getquick', array(
2382 'field_name' => 'external_identifier',
2383 'table_name' => 'cc',
2385 $this->assertEquals(0, $result['count']);
2386 $result = $this->callAPISuccess('contact', 'getquick', array(
2388 'field_name' => 'external_identifier',
2389 'table_name' => 'cc',
2391 $this->assertEquals(1, $result['count']);
2392 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2396 * Test that getquick returns contacts with an exact first name match first.
2398 public function testGetQuickID() {
2399 $max = CRM_Core_DAO
::singleValueQuery("SELECT max(id) FROM civicrm_contact");
2400 $this->getQuickSearchSampleData();
2401 $result = $this->callAPISuccess('contact', 'getquick', array(
2403 'field_name' => 'id',
2404 'table_name' => 'cc',
2406 $this->assertEquals(1, $result['count']);
2407 $this->assertEquals('A Bobby, Bobby', $result['values'][0]['sort_name']);
2408 $result = $this->callAPISuccess('contact', 'getquick', array(
2410 'field_name' => 'contact_id',
2411 'table_name' => 'cc',
2413 $this->assertEquals(1, $result['count']);
2414 $this->assertEquals('A Bobby, Bobby', $result['values'][0]['sort_name']);
2418 * Test that getquick returns contacts with an exact first name match first.
2420 * Depending on the setting the sort name sort might click in next or not - test!
2422 public function testGetQuickFirstName() {
2423 $this->getQuickSearchSampleData();
2424 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2425 $result = $this->callAPISuccess('contact', 'getquick', array(
2427 'field_name' => 'first_name',
2428 'table_name' => 'cc',
2436 foreach ($expected as $index => $value) {
2437 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2439 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2440 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2441 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2442 $this->assertEquals('A Bobby, Bobby', $result['values'][1]['sort_name']);
2446 * Test that getquick applies ACLs.
2448 public function testGetQuickFirstNameACLs() {
2449 $this->getQuickSearchSampleData();
2450 $userID = $this->createLoggedInUser();
2451 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2452 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
2453 $result = $this->callAPISuccess('contact', 'getquick', array(
2455 'field_name' => 'first_name',
2456 'table_name' => 'cc',
2458 $this->assertEquals(0, $result['count']);
2460 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2461 CRM_Contact_BAO_Contact_Permission
::cache($userID, CRM_Core_Permission
::VIEW
, TRUE);
2462 $result = $this->callAPISuccess('contact', 'getquick', array(
2464 'field_name' => 'first_name',
2465 'table_name' => 'cc',
2467 $this->assertEquals('K Bobby, Bob', $result['values'][1]['sort_name']);
2468 // Without the ACL 9 would be bob@h.com.
2469 $this->assertEquals('I Bobby, Bobby', $result['values'][9]['sort_name']);
2473 * Full results returned.
2474 * @implements CRM_Utils_Hook::aclWhereClause
2476 * @param string $type
2477 * @param array $tables
2478 * @param array $whereTables
2479 * @param int $contactID
2480 * @param string $where
2482 public function aclWhereNoBobH($type, &$tables, &$whereTables, &$contactID, &$where) {
2483 $where = " (email <> 'bob@h.com' OR email IS NULL) ";
2484 $whereTables['civicrm_email'] = "LEFT JOIN civicrm_email e ON contact_a.id = e.contact_id";
2488 * Test that getquick returns contacts with an exact last name match first.
2490 public function testGetQuickLastName() {
2491 $this->getQuickSearchSampleData();
2492 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2493 $result = $this->callAPISuccess('contact', 'getquick', array(
2495 'field_name' => 'last_name',
2496 'table_name' => 'cc',
2504 foreach ($expected as $index => $value) {
2505 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2507 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2508 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2509 $this->assertEquals('Bob, Bob :: bob@bob.com', $result['values'][0]['data']);
2513 * Test that getquick returns contacts by city.
2515 public function testGetQuickCity() {
2516 $this->getQuickSearchSampleData();
2517 $result = $this->callAPISuccess('contact', 'getquick', array(
2519 'field_name' => 'city',
2520 'table_name' => 'sts',
2522 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
2523 $result = $this->callAPISuccess('contact', 'getquick', array(
2525 'field_name' => 'city',
2526 'table_name' => 'sts',
2528 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
2529 $this->assertEquals('C Bobby, Bobby :: Whanganui', $result['values'][1]['data']);
2533 * Set up some sample data for testing quicksearch.
2535 public function getQuickSearchSampleData() {
2537 array('first_name' => 'Bob', 'last_name' => 'Bob', 'external_identifier' => 'abc', 'email' => 'bob@bob.com'),
2538 array('first_name' => 'Bobby', 'last_name' => 'A Bobby', 'external_identifier' => 'abcd'),
2540 'first_name' => 'Bobby',
2541 'last_name' => 'B Bobby',
2542 'external_identifier' => 'bcd',
2543 'api.address.create' => array(
2544 'street_address' => 'Sesame Street',
2545 'city' => 'Toronto',
2546 'location_type_id' => 1,
2550 'first_name' => 'Bobby',
2551 'last_name' => 'C Bobby',
2552 'external_identifier' => 'bcde',
2553 'api.address.create' => array(
2554 'street_address' => 'Te huarahi',
2555 'city' => 'Whanganui',
2556 'location_type_id' => 1,
2559 array('first_name' => 'Bobby', 'last_name' => 'D Bobby', 'external_identifier' => 'efg'),
2560 array('first_name' => 'Bobby', 'last_name' => 'E Bobby', 'external_identifier' => 'hij', 'email' => 'bob@bobby.com'),
2561 array('first_name' => 'Bobby', 'last_name' => 'F Bobby', 'external_identifier' => 'klm'),
2562 array('first_name' => 'Bobby', 'last_name' => 'G Bobby', 'external_identifier' => 'nop'),
2563 array('first_name' => 'Bobby', 'last_name' => 'H Bobby', 'external_identifier' => 'qrs', 'email' => 'bob@h.com'),
2564 array('first_name' => 'Bobby', 'last_name' => 'I Bobby'),
2565 array('first_name' => 'Bobby', 'last_name' => 'J Bobby'),
2566 array('first_name' => 'Bob', 'last_name' => 'K Bobby', 'external_identifier' => 'bcdef'),
2568 foreach ($contacts as $type => $contact) {
2569 $contact['contact_type'] = 'Individual';
2570 $this->callAPISuccess('Contact', 'create', $contact);
2575 * Test get ref api - gets a list of references to an entity.
2577 public function testGetReferenceCounts() {
2578 $result = $this->callAPISuccess('Contact', 'create', array(
2579 'first_name' => 'Testily',
2580 'last_name' => 'McHaste',
2581 'contact_type' => 'Individual',
2582 'api.Address.replace' => array(
2583 'values' => array(),
2585 'api.Email.replace' => array(
2588 'email' => 'spam@dev.null',
2590 'location_type_id' => 1,
2594 'api.Phone.replace' => array(
2597 'phone' => '234-567-0001',
2599 'location_type_id' => 1,
2602 'phone' => '234-567-0002',
2604 'location_type_id' => 1,
2610 //$dao = new CRM_Contact_BAO_Contact();
2611 //$dao->id = $result['id'];
2612 //$this->assertTrue((bool) $dao->find(TRUE));
2614 //$refCounts = $dao->getReferenceCounts();
2615 //$this->assertTrue(is_array($refCounts));
2616 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
2618 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
2619 'id' => $result['id'],
2621 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
2623 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
2624 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
2625 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
2626 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
2627 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
2631 * Test the use of sql operators.
2633 public function testSQLOperatorsOnContactAPI() {
2634 $this->individualCreate();
2635 $this->organizationCreate();
2636 $this->householdCreate();
2637 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
2638 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
2639 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
2640 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
2644 * CRM-14743 - test api respects search operators.
2646 public function testGetModifiedDateByOperators() {
2647 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
2648 $contact1 = $this->individualCreate();
2649 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
2650 CRM_Core_DAO
::executeQuery($sql);
2651 $contact2 = $this->individualCreate();
2652 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
2653 CRM_Core_DAO
::executeQuery($sql);
2654 $contact3 = $this->householdCreate();
2655 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
2656 CRM_Core_DAO
::executeQuery($sql);
2657 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
2658 $this->assertEquals($contacts['count'], 3);
2659 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
2660 $this->assertEquals($contacts['count'], $preExistingContactCount);
2664 * CRM-14743 - test api respects search operators.
2666 public function testGetCreatedDateByOperators() {
2667 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
2668 $contact1 = $this->individualCreate();
2669 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
2670 CRM_Core_DAO
::executeQuery($sql);
2671 $contact2 = $this->individualCreate();
2672 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
2673 CRM_Core_DAO
::executeQuery($sql);
2674 $contact3 = $this->householdCreate();
2675 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
2676 CRM_Core_DAO
::executeQuery($sql);
2677 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
2678 $this->assertEquals($contacts['count'], 3);
2679 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
2680 $this->assertEquals($contacts['count'], $preExistingContactCount);
2684 * CRM-14263 check that API is not affected by search profile related bug.
2686 public function testReturnCityProfile() {
2687 $contactID = $this->individualCreate();
2688 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
2689 $this->callAPISuccess('address', 'create', array(
2690 'contact_id' => $contactID,
2691 'city' => 'Cool City',
2692 'location_type_id' => 1,
2694 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
2695 $this->assertEquals(1, $result['count']);
2699 * CRM-15443 - ensure getlist api does not return deleted contacts.
2701 public function testGetlistExcludeConditions() {
2702 $name = md5(time());
2703 $contact = $this->individualCreate(array('last_name' => $name));
2704 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
2705 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
2706 // We should get all but the deleted contact.
2707 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
2708 $this->assertEquals(2, $result['count']);
2709 // Force-exclude the deceased contact.
2710 $result = $this->callAPISuccess('contact', 'getlist', array(
2712 'params' => array('is_deceased' => 0),
2714 $this->assertEquals(1, $result['count']);
2715 $this->assertEquals($contact, $result['values'][0]['id']);
2719 * Test contact getactions.
2721 public function testGetActions() {
2722 $description = "Getting the available actions for an entity.";
2723 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
2743 $deprecated = array(
2747 foreach ($expected as $action) {
2748 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
2750 foreach ($deprecated as $action) {
2751 $this->assertArrayKeyExists($action, $result['deprecated']);
2756 * Test the duplicate check function.
2758 public function testDuplicateCheck() {
2759 $this->callAPISuccess('Contact', 'create', array(
2760 'first_name' => 'Harry',
2761 'last_name' => 'Potter',
2762 'email' => 'harry@hogwarts.edu',
2763 'contact_type' => 'Individual',
2765 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
2767 'first_name' => 'Harry',
2768 'last_name' => 'Potter',
2769 'email' => 'harry@hogwarts.edu',
2770 'contact_type' => 'Individual',
2774 $this->assertEquals(1, $result['count']);
2775 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
2777 'first_name' => 'Harry',
2778 'last_name' => 'Potter',
2779 'email' => 'no5@privet.drive',
2780 'contact_type' => 'Individual',
2783 $this->assertEquals(0, $result['count']);
2786 public function testGetByContactType() {
2787 $individual = $this->callAPISuccess('Contact', 'create', array(
2788 'email' => 'individual@test.com',
2789 'contact_type' => 'Individual',
2791 $household = $this->callAPISuccess('Contact', 'create', array(
2792 'household_name' => 'household@test.com',
2793 'contact_type' => 'Household',
2795 $organization = $this->callAPISuccess('Contact', 'create', array(
2796 'organization_name' => 'organization@test.com',
2797 'contact_type' => 'Organization',
2799 // Test with id - getsingle will throw an exception if not found
2800 $this->callAPISuccess('Contact', 'getsingle', array(
2801 'id' => $individual['id'],
2802 'contact_type' => 'Individual',
2804 $this->callAPISuccess('Contact', 'getsingle', array(
2805 'id' => $individual['id'],
2806 'contact_type' => array('IN' => array('Individual')),
2809 $this->callAPISuccess('Contact', 'getsingle', array(
2810 'id' => $organization['id'],
2811 'contact_type' => array('IN' => array('Individual', 'Organization')),
2814 $result = $this->callAPISuccess('Contact', 'get', array(
2815 'contact_type' => array('IN' => array('Individual', 'Organization')),
2816 'options' => array('limit' => 0),
2819 $this->assertContains($organization['id'], array_keys($result['values']));
2820 $this->assertContains($individual['id'], array_keys($result['values']));
2821 $this->assertNotContains($household['id'], array_keys($result['values']));
2823 $result = $this->callAPISuccess('Contact', 'get', array(
2824 'contact_type' => 'Household',
2825 'options' => array('limit' => 0),
2828 $this->assertNotContains($organization['id'], array_keys($result['values']));
2829 $this->assertNotContains($individual['id'], array_keys($result['values']));
2830 $this->assertContains($household['id'], array_keys($result['values']));
2834 * Test merging 2 contacts.
2836 public function testMerge() {
2837 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
2838 $mainContact = $this->callAPISuccess('contact', 'create', $this->_params
);
2839 $this->callAPISuccess('contact', 'merge', array('main_id' => $mainContact['id'], 'other_id' => $otherContact['id']));
2840 $contacts = $this->callAPISuccess('contact', 'get', $this->_params
);
2841 $this->assertEquals($otherContact['id'], $contacts['id']);